В допандемическом 2020 Брайан Браун отправился на неделю в Recurse Center и разработал Checkboxland. Эта библиотека JavaScript отображает текст и анимацию на сетке флажков. 

К забавному маленькому проекту автор сделал несколько демонстраций, написал об этом, а в итоге положил проект на полку и не прикасался к нему около года. В конце концов, отчаянно захотелось развлечься с программированием, и автор снова взялся за Checkboxland. Хотелось сделать более качественную и сложную анимацию, поэтому всё началось с эффекта пульсации — и зацепило. Да, на КДПВ вы видите кадр из видео на чекбоксах.

Пока у нас начинается курс по Frontend-разработке, делимся сразу двумя материалами о чекбоксах.


Математические анимации

Анимация пульсации. Более подробную информацию см. в моей статье о пульсациях https://www.bryanbraun.com/2021/04/15/ripple-animation-in-javascript/
Анимация пульсации. Более подробную информацию см. в моей статье о пульсациях https://www.bryanbraun.com/2021/04/15/ripple-animation-in-javascript/

Создание пульсации заставило меня углубиться в математику анимации. Вскоре я понял, что могу использовать подобные приёмы для создания других анимаций, в том числе этих:

Когда я показывал кому-то анимацию, подобную этой, люди часто пытались нажать на флажки, чтобы посмотреть, что произойдёт. Нажатие ничего не давало — анимация просто отменяла их клики, что весьма разочаровывало, поэтому я захотел сделать анимацию с реакцией на нажатия.

Интерактивные анимации

«Лазер»-анимация. Попробуйте здесь https://www.bryanbraun.com/checkboxland/docs/demos/lasers/
«Лазер»-анимация. Попробуйте здесь https://www.bryanbraun.com/checkboxland/docs/demos/lasers/
Анимация «пульс». Попробуйте здесь: https://www.bryanbraun.com/checkboxland/docs/demos/pulse/
Анимация «пульс». Попробуйте здесь: https://www.bryanbraun.com/checkboxland/docs/demos/pulse/

Чем больше интерактивных демонстраций я делал, тем больше идей у меня возникало. Я могу создавать игры! Змейку, пинг-понг, тетрис! Но, прежде чем я слишком далеко продвинулся по этому пути, меня посетила новая мысль.

Если бы я мог отобразить любое изображение, то мне не пришлось бы проходить через трудоёмкий процесс определения каждого флажка вручную или придумывать алгоритм для нужной мне сцены.

Изображения

Преобразование изображений казалось сложной задачей, поэтому я долго откладывал её, пока не наткнулся на эту замечательную статью о преобразовании изображений в ASCII-текст. Через какое-то время я конвертировал изображения:

Вскоре я понял, что конвертирование изображений — это 90% пути к конвертированию видео. И вот результат.

Видео

Видео в формате mp4 (слева) служит основой для анимации флажка (справа). Попробуйте другие видео или загрузите своё https://www.bryanbraun.com/checkboxland/docs/demos/video-test/
Видео в формате mp4 (слева) служит основой для анимации флажка (справа). Попробуйте другие видео или загрузите своё https://www.bryanbraun.com/checkboxland/docs/demos/video-test/

Вскоре я расширил API Checkboxland, чтобы можно было загружать любое видео (например, из giphy или gifer) и мгновенно генерировать версию с флажками. Анимация флажками стала тривиальной.

Это означает, что я могу отображать данные с веб-камеры, что привлекло много внимания в Twitter:

Наконец, мой коллега Рид рассказал мне о задаче, где люди пытаются воспроизвести анимационный ролик «Bad Apple» на разных непонятных вычислительных средах (см. кучу примеров здесь). Это прозвучало забавно, поэтому я пошёл и записал видео на Youtube.

Весь этот процесс был интересным, но мне действительно пора остановиться.

Я был ранен проектом прямо в голову, бросил из-за него всё. Конечно, это безобидное развлечение, но я начинаю чувствовать вину за то, что трачу месяцы на возню с этими вещами, когда у меня есть инструменты и навыки, чтобы выпустить нечто действительно полезное.

Я ощущаю себя Суперменом, использующим сверхспособности, чтобы поджарить яйцо. Если я продолжу в том же духе, то стану известен как «парень с галочкой». Это не слишком продаваемо, но, думаю, бывает ещё хуже.

К счастью, кажется, я начинаю исчерпывать все интересные идеи, которые мог бы сделать в этом формате. Иногда это выглядит как «чувак, мы поняли, ты можешь сделать что угодно с флажками».

У меня есть ешё несколько затянувшихся в реализации идей, хотя… быть может, это как управляемый лесной пожар, и я должен просто позволить себе продолжать делать это всё, пока идеи не перегорят сами собой.

Пока автор решает, что делать с идеями, вы можете начать изучение фронтенда или просто прочитать следующий материал.


Пять приёмов стилизации чекбоксов

Оригинал. Автор: Preethi

Мы могли бы оставить без стилизации поле ввода текста или ссылку, даже кнопку. Но чекбоксы... нет, мы не оставим их в покое. И, хотя дизайн чекбоксов не так сложен, мы не должны ограничиваться сменой цвета фона или добавлением/удалением рамок, чтобы обозначать изменения состояния. И нам не нужны какие-то особые навыки дизайна (которыми мы не обладаем), чтобы всё это работало.

Начинаем

В следующих демо почти у всех чекбоксов трёхуровневая компоновка: внизу чекбокс, а сверху — два элемента или псевдоэлемента. От того, какой из них виден, зависит состояние чекбокса, то есть отмечен он или нет.

Посмотрите на CSS-код в pen: все макеты там (в том числе для чекбоксов) — это гриды. Попробуйте другие варианты, подходящие для вашего случая, и узнайте больше в гайде по CSS Grid. Дополнительные замечания по коду и альтернативам дизайна — в конце исходного кода внутри pen.

В любых элементах, находящихся поверх чекбокса, есть свойство pointer-events: none, поэтому они не затрудняют нажатие на чекбокс.

И вот первый метод стилизации.

1. Смешанные фоны как состояние чекбокса

Смешивание — универсальный метод CSS. Манипулирование цветами двух и более элементов или фонов удобно в неожиданных контекстах, в том числе для чекбоксов:

<input id="un" type="checkbox"> <label for="un">un</label>
<!-- more checkboxes --> 
input[type=checkbox]::before,
input[type=checkbox]::after {
  mix-blend-mode: hard-light;
  pointer-events: none;
  /* more style */
}
input[type=checkbox]::before {
  background: green;
  content: '✓';
  color: white;
  /* more style */
}
input[type=checkbox]::after {
  background: blue;
  content: '⨯';
  /* more style */
}
input[type=checkbox]:checked::after {
  mix-blend-mode: unset;
  color: transparent;
}

Здесь расположенные один под другим псевдоэлементы стилизованы зелёным и синим, каждому присвоено значение mix-blend-mode. Это значит, что фон каждого элемента сливается с фоном за ним.

Задействовано значение hard-light, которое имитирует multiply или screen в зависимости от того, темнее или светлее верхний цвет. Подробнее о различных режимах смешивания можно прочитать на MDN. Когда чекбокс отмечен галочкой, значение mix-blend-mode псевдоэлемента ::after не задано и визуальное отображение несколько иное.

2. 3D-анимация

Анимировать цветные блоки — отличная идея. Сделаем их, как в 3D: так будет ещё эффектнее. В CSS есть средства визуализации элементов в эмулируемом 3D-пространстве. Используя их, создаём 3D-чекбокс и поворачиваем его, чтобы обозначить изменение состояния:

<div class="c-checkbox">
  <input type="checkbox" id="un">
  <!-- cube design -->
  <div><i></i><i></i><i></i><i></i></div>
</div>
<label for="un">un</label>
<!-- more checkboxes -->
.c-checkbox > div {
  transition: transform .6s cubic-bezier(.8, .5, .2, 1.4);
  transform-style: preserve-3d;
  pointer-events: none;
  /* more style */
}
/* front face */
.c-checkbox > div > i:first-child {
  background: #ddd;
  transform:  translateZ( -10px );
}
/* back face */
.c-checkbox > div > i:last-child {
  background: blue;
  transform:  translateZ( 10px );
}
/* side faces */
.c-checkbox > div > i:nth-of-type(2),
.c-checkbox > div > i:nth-of-type(3) {
  transform: rotateX(90deg)rotateY(90deg);
  position: relative;
  height: 20px;
  top: 10px;
}
.c-checkbox > div > i:nth-of-type(2) {
  background: navy;
  right: 20px;
}
.c-checkbox > div > i:nth-of-type(3) {
  background: darkslategray;
  left: 20px;
}

<div> становится контейнером 3D-пространства — его дочерние элементы располагаются вдоль осей x, y и z — после того, как задаётся transform-style: preserve-3d.

Используя свойство transform, размещаем два элемента <i> (серого и синего цвета) на оси z на некотором расстоянии друг от друга. А ещё два — между ними, покрывая левую и правую стороны. Это как картонная коробка, у которой сверху и снизу нет граней.

Когда чекбокс отмечен галочкой, серо-синяя коробка вращается. Вращение анимируется добавлением transition к <div>:

input:checked + div { 
  transform: rotateY( 180deg ); 
}

3. Изменение радиуса границы

Поменяем не только радиус границы чекбокса, отмеченного галочкой, но и радиусы границ соседних чекбоксов:

<input type="checkbox" id="un"> <label for="un">un</label>
<!-- more rows of checkboxes -->
input {
  background: #ddd;
  border-radius: 20px;
  /* more style */
}
input:not(:first-of-type)::before {
  content: '';    
  transform: translateY(-60px); /* move up a row */
  pointer-events: none;
}
input:checked + * + input::before,
input:last-of-type:checked {
  border-radius: 20px;
  background: blue;
}
input:checked + * + input:checked + * + input::before {
  border-top-left-radius: unset !important;
  border-top-right-radius: unset !important;
}
input:checked::before {
  border-bottom-left-radius: unset !important;
  border-bottom-right-radius: unset !important;
}
/* between the second-last and last boxes */ 
input:nth-of-type(4):checked + * + input:checked {
  border-top-left-radius: unset;
  border-top-right-radius: unset;
}

При нажатии на чекбокс меняются не только его собственные границы, но и границы чекбоксов до и после него.

Здесь нет селекторов, выбирающих предыдущие элементы, — только последующие. Для управления внешним видом предыдущего чекбокса используется его псевдоэлемент. Все чекбоксы, кроме первого, получают псевдоэлементы, которые перемещаются в верхнюю часть предыдущего чекбокса. Теперь предположим, что чекбоксы A, B и C расположены один за другим:

  • Нажав на B, можно изменить внешний вид A, стилизуя псевдоэлемент B.

  • Так же, стилизуя псевдоэлемент C, можно изменить внешний вид B,

  • внешний вид C можно изменить, стилизуя псевдоэлемент D.

  • Из элемента B доступны псевдоэлементы B, C и D, пока между ними в компоновке используется селектор следующего элемента.

Четыре угла каждого чекбокса изначально закруглены, когда чекбокс не отмечен. Но когда чекбокс отмечен, верхние углы следующего чекбокса и нижние предыдущего выпрямляются (посредством переопределения и удаления их граничных радиусов).

4. CSS-маска

Тумблеры и переключатели тоже можно выполнить как чекбоксы, которые стилизуются с помощью CSS-маски. Это техника, где для фильтрации части фона используется изображение:

<input type="checkbox">
<div class="skin one"></div>
<div class="skin two"></div>
.one.skin {
  background: no-repeat center -40px url('photo-1584107662774-8d575e8f3550?w=350&q=100');
}
.two.skin {
  background: no-repeat center -110px url('photo-1531430550463-9658d67c492d?w=350&q=100');
  --mask: radial-gradient(circle at 45px 45px , rgba(0,0,0,0) 40px, rgba(0,0,0,1) 40px);
  mask-image: var(--mask); -webkit-mask-image: var(--mask);
}

Оба элемента класса skin, которые отображают пейзажные фотографии, расположены поверх чекбокса. Самый верхний получает mask-image в виде обычного тумблера — это прозрачный круг слева, а оставшаяся часть имеет полностью прозрачный цвет. Сквозь прозрачный круг видно фото, оставшееся изображение маски показывает фото наверху.

При нажатии на чекбокс прозрачный круг перемещается вправо и изображение вверху видно через круг; оставшаяся часть показывает фото внизу:

input:checked ~ .two.skin {
  --mask: radial-gradient(circle at 305px 45px, rgba(0,0,0,1) 40px, rgba(0,0,0,0) 40px);
  mask-image: var(--mask); -webkit-mask-image: var(--mask);
}

5. Приём с box-shadow

В заключение — нечто самое простое, но и, на мой взгляд, самое эффектное — анимированная вставка box-shadow:

<input id="un" type="checkbox"> <label for="un">un</label>
input {
  transition: box-shadow .3s;
  background: lightgrey;
  /* more style */
}
input:checked { 
  box-shadow: inset 0 0 0 20px blue;
}

Одно из свойств CSS, которое можно анимировать по умолчанию — box-shadow. Оно хорошо сочетается с минимализмом.

Вот и всё на сегодня. Прокачать навыки или начать освоение фронтенда с чистого листа вы можете на наших курсах:

Также вы можете перейти на страницы курсов из каталога, чтобы увидеть, как мы готовим специалистов в других направлениях.

Профессии и курсы

Комментарии (2)


  1. ZhilkinSerg
    11.10.2021 23:12

    Это все сильно медленнее попиксельного рисования?


  1. LaRN
    14.10.2021 08:41

    Месье знает толк в извращения :)

    Вот интересно, можно ли сюда прикрутить двойную буферизацию. Т.е. рисуешь на одном div невидимой, потом включаешь ему видимость, и рисуешь на втором. В следующем кадре они меняются местами. По идее гладкость анимации должна стать повыше.