От автора: творческие эксперименты с применением анимации и переходов к псевдоэлементам для создания интересных эффектов.
Сегодня мы собираемся поэкспериментировать с анимацией и переходами применительно к псевдоэлементам (:before и :after) и раскрыть их потенциал. Мы немного поговорим об анимации псевдоэлементов и рассмотрим четыре примера, где применяются специальные техники достижения многих эффектов. Сначала давайте рассмотрим преимущества и недостатки применения к псевдоэлементам анимации и переходов.
ПРЕИМУЩЕСТВА
Упрощение и оптимизация разметки HTML
Использование возможностей CSS3
Внесение определенного вклада в дизайн
НЕДОСТАТКИ
Поддержка только современных браузеров типа Firefox, IE10 и, последнее время, Chrome (для информации смотрите обновленную таблицу поддержки)
Пока не работает в мобильных браузерах
Псевдоэлементы нельзя идентифицировать по ID
Псевдоэлементы не появляются в DOM.
Понятно, что недостатков больше, чем преимуществ, но я считаю, что следует подумать о будущем и дать им шанс!
Следующие четыре примера были созданы специально для этой статьи. Конечно, существуют прочие способы добиться тех же визуальных эффектов, но ради этого эксперимента мы, естественно, используем псевдоэлементы, так что помните, что они работают только в браузерах, поддерживающих их анимацию и переходы.
Пожалуйста, обратите внимание:
В этом учебнике мы пропустим вендорные префиксы, но вы обнаружите их в файлах для скачивания.
В примерах мы в основном будем применять свойство box-shadow и единицы EM.
Очень интересный факт: псевдоэлементы наследуют свойства от своего родительского элемента. В случае с анимацией все изменения действуют на них напрямую. Это будет удобно, если понадобится увеличить до максимума их поддержку. Чтобы узнать об этом еще больше, прочтите Примените переходы CSS к псевдоэлементам прямо сейчас (Use CSS transitions for pseudo-elements right now)Романа Комарова.
Давайте начнем!
ПРИМЕР 1
Сначала нужно сделать забавную штуку: анимацию водной капли, падающей в закругленный контейнер (на основе логотипа Codrops)
Разметка
1 |
<div class="drop"></div> |
У нас всего один элемент, хотя у него мог быть контейнер, помогающий изменять уровень.
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
*, *:before, *:after { box-sizing: border-box; } .drop { background: rgba(255, 255, 245, 1); border: 4px solid rgba(255, 245, 235, 1); border-radius: 100%; box-shadow: inset -0.1em 0 2em 0.5em rgba(255, 255, 255, 0.5), inset -0.1em 0 0.5em 0 rgba(0, 0, 0, 0.8); position: relative; margin: 0 auto; width: 15em; height: 15em; overflow: hidden; } .drop:before, .drop:after { content:""; display:block; position:absolute; } /* Капля */ .drop:before { background: rgba(167, 217, 234, 1); border-radius: 100%; /* Начало капели */ box-shadow: 0 0 0 0.1em rgba(167, 217, 234, 0.8), 0 0 0 0.15em rgba(167, 217, 234, 0.8), 0 0 0 0.2em rgba(167, 227, 234, 0.8), 0 0 0 0.25em rgba(167, 227, 234, 0.8), 0 0 0 0.3em rgba(167, 227, 234, 0.8), 0 0 0 0.35em rgba(167, 227, 234, 0.8), 0 0 0 0.4em rgba(167, 227, 234, 0.8), 0 0 0 0.45em rgba(167, 227, 234, 0.8), 0 0 0 0.5em rgba(167, 227, 234, 0.8); top: 0%; left: 50%; /*Ширина "width" и высота "height" деления должны быть меньше общего размера "box-shadow". Так мы сможем контролировать различные типы размеров. */ width: 0.2em; height: 0.2em; animation: fall 3.5s cubic-bezier(0.5, 0, 1, 0.5) infinite; } /* Поверхность */ .drop:after { background: rgb(52, 152, 219); background: linear-gradient(rgba(52, 255, 255, 1) 0%, rgba(52, 152, 219, 1) 10%, rgba(152, 252, 219, 1) 100%); border-radius: 100% 0 50% 0; left: 0; bottom: 0; width: inherit; height: 3em; opacity: 0.7; animation: surface 3s linear infinite; } /* Анимация капели */ @keyframes fall { /* Форма капли */ 5%, 15% { box-shadow: 0 -1.4em 0 0.1em rgba(167, 217, 234, 1), 0 -0.8em 0 0.15em rgba(167, 217, 234, 1), 0 -0.3em 0 0.2em rgba(167, 217, 234, 1), 0 -0.1em 0 0.25em rgba(167, 217, 234, 1), 0 0 0 0.3em rgba(167, 217, 234, 1), 0 0.2em 0 0.35em rgba(167, 217, 234, 1), 0 0.4em 0 0.4em rgba(167, 217, 234, 1), 0 0.6em 0 0.45em rgba(167, 217, 234, 1), 0 0.8em 0 0.5em rgba(167, 217, 234, 1); } /* Падение капли */ 16% { top: 80%; } /* Контакт с поверхностью */ 18% { top: 80%; box-shadow: 1em -8em 0 0.2em rgba(177, 227, 234, 1), -2.2em -3.8em 0 0.1em rgba(177, 227, 234, 1), 3em -2.85em 0 0.3em rgba(177, 227, 234, 1), -3.5em -4em 0 0.2em rgba(177, 227, 234, 1), 0 0 0 0.3em rgba(177, 227, 234, 1), 2em -2em 0 0.2em rgba(177, 227, 234, 1), -0.3em -3em 0 0.2em rgba(177, 227, 234, 1), 0.5em -5em 0 0.35em rgba(177, 227, 234, 1), -3em -1em 0 0.3em rgba(177, 227, 234, 1); } /* Брызги */ 30% { top: 90%; box-shadow: 1.5em 0 0 0.2em rgba(252, 252, 255, 0.1), -2em 0 0 0.15em rgba(252, 252, 255, 0.1), 3em 0 0 0.2em rgba(252, 252, 255, 0.1), -2em 0 0 0.25em rgba(252, 252, 255, 0.1), 0 0 0 0.2em rgba(252, 252, 255, 0.1), 2.35em 0 0 0.3em rgba(252, 252, 255, 0.1), -0.5em 0 0 0.2em rgba(252, 252, 255, 0.1), 1em 0 0 0.3em rgba(252, 252, 255, 0.1), -4em 0 0 0.4em rgba(252, 252, 255, 0.1); } /* Скрывание */ 40%, 100% { top: 95%; background: rgba(255, 255, 255, 1); box-shadow: 1.8em 0.5em 0 0.2em rgba(255, 255, 255, 0), -3em 0.5em 0 0.1em rgba(255, 255, 255, 0), 4em 0.5em 0 0.1em rgba(255, 255, 255, 0), -3.5em 0.5em 0 0.1em rgba(255, 255, 255, 0), 0 0 0 0.3em rgba(255, 255, 215, 0), 2.45em 0.5em 0 0.1em rgba(255, 255, 255, 0), -0.8em 0.5em 0 0.2em rgba(255, 255, 255, 0), 1.5em 0.5em 0 0.3em rgba(255, 255, 255, 0), -4.5em 0.5em 0 0.2em rgba(255, 255, 255, 0); } } /* Анимация водной поверхности */ @keyframes surface { 50% { border-radius: 0 75% 0 75%; opacity: 0.5; height: 3.5em; } } |
Для получения более натуралистичной анимации вот вам две подсказки:
Смотрите и анализируйте справочную информацию – изображения, видео и т.д.
Поэкспериментируйте с различными скоростями переходов свойств CSS и ключевых кадров.
Еще информация об анимации и определенно забавная статья, стоящая изучения – это Аварийный набор аниматора (The Animator’s Survival Kit) от Ричарда Уильямса (Richard Williams).
Вернемся к нашим баранам. В последнем примере у псевдокласса :before та же ширина, что у его родительского элемента. Чтобы неожиданно не возникла проблема переполнения, мы применим значение “inherit”.
ПРИМЕР 2
В этом примере с помощью перехода мы создадим эффект проведения мышью.
Разметка
1 2 3 |
<div class="circle"> <h1>codrops</h1> </div> |
Здесь есть только контейнер и заголовок, чтобы отделить текст от всего остального.
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
.circle { background: rgb(255,255,255); border-radius: 100%; cursor: pointer; position: relative; margin: 0 auto; width: 15em; height: 15em; overflow: hidden; transform: translateZ(0); } .circle h1 { color: rgba(189, 185, 199,0); font-family: 'Lato', sans-serif; font-weight: 900; font-size: 1.6em; line-height: 8.2em; text-align: center; text-transform: uppercase; -webkit-font-smoothing: antialiased; user-select: none; transition: color 0.8s ease-in-out; } .circle:before, .circle:after { border-radius: 100%; content:""; position: absolute; top: 0; left: 0; width: inherit; height: inherit; box-shadow: inset 10.6em 0 0 rgba(30, 140, 209, 0.2), inset 0 10.6em 0 rgba(30, 140, 209, 0.2), inset -10.6em 0 0 rgba(30, 140, 209, 0.2), inset 0 -10.6em 0 rgba(30, 140, 209, 0.2); transition: box-shadow 0.75s; } /* Мы вращаем псевдоэлемент :after, чтобы его край пришелся на угол, то же самое можно было бы сделать с помощью тени блока box-shadow. */ .circle:after { transform: rotate(45deg); } /* Применение "pseudo-class + pseudo-element" не создает никаких проблем:) */ .circle:hover:before, .circle:hover:after { box-shadow: inset 0.86em 0 0 rgba(255, 0, 0, 0.5), inset 0 0.86em 0 rgba(252, 150, 0, 0.5), inset -0.86em 0 0 rgba(0, 255, 0, 0.5), inset 0 -0.86em 0 rgba(0, 150, 255, 0.5); } .circle:hover > h1 { color: rgba(185, 185, 185,1); } |
Вам нужно применять за раз только один цвет во избежание ненужного смешения цветов при наложении во время запуска эффекта проведения мышью.
ПРИМЕР 3
Как мы посмели бы пройти мимо обязательной анимации загрузки! Тут идея заключается в смешении цветов по мере вращения. Это очень просто!
Разметка
1 |
<div class="loading"></div> |
Для разметки мы применим один-единственный элемент.
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
.loading { background: rgba(0, 50, 250, 0); position: relative; margin: 5em auto 0 auto; width: 3em; height: 3em; animation-name:rotate; } .loading, .loading:before, .loading:after { border-radius: 100%; animation-duration: 3s; animation-iteration-count: infinite; animation-timing-function: ease-in; } .loading:before, .loading:after { content: ""; position: absolute; top: 0; left: 0; width: inherit; height: inherit; } .loading:before { background: rgba(200, 250, 100, 0); animation-name: ring; } .loading:after { background: rgba(250, 0, 200, 0); animation-name: ring2; } @keyframes rotate { 0% { transform: rotateZ(0deg) scaleX(0.1) scaleY(0.1) translateZ(0); box-shadow: inset 0.8em 0 0 rgba(255, 0, 0, 0.5), inset 0 0.8em 0 rgba(252, 150, 0, 0.5), inset -0.8em 0 0 rgba(0, 255, 0, 0.5), inset 0 -0.8em 0 rgba(0, 150, 255, 0.5); } /* Скрыто */ 85%, 100% { /* 360 градусов х 10 */ transform: rotateZ(3600deg) scaleX(2.01) scaleY(2) translateZ(0); box-shadow: inset 0 0 0 rgba(255, 0, 0, 0), inset 0 0 0 rgba(252, 150, 0, 0), inset 0 0 0 rgba(0, 255, 0, 0), inset 0 0 0 rgba(0, 150, 255, 0); } } @keyframes ring { 0% { transform: scaleX(0.1) scaleY(0.5); box-shadow: inset 0.8em 0 0 rgba(255, 0, 0, 0.5), inset 0 0.8em 0 rgba(252, 150, 0, 0.5), inset -0.8em 0 0 rgba(0, 255, 0, 0.5), inset 0 -0.8em 0 rgba(0, 150, 255, 0.5); } /* Скрыто */ 75%, 100% { transform: scaleX(2) scaleY(2.1); box-shadow: inset 0 0 0 rgba(255, 0, 0, 0), inset 0 0 0 rgba(252, 150, 0, 0), inset 0 0 0 rgba(0, 255, 0, 0), inset 0 0 0 rgba(0, 150, 255, 0); } } @keyframes ring2 { 0% { transform: scaleX(0.5) scaleY(0.1); box-shadow: inset 0.8em 0 0 rgba(255, 0, 0, 0.5), inset 0 0.8em 0 rgba(252, 150, 0, 0.5), inset -0.8em 0 0 rgba(0, 255, 0, 0.5), inset 0 -0.8em 0 rgba(0, 150, 255, 0.5); } /* Скрыто */ 65%, 100% { transform: scaleX(2) scaleY(2.1); box-shadow: inset 0 0 0 rgba(255, 0, 0, 0), inset 0 0 0 rgba(252, 150, 0, 0), inset 0 0 0 rgba(0, 255, 0, 0), inset 0 0 0 rgba(0, 150, 255, 0); } } |
Это – отличный пример экспериментирования с временными интервалами и скоростями для получения действительно эффектной анимации.
ПРИМЕР 4
А это – самый безумный и экстравагантный пример из всех: маленькое летучее одноглазое существо! Здесь мы применим и анимацию, и переходы.
Разметка
1 |
<div class="pojoro">●</div> |
Для глаза существа мы применим один элемент.
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
.pojoro { background: rgba( 255, 255, 255, 1); background: radial-gradient(ellipse at center, rgba(255,255,255,1) 40%,rgba(51,51,51,1) 100%); border-radius: 100%; /* box-shadow: смешанный цвет, тело, ресницы */ box-shadow: 0 0 0 0.2em rgb(146,89,149), 0 0 0.1em 0.55em rgb(176,89,179), inset 0 0.2em 0 0 rgb(136,79,139); /* ojo (глаз) */ color: rgba( 40, 40, 40, 0.8); line-height: 1.1em; padding-left: 0.18em; -webkit-font-smoothing: antialiased; user-select: none; /*юзабилити, расположение и переход */ cursor: pointer; position: relative; margin: 5em auto 0 auto; width: 1em; height: 1em; transform-origin: center; transition: all 0.8s ease-in-out; /*Разделите анимацию, чтобы лучше контролировать глаз и тело */ animation: eye 2.2s ease-in-out infinite, body 1.15s 1.8s linear infinite; } /* Поднимите и измените создание. */ .pojoro:hover { transform: scaleY(0.9) scaleX(0.95) translateY(-3em) translateZ(0); } /* Крылья */ .pojoro:before, .pojoro:after { background: rgba(0,0,0,0); border-radius: 100%; content: ""; /* display:none, скройте крылья */ display: none; position: absolute; width: 1em; height: 0.1em; -webkit-filter: blur(1px); transition: all 0.2s; animation-duration: 0.2s; animation-iteration-count: infinite; animation-timing-function: ease-in-out; } .pojoro:before { top: 25%; left: 1.45em; margin-left: -1em; transform-origin: left; transform: rotate(-60deg); animation-name: wings; } .pojoro:after { top: 25%; left: -2.2em; margin-left: 1em; transform-origin: right; transform: rotate(60deg); animation-name: wings2; } .pojoro:hover:before, .pojoro:hover:after { background: rgba(100,100,100,0.8); /* display:block, появляются крылья и начинается анимация */ display: block; margin-left: 0em; width: 2em; height: 0.3em; } @keyframes eye { /* Движение глаза */ 5%, 10% { line-height: 1.2em; padding-left: 0em; } 15%, 20% { line-height: 1.15em; padding-left: 0.4em; } /* Движение ресниц */ 25% { box-shadow: 0 0 0 0.2em rgb(146,89,149), 0 0 0.1em 0.55em rgb(166,89,169), inset 0 1em 0 0 rgb(136,79,139); } 23%, 27% { box-shadow: 0 0 0 0.2em rgb(146,89,149), 0 0 0.1em 0.55em rgb(166,89,169), inset 0 0.2em 0 0 rgb(136,79,139); } } @keyframes body { 50% { width: 1.4em; height: 1.4em; } } @keyframes wings { 50% { transform: rotate(65deg); } } @keyframes wings2 { 50% { transform: rotate(-65deg); } } |
При проведении мышью мы активируем анимацию крыльев, а тело начинает подниматься. И это был последний пример!
В заключение скажу, что псевдоэлементы – отличная вещь, и их сочетание с анимацией и переходами позволяет создавать забавные эффекты без применения излишнего количества разметки и изображений. Надеюсь на скорое расширение их браузерной поддержки; а до этого момента мы сможем играть с ними и получать удовольствие от интересных техник. А что вы думаете об этом?
Надеюсь, статья окажется полезной и послужит вам вдохновителем.
Автор: Marco Barria
Источник: //tympanus.net/
Редакция: Команда webformyself.