Теория

Хотя заголовок этого раздела и намекает на рулоны сплошного текста, заниматься мы этим не будем. Нужно лишь уяснить несколько базовых понятий, которые нам понадобятся при создании того, ради чего и писалась эта статья. Теории будет мало, в основном примеры, поэтому не поленитесь её прочитать. Это полезно. Итак, наконец-то приступим.

Псевдоэлементы

Псевдоэлементы

Псевдоэлемент — это дополнительный внутренний элемент, созданный с помощью CSS.

Псевдоэлементов в CSS не так много, нам пригодится лишь два из них: :before и :after.

Добавление контента перед содержимым элемента

Псевдоэлемент :before применяется для отображения какого-либо контента до содержимого самого элемента, к которому он добавляется.

Внимание

Хочу напомнить, что для более тщательного рассмотрения примера, можно перейти на сайт JSFiddle кликнув по ссылке "Edit in JSFiddle" или их логотипу.

Пример — Добавление префикса параграфу.

Добавление контента после содержимого элемента

Псевдоэлемент :after применяется для отображения какого-либо контента после содержимого самого элемента, к которому он добавляется.

Пример — Добавление напоминания в виде звездочки об обязательном для заполнения поле.

Покадровая анимация в CSS

Правило @keyframes позволяет пользователю описать анимацию CSS-свойств в виде перечня ключевых кадров.

@keyframes <название> {
  <селектор кадра 1> {
    <свойство 1>:<значение 1>;
  }
  ...
  <селектор кадра n> {
    <свойство 1>:<значение 1>;
  }
}

Пример — Анимация вращения элемента.

Практика

Базовая разметка

Создадим базовую разметку:

<!-- Checkboxes -->
<label class="label">
  <input type="checkbox">
  <span class="label-text">Checkbox #1</span>
</label>
<!-- Radio -->
<label class="label">
  <input type="radio">
  <span class="label-text">Radio #1</span>
</label>

Добавим немного базовых стилей:

.form-label {
  cursor: pointer;
  color: #333;
}

Фейковый элемент

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

Для этого сначала мы должны скрыть основной:

.form-label > input[type="checkbox"],
.form-label > input[type="radio"] {
  display: none;
}

На этом этапе мы не понимаем какой это элемент, активирован ли он и что он вообще делает.

Поэтому нам нужно добавить новую иконку для элементов. Именно для этого нам понадобятся псевдоэлементы.

Я буду использовать шрифт Font Awesome, в котором полно разнообразных иконок, но это не значит, что вы не можете использовать, допустим, картинку, текст или свой иконочный шрифт — главное, чтобы это работало с CSS-свойством content.

Для использования шрифта Font awesome необходимо сначала его подключить. Делается это двумя способами:

В CSS:

@import "https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css"

В HTML:

<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">

Советую подключать шрифт через HTML. Однако в этом примере, так как используется сервис JSFiddle, я буду подключать шрифт через CSS.

Создаём псевдоэлемент перед текстом элемента и задаём ему такие стили:

.form-label > input[type="checkbox"] + .label-text:before,
.form-label > input[type="radio"] + .label-text:before {
  font-family: "FontAwesome";
  font-style: normal;
  font-weight: normal;
  font-variant: normal;
  text-transform: none;
  line-height: 1;
  width: 1em;
  display: inline-block;
  margin-right: 5px;
}

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

Далее мы должны указать какие иконки нужно использовать. Делается это с помощью CSS-свойства content.

Для чекбокса это будет:

/* Checkbox */
.form-label > input[type="checkbox"] + .label-text:before {
  content: "\f096";
}

Для радио кнопки:

/* Radio */
.form-label > input[type="radio"] + .label-text:before {
  content: "\f10c";
}

Сейчас наши элементы выглядят вот так:

Сколько на них не нажимай, визуально состояния они не изменяют. Нужно это исправить. Используем для этого давно известные нам псевдоклассы, в данном случае :checked.

/* Checkbox */
.form-label > input[type="checkbox"] + .label-text:before { content: "\f096"; }
.form-label > input[type="checkbox"]:checked + .label-text:before { content: "\f14a"; }

/* Radio */
.form-label > input[type="radio"] + .label-text:before { content: "\f10c"; }
.form-label > input[type="radio"]:checked + .label-text:before { content: "\f192"; }

Выглядит, конечно, громоздко. Зато элементы теперь меняют своё состояние:

Венцом нашего творения будет запрет на выделение:

.form-label > .label-text {
  user-select: none;
}

Анимация

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

Во-первых, нам нужно обозначить ключевые кадры:

@keyframes tick {
  0% {
    transform: scale(0);
  }
  90% {
    transform: scale(1.4);
  }
  100% {
    transform: scale(1);
  }
}

С помощью свойства transform мы увеличиваем размер нашей иконки от 0 до 1.4 реального размера, а потом уменьшаем с 1.4 до 1.

Добавим вызов анимации в уже имеющийся CSS код. Делается это очень просто:

.form-label > input[type="checkbox"]:checked + .label-text:before {
  content: "\f14a";
  animation: tick .2s ease-in-out;
}

.form-label > input[type="radio"]:checked + .label-text:before {
  content: "\f192";
  animation: tick .2s ease-in-out;
}

Свойство animation — это короткая запись свойств: animation-name, animation-duration и animation-timing-function.

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

Классно! В итоге получаем отлично работающий пример.

Разумеется, можно использовать и другие эффекты, например, что-то из библиотеки Animate.css, хотя мне сложно представить это :)

Удачной анимации, друзья!