Статьи

Использование CSS-преобразований в реальном мире

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

Преобразования HTML-элементов стали стандартом CSS3 в 2012 году и до того были доступны в некоторых браузерах. Преобразования позволяют вам преобразовывать элементы на веб-странице — как объяснено в нашей статье 101 о преобразованиях CSS . Вы можете легко вращать, масштабировать или наклонять свои элементы с помощью всего одной строки кода, что раньше было сложно. Доступны как 2D, так и 3D преобразования.

Что касается поддержки браузеров, 2D-преобразования поддерживаются всеми основными браузерами, включая Internet Explorer, который поддерживается с версии 9. Что касается 3D-преобразований, IE имеет лишь частичную поддержку с версии 10.

Эта статья не будет посвящена основам преобразований. Если вы не чувствуете себя очень уверенно с преобразованиями, я рекомендую сначала прочитать о 2D и 3D преобразованиях .

Вертикально выравнивание детей

Любой веб-дизайнер знает, насколько утомительным может быть вертикальное выравнивание элементов. Эта задача может показаться очень простой для человека, который не знаком с CSS, но на самом деле существует масса методов, которые тщательно сохраняются между поколениями разработчиков. Некоторые предлагают использовать display: inline с vertical-align: middle , некоторые голосуют за display: table и сопровождающие стили, тогда как настоящие программисты старой школы все еще разрабатывают свои сайты с помощью таблиц (просто шучу, не делай этого!). Кроме того, эту задачу можно решить с помощью Flexbox или гридов, но для небольших компонентов преобразования могут быть более простым вариантом.

Вертикальное выравнивание может быть более сложным, когда высота элемента является переменной. Тем не менее, CSS-преобразования обеспечивают один из способов решения проблемы. Давайте рассмотрим очень простой пример с двумя вложенными div :

 <div class="parent"> <div class="child"> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore </div> </div> <div class="parent"> <div class="child"> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam </div> </div> 

Ничего сложного: только два вложенных блока с текстом Lorem Ipsum разной длины.

Давайте установим ширину, высоту и границу для родителя, а также некоторые интервалы, чтобы он выглядел лучше:

 .parent { height: 300px; width: 600px; padding: 0 1em; margin: 1em; border: 1px solid red; } 

Также немного увеличьте размер шрифта для детей:

 .child { font-size: 1.2rem; } 

В результате вы увидите что-то вроде этого:

Наш первоначальный макет

И теперь ваш клиент говорит: «Пожалуйста, выровняйте текст по вертикали так, чтобы он находился посередине этих красных прямоугольников». Нееет! , Но не бойтесь: мы вооружены преобразованиями! Первый шаг — расположить наших детей относительно и переместить их на 50% вниз:

 .child { font-size: 1.2rem; position: relative; top: 50%; } 

После этого примените секретный компонент — функцию translateY — который будет перемещать элементы по вертикали:

 .child { font-size: 1.2rem; position: relative; top: 50%; transform: translateY(-50%); } 

Итак, что здесь происходит? top: 50% перемещает верх дочернего элемента в центр родительского элемента:

Перемещение вершины дочернего элемента в центр родителя

Но этого недостаточно, потому что мы хотим, чтобы центр ребенка был выровнен с центром родителя. Поэтому, применяя translateY мы перемещаем ребенка на 50% его высоты:

Центрирование по вертикали с помощью translateY

Некоторые разработчики сообщают, что этот подход может привести к тому, что дети станут размытыми из-за того, что элемент помещен в «полупиксель». Решение для этого состоит в том, чтобы установить перспективу элемента:

 .child { // ... transform: perspective(1px) translateY(-50%); } 

Это оно! Ваши дети теперь выровнены правильно даже с переменным текстом, что действительно приятно. Конечно, это решение немного хакерское, но оно работает в старых браузерах в отличие от CSS Grid. Окончательный результат можно увидеть на CodePen:

Создание стрел

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

Вместо этого давайте попробуем придерживаться чисто CSS-решения. Предположим, у нас есть текстовое поле:

 <div class="box"> <div class="box-content"> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam </div> </div> 

У этого есть некоторый общий стиль, чтобы сделать его похожим на речевой пузырь:

 html { font-size: 16px; } .box { width: 10rem; background-color: #e0e0e0; padding: 1rem; margin: 1rem; border-radius: 1rem; } 

Коробка с закругленными углами

Здесь я использую единицы rem чтобы при изменении размера шрифта корня поле масштабировалось соответственно.

Далее, я бы хотел сделать этот пузырь более «пузыривым», отображая стрелку справа. Мы добьемся этого, используя псевдо-селектор :: before :

 .box::before { content: ''; width: 1rem; height: 1rem; background-color: #e0e0e0; overflow: hidden; } 

Чем больше ширина и высота, которые вы назначаете, тем больше будет стрелка.

Теперь переместите стрелку вправо:

 .box { // ... position: relative; } .box::before { // ... position: absolute; right: -0.5rem; } 

Однако в настоящее время этот элемент совсем не похож на стрелку:

Еще не стрела

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

 .box::before { // ... top: 50%; } 

Он не совсем точно выровнен, но мы исправим это позже.

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

 .box::before { // ... transform: rotate(45deg); } 

Вот скриншот с консоли разработчика (поле выделено синим цветом, чтобы вы могли видеть, как оно на самом деле расположено):

Консоль разработчика вид повернутого квадрата

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

 .box::before { // ... margin-top: -0.5rem; } 

Это оно! Теперь, даже если вам нужно настроить размер шрифта на странице, ваше поле и стрелка будут масштабироваться правильно! Вот окончательный результат:

Создание загрузчика «Jumping Ball»

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

Ранее, когда не было CSS-анимации и преобразований, мы, вероятно, использовали бы графический редактор для создания анимированного изображения загрузчика GIF. В этом больше нет необходимости, потому что CSS3 предлагает мощные опции. Итак, давайте посмотрим, как преобразования можно использовать в сочетании с анимацией, чтобы создать красивый прыгающий мяч.

Для начала создайте пустой div :

 <div class="loader"></div> 

Шары обычно круглые (капитан, очевидно, спасение!), Поэтому давайте дадим ему ширину, высоту и радиус границы:

 .loader { border-radius: 50%; width: 50px; height: 50px; } 

Давайте также воспользуемся CSS-редактором градиента фона для генерации градиента:

 .loader { border-radius: 50%; width: 50px; height: 50px; background: linear-gradient(to bottom, #cb60b3 0%,#c146a1 50%,#a80077 51%,#db36a4 100%); } 

Вот наш блестящий фиолетовый шар, который напоминает покебол:

Наш блестящий фиолетовый шар

Как мы можем заставить его прыгать? Ну, с помощью CSS-анимации ! В частности, я собираюсь определить бесконечную анимацию, называемую jump которая занимает 1,5 секунды, и выполняет перечисленные действия вперед и назад:

 .loader { // ... animation: jump 1.5s ease-out infinite alternate; } 

Далее, давайте спросим себя: что это значит, когда мы говорим «прыгать»? В простейшем случае это означает перемещение вверх и вниз по оси Y (по вертикали). Итак, давайте снова воспользуемся функцией translateY и определим ключевые кадры:

 @keyframes jump { from { transform: translateY(0px) } to { transform: translateY(-50px) } } 

Итак, изначально мяч находится в точке с координатами (0,0) , но затем мы перемещаем его до (0,-50) . Однако в настоящее время у нас может не хватить места для мяча, чтобы он мог прыгнуть, поэтому давайте добавим немного запаса

 .loader { margin-top: 50px; } 

Конечно, мы можем сделать больше. Например, давайте вращать этот шар, пока он прыгает:

 @keyframes jump { from { transform: translateY(0px) rotate(0deg) } to { transform: translateY(-50px) rotate(360deg) } } 

Кроме того, почему бы нам не сделать его меньше? Для этого воспользуемся функцией scale которая изменяет ширину и высоту элемента, используя заданные множители:

 @keyframes jump { from { transform: translateY(0px) rotate(0deg) scale(1,1); } to { transform: translateY(-50px) rotate(360deg) scale(0.8,0.8); } } 

Кстати, обратите внимание, что все функции должны быть перечислены для свойства transform как to разделах, так и to разделах, потому что иначе анимация не будет работать должным образом!

Наконец, давайте добавим немного непрозрачности для шара:

 @keyframes jump { from { transform: translateY(0px) rotate(0deg) scale(1,1); opacity: 1; } to { transform: translateY(-50px) rotate(360deg) scale(0.8,0.8); opacity: 0.8; } } 

Это оно! Наш элемент загрузчика готов, и вот окончательный результат:

Создание загрузчика Spinner с SVG

Мы уже видели, как создать простой загрузчик с «прыгающим мячом» всего за несколько строк кода. Однако для более сложного эффекта вы можете использовать SVG, которые определены с помощью набора специальных тегов.

Эта статья не предназначена для объяснения того, как работают изображения SVG и как их создавать, но у Sitepoint есть пара статей на эту тему.

В качестве примера, давайте создадим спиннер-загрузчик. Вот соответствующий SVG:

 <svg class="spinner" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg"> <!-- 1 --> <circle class="path spinner-border" cx="33" cy="33" r="31" stroke="url(#gradient)"></circle> <!-- 2 --> <linearGradient id="gradient"> <!-- 3 --> <stop offset="50%" stop-color="#000" stop-opacity="1"></stop> <stop offset="65%" stop-color="#000" stop-opacity=".5"></stop> <stop offset="100%" stop-color="#000" stop-opacity="0"></stop> </linearGradient> <circle class="path spinner-dot" cx="37" cy="3" r="2"></circle> <!-- 4 --> </svg> 

Основные вещи, чтобы отметить здесь:

  1. Наш холст имеет область просмотра 66 × 66.
  2. Это определяет фактический круг, который будет вращаться. Его центр расположен в (33,33) а радиус составляет 31px. У нас также будет штрих 2px, что означает 31 * 2 + 2 * 2 = 66 . stroke="url(#gradient) означает, что цвет обводки определяется элементом с идентификатором #gradient .
  3. Это наш градиент для хода прядильщика. Он имеет три точки останова, которые устанавливают различные значения непрозрачности, что приведет к довольно крутому эффекту.
  4. Это точка, которая будет отображаться на ходу прядильщика. Это будет выглядеть как маленькая «голова».

Теперь давайте определим стили для холста и масштабируем его до 180 × 180:

 .spinner { margin: 10px; width: 180px; height: 180px; } 

Теперь .spinner-border , .spinner-dot и некоторые общие стили для них:

 .spinner-dot { stroke: #000; stroke-width: 1; fill: #000; } .spinner-border { fill: transparent; stroke-width: 2; width: 100%; height: 100%; } .path { stroke-dasharray: 170; stroke-dashoffset: 20; } 

Вот как выглядит наш счетчик на этом этапе. На данный момент это не вращается, конечно:

Наш счетчик на этом этапе

Теперь давайте заставим его вращаться, что фактически означает поворот на 360 градусов:

 .spinner { // ... animation: rotate 2s linear infinite; } @keyframes rotate { to { transform: rotate(360deg); } } 

Это бесконечная анимация, которая занимает 2 секунды.

Кроме того, мы можем добиться интересного эффекта « змеи, пытающейся откусить свой хвост » с помощью функции перекоса. Помните, что я назвал эту маленькую точку «головой»? Почему бы нам не притворяться, что это голова змеи? Чтобы он выглядел более реалистично, мы наклоним его по оси X:

 .spinner-dot { // ... animation: skew 2s linear infinite alternate; } @keyframes skew { from { transform: skewX(10deg) } to { transform: skewX(40deg) } } 

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

Змея, преследующая свой хвост

Вот окончательный результат нашего счетчика:

Создание флип-анимации

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

Итак, прежде всего, давайте создадим макет:

 <section class="container"> <figure class="photo"> <img src="https://images.freeimages.com/images/large-previews/535/natural-wonders-1400924.jpg" class="front side"> <figcaption class="back side"> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </figcaption> </figure> <figure class="photo"> <img src="https://images.freeimages.com/images/large-previews/6d5/lake-at-the-cottage-1372381.jpg" class="front side"> <figcaption class="back side"> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </figcaption> </figure> <figure class="photo"> <img src="https://images.freeimages.com/images/large-previews/a0d/autumn-tree-1382832.jpg" class="front side"> <figcaption class="back side"> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </figcaption> </figure> </section> 

Здесь у нас есть контейнер с тремя фотографиями. Эти фотографии на самом деле будут иметь две стороны: переднюю и заднюю, как у монеты есть головы и хвосты. Передняя часть содержит фактическое изображение, тогда как задняя часть (которая изначально не видна) содержит описание.

Украсьте контейнер, добавив к нему некоторое поле:

 .container { margin: 10px auto; } 

Каждая фотография корректируется в соответствии с шириной области просмотра и перемещается влево:

 .photo { width: 22vw; height: 20vw; min-width: 130px; min-height: 100px; float: left; margin: 0 20px; } 

Сами изображения должны поддерживать соотношение сторон и пытаться заполнить родительский:

 .photo img { object-fit: cover; } 

Каждая сторона должна занимать 100% ширины и высоты родителя:

 .side { width: 100%; height: 100%; } 

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

Довольно стандартный макет галереи

Далее я хотел бы поместить описание прямо над изображением (по оси Z). Для этого давайте настроим некоторые правила position :

 .photo { // ... position: relative; } .side { // ... position: absolute; } 

Текст теперь отображается прямо над изображением:

Текст отображается над изображением

Теперь пришло время для магии. Я бы хотел, чтобы дети блока .photo были расположены в 3D с помощью свойства transform-style . Это позволит нам достичь ощущения перспективы:

 .photo { // ... transform-style: preserve-3d; } 

Задняя сторона не должна быть видна изначально:

 .side { // ... backface-visibility: hidden; } 

Что касается самого .back , поверните его на 180 градусов по оси Y:

 .back { transform: rotateY(180deg); text-align: center; background-color: #e0e0e0; } 

Это приведет к тому, что описание будет скрыто.

Затем определите анимацию при наведении:

 .photo:hover { transform: rotateY(180deg); } 

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

 .photo { // ... transition: transform 1s ease-in-out; } 

Вот окончательный результат:

Слово предостережения

Без сомнения, CSS-преобразования и анимация являются очень мощными инструментами, которые можно использовать для создания интересных и красивых эффектов. Тем не менее, важно быть разумным в отношении их использования и не злоупотреблять ими. Помните, что вы создаете сайты для пользователей, а не для себя (в большинстве случаев, во всяком случае). Следовательно, CSS следует использовать для лучшего восприятия пользователя, а не для того, чтобы показать все классные трюки, которые вы уже изучили.

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

Вывод

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

Если у вас есть дополнительные вопросы, не стесняйтесь размещать их в комментариях.