
В этом уроке, мы разберемся как создавать различные эффекты анимации при помощи CSS3. Несколько важных моментов, прежде чем мы начнем:
Вы не увидите никаких префиксов в CSS фрагментах, но вы, конечно же, найдете их в ресурсных файлах.
Цель этого урока, это показать потенциал CSS, а особенно CSS3, поэтому рендеринг может быть изменен на-IE9. Если вы планируете поддерживать эти браузеры, не забудьте сделать резервные варианты.
Мы будем использовать box-model, где [width]= [element-width] + [padding]+ [borders]. Мы активируем их с следующим фрагментом:
*,
*:before,
*:after {
box-sizing: border-box;
}CSS: За и Против
Каковы преимущества и недостатки чистого эффекта CSS “загрузки” и “предварительной загрузки”? Почему не JavaScript код, или даже старый добрый способ: анимированный GIF? Нет универсального ответа на этот вопрос, все будет зависеть от ситуации. Но позвольте нам дать вам некоторые идеи:
За:
- CSS легко редактируемый: вы можете быстро изменить длительность, скорость, цвет и т.д. вашей анимации
- CSS является “вектроным”: вы можете масштабировать его по своему усмотрению без потери качества
- CSS анимации быстрее, чем JS “анимации”, так как они используют родной двигатель браузера
- CSS анимации используют GPU ускорение: если у вас есть хорошее устройство, то тогда у вас будет очень быстрая и плавная анимация
Против:
- У CSS анимации нет полной поддержки браузера: IE9 и Opera Mini не понимают их
- CSS (pre) загрузчики могут включать объемные разметки
- CSS немогут активировать экшнс на нажатие мышкой и тд., в отличие от JS
Пример 1

Мы начнем с чего-нибудь простого. Наш ползунок бесконечно бегает в окне слева направо. “Движение” является очень важным, для того чтобы пользователь видел, что приложение/сайт действительно что-то делает.
Разметка
<div class="bar"> <i class="sphere"></i> </div>
CSS
Во-первых, нам нужно создать контейнер для сферы: bar. Чтобы сохранить пропорции и сделать призагрузчики масштабируемыми, мы использовали em единицы. Просто измените значение размера шрифта на обертке, для того чтобы все масштабировалось так, как вы хотите.
.demo-1 .bar {
/* Size and position */
font-size: 20px; /* 1em */
width: 10em;
height: 1em;
position: relative;
margin: 100px auto;
/* Styles */
border-radius: .5em; /* Height/2 */
background: white; /* Fallback */
background: rgba(255,255,255,0.6);
box-shadow:
0 0 0 .05em rgba(100,100,100,0.075), /* Subtle border */
0 0 0 .25em rgba(0,0,0,0.1), /* Outter border */
inset 0 .1em .05em rgba(0,0,0,0.1), /* Inset shadow */
0 .05em rgba(255,255,255,0.7); /* Slight reflection */
}Давайте займёмся “Подождите”. Вы, наверное, заметили, что его нету в разметке: это потому, что это контент. На самом деле он должен быть в разметке в реальном случае, так как это важное содержание, а не только графический материал.
.demo-1 .bar:after {
/* Content and position */
content: "Подождите.";
position: absolute;
left: 25%;
top: 150%;
/* Font styles */
font-family: 'Carrois Gothic', sans-serif;
font-size: 1em;
color: #555;
text-shadow: 0 .05em rgba(255,255,255,0.7);
}Теперь давайте взглянем на сферу.
.demo-1 .sphere {
/* Size */
display: block;
width: 1em;
height: 100%;
/* Styles */
border-radius: 50%;
background: linear-gradient(#eee, #ddd);
box-shadow:
inset 0 .15em .1em rgba(255,255,255,0.3), /* Top light */
inset 0 -.1em .15em rgba(0,0,0,0.15), /* Bottom shadow */
0 0 .25em rgba(0,0,0,0.3); /* Outter shadow */
/* Animation */
animation: move 1.75s ease-in-out infinite alternate;
}Ключевые фреймы запускающие анимации:
@keyframes move {
to { margin-left: 90%; }
}Пример 2

Теперь давайте продолжим с чем-то немного посложнее, но не слишком! Вращающаяся … мельница? :)
Разметка
Этот пример полностью основан на псевдо-элементе. Полностью. Нет необходимости в дополнительной разметке.
<div class="spinner"></div>
CSS
Во-первых, сам элемент. Мы использовали красный и бежевый, но вы можете выбрать любой понравившийся вам цвет. То же самое касается количества цветов, мы взяли два, но вы можете пойти с четырьмя, или только одним, или любым другим количеством.
.demo-2 .spinner {
/* Size and position */
font-size: 100px; /* 1em */
width: 1em;
height: 1em;
position: relative;
margin: 100px auto;
/* Styles */
border-radius: 50%;
background: #FF4F72; /* Fallback */
background:
linear-gradient(#ea2d0e 50%, #fcd883 50%), /* First column */
linear-gradient(#fcd883 50%, #ea2d0e 50%); /* Second column */
background-position:
0 0, /* Position of 1st column */
100% 0; /* Position of 2nd column */
background-size: 50% 100%; /* Contraction of "50% 100%, 50% 100%" */
background-repeat: no-repeat;
box-shadow:
inset 0 0 0 .12em rgba(0,0,0,0.2), /* Inner border */
0 0 0 .12em rgba(255,255,255,0.1); /* Outter border */
opacity: 0.7;
animation: rota 3s infinite alternate;
}Теперь, псевдо-элемент для внутреннего прозрачного белого круга.
.demo-2 .spinner:after {
/* Size */
content: "";
width: 50%;
height: 50%;
/* Perfect centering */
position: absolute;
top: 25%;
left: 25%;
/* Styles */
border: .12em solid rgba(255,255,255,0.3);
border-radius: inherit;
}Анимация
@keyframes rota {
25% { transform: rotate(270deg); }
50% { transform: rotate( 90deg); }
75% { transform: rotate(360deg); }
100% { transform: rotate(180deg); }
}Пример 3

Теперь давайте рассмотрим что-то немного сложнее. Но не волнуйтесь, это действительно не так сложно.
Разметка
HTML для этого варианта не самый красивый. Поскольку мы не можем анимировать псевдо-элементы, мы должны использовать несколько элементов, чтобы это сделать. Мы выбрали списки (даже если они не очень семантические), но вы можете выбрать все, что захотите.
<ul class="spinner">
<li></li>
<li></li>
<li></li>
<li></li>
</ul>CSS
Первое, что нужно сделать, это стилизовать сам список.
.demo-3 .spinner {
/* Size and position */
font-size: 100px; /* 1em */
width: 1em;
height: 1em;
margin: 100px auto;
position: relative;
/* Styles */
list-style: none;
border-radius: 50%;
border: .01em solid rgba(150,150,150,0.1); /* Subtle white line circling the dots */
}И общие свойства для всех элементов списка.
.demo-3 .spinner li {
width: .2em;
height: .2em;
position: absolute;
border-radius: 50%;
}А теперь, несколько объяснений о том, что грядет. При загрузке страницы, четыре точки не будут перекрывать друг друга, они расположены как стороны света: север, юг, восток, запад. Но, их центры вращения все в одном и том же месте – в точном центре спиннера.
.demo-3 .spinner li:nth-child(1) {
background: #00C176; /* Blue */
top: 0;
left: 50%;
margin-left: -.1em; /* Width/2 */
transform-origin: 50% 250%;
animation:
rota 1.13s linear infinite,
opa 3.67s ease-in-out infinite alternate;
}
.demo-3 .spinner li:nth-child(2) {
background: #FF003C; /* Red */
top: 50%;
right: 0;
margin-top: -.1em; /* Height/2 */
transform-origin: -150% 50%;
animation:
rota 1.86s linear infinite,
opa 4.29s ease-in-out infinite alternate;
}
.demo-3 .spinner li:nth-child(3) {
background: #FABE28; /* Yellow */
bottom: 0;
left: 50%;
margin-left: -.1em; /* Width/2 */
transform-origin: 50% -150%;
animation:
rota 1.45s linear infinite,
opa 5.12s ease-in-out infinite alternate;
}
.demo-3 .spinner li:nth-child(4) {
background: #88C100; /* Green */
top: 50%;
left 0;
margin-top -.1em; /* Height/2 */
transform-origin: 250% 50%;
animation:
rota 1.72s linear infinite,
opa 5.25s ease-in-out infinite alternate;
}Наконец, две анимации. Одна предназначена для вращения, а другая для прозрачности. Да, прозрачность здесь меняется тоже!
@keyframes rota {
to { transform: rotate(360deg); }
}
@keyframes opa {
12.0% { opacity: 0.80; }
19.5% { opacity: 0.88; }
37.2% { opacity: 0.64; }
40.5% { opacity: 0.52; }
52.7% { opacity: 0.69; }
60.2% { opacity: 0.60; }
66.6% { opacity: 0.52; }
70.0% { opacity: 0.63; }
79.9% { opacity: 0.60; }
84.2% { opacity: 0.75; }
91.0% { opacity: 0.87; }
}Пример 4

Разметка
Довольно тяжелый случай, так как нам нужно обернуть каждую букву на спан. Также, нам нужна обертка для отмены вращения основного элемента.
<div class="wrapper">
<div class="inner">
<span>L</span>
<span>o</span>
<span>a</span>
<span>d</span>
<span>i</span>
<span>n</span>
<span>g</span>
</div>
</div>CSS
Во-первых, у нас есть много вещей, которые нужно применить к основному элементу: размер, положение, шрифт, анимация и т.д.
.demo-4 .wrapper {
/* Size and position */
font-size: 25px; /* 1em */
width: 8em;
height: 8em;
margin: 100px auto;
position: relative;
/* Styles */
border-radius: 50%;
background: rgba(255,255,255,0.1);
border: 1em dashed rgba(138,189,195,0.5);
box-shadow:
inset 0 0 2em rgba(255,255,255,0.3),
0 0 0 0.7em rgba(255,255,255,0.3);
animation: rota 3.5s linear infinite;
/* Font styles */
font-family: 'Racing Sans One', sans-serif;
color: #444;
text-align: center;
text-transform: uppercase;
text-shadow: 0 .04em rgba(255,255,255,0.9);
line-height: 6em;
}Мы все еще должны создать внутренние колеса с псевдо-элементами.
.demo-4 .wrapper:before,
.demo-4 .wrapper:after {
content: "";
position: absolute;
z-index: -1;
border-radius: inherit;
box-shadow: inset 0 0 2em rgba(255,255,255,0.3);
border: 1em dashed;
}
.demo-4 .wrapper:before {
border-color: rgba(138,189,195,0.2);
top: 0; right: 0; bottom: 0; left: 0;
}
.demo-4 .wrapper:after {
border-color: rgba(138,189,195,0.4);
top: 1em; right: 1em; bottom: 1em; left: 1em;
}Теперь внутренние обертки и спаны. Обратите внимание, как мы используем “reverse” параметр на внутреннем контейнере для отмены вращения основного элемента.
.demo-4 .wrapper .inner {
width: 100%;
height: 100%;
animation: rota 3.5s linear reverse infinite;
}
.demo-4 .wrapper span {
display: inline-block;
animation: placeholder 1.5s ease-out infinite;
}
.demo-4 .wrapper span:nth-child(1) { animation-name: loading-1; }
.demo-4 .wrapper span:nth-child(2) { animation-name: loading-2; }
.demo-4 .wrapper span:nth-child(3) { animation-name: loading-3; }
.demo-4 .wrapper span:nth-child(4) { animation-name: loading-4; }
.demo-4 .wrapper span:nth-child(5) { animation-name: loading-5; }
.demo-4 .wrapper span:nth-child(6) { animation-name: loading-6; }
.demo-4 .wrapper span:nth-child(7) { animation-name: loading-7; }К сожалению, нам нужна одна анимация для каждой буквы, так как они должны идти с задержкой. Сначала мы думали об анимации с задержкой, но это свойство только делает задержку при первом запуске, а не при каждом, поэтому такой способ работать не будет.
@keyframes rota {
to { transform: rotate(360deg); }
}
@keyframes loading-1 {
14.28% { opacity: 0.3; }
}
@keyframes loading-2 {
28.57% { opacity: 0.3; }
}
@keyframes loading-3 {
42.86% { opacity: 0.3; }
}
@keyframes loading-4 {
57.14% { opacity: 0.3; }
}
@keyframes loading-5 {
71.43% { opacity: 0.3; }
}
@keyframes loading-6 {
85.71% { opacity: 0.3; }
}
@keyframes loading-7 {
100% { opacity: 0.3; }
}Эти анимациии может быть немного сложно понять, поэтому давайте разберемся, каждая буква должна:
- Потерять немного непрозрачности
- Вернуться к полной непрозрачности
- Подождите, пока все остальные буквы сделают тоже самое
- Вернитесь к шагу 1 и повторите
Как конкретно это сделать:
- Вы посчитали количество букв в своем элементе. Наш демо насчитывает 7
- Вы разделили 100 (количество ключевых кадров, выраженных в %) на это число. В этом примере оно равно ~ 14,28
- Каждый 14,28 ключевой кадр, буква делает свое дело
- Готово
Как видите, все примеры достаточно просты в использовании.
Высоких конверсий!





