Как создать 3D-эффекты в CSS
Существует аналогия, которая сравнивает языки программирования с домом: HTML — это структура дома (стены, перегородки), CSS — декор и оформление (мебель, интерьер), а JavaScript — функциональность (электроснабжение, сантехника).
В этой статье мы сосредоточимся на CSS, который, несмотря на то, что не является классическим языком разметки, по праву считается одним из самых популярных инструментов в веб-разработке. Многие задачи можно решить без привлечения JS.
На этом уроке вы научитесь создавать 3D-эффекты с помощью CSS, используя свойства и операции, которые позволяют управлять элементами в виртуальном 3D-пространстве. Мы также рассмотрим визуальные иллюзии с использованием теней и света.
Понимание трехмерности изображений
В трехмерном пространстве объекты имеют три величины: длина, ширина и высота. Разработчики в своем широком кругу общения ширину воспринимают так же как и длину, но она более короткая. Так же дела обстоят и с высотой, обычно под ней подразумевается глубина. При обычном взгляде на экран вы видите только 2D, для создания 3D-эффекта вам понадобится свойство CSS transform
.
Благодаря свойству transform можно управлять трехмерными размерами и положением элемента. Управление горизонтальным положением возможна с помощью translateX()
, вертикальным положением — translateY()
, а высотой/глубиной — translateZ()
.
Возьмем для примера иллюстрацию, в котором два прямоугольных элемента — один маленький, а другой большой. Маленький элемент — дочерний (Child), и он вложен в больший родительский элемент (Parent):
При изменении положения дочернего элемента по горизонтали и вертикали используя translate
, вы увидите, что он перемещается:
Изменяя положение элемента child по оси Z с помощью функции translateZ()
, мы ожидаем увидеть эффект глубины — элемент должен казаться удаляющимся или приближающимся к зрителю. Однако на практике этого не происходит, так как отсутствует перспектива.
Перспектива — это визуальный эффект, который позволяет передать ощущение объема и глубины. В CSS для этого используются свойства perspective
и оператор perspective()
, специально предназначенные для работы с 3D-преобразованиями.
Чтобы создать эффект перспективы, нужно задать свойство perspective
родительскому элементу, а для дочернего элемента использовать функцию perspective()
в сочетании со свойством transform
.
Рассмотрим на примере, как свойство perspective
влияет на функцию translateZ()
. Мы создадим простую анимацию, демонстрирующую этот эффект.
Вот HTML и CSS для родительского и дочернего элементов.:
<div class="parent">
<div class="child">
</div>
</div>
.parent {
display: flex;
justify-content: center;
align-items: center;
background: rgba(255, 255, 255, 0.07);
width: 400px;
height: 500px;
border: 0.5px solid rgba(255, 255, 255, 0.15);
border-radius: 5px;
z-index: 0;
}
.child {
background: rgba(255, 255, 255, 0.25);
width: 200px;
height: 250px;
border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 5px;
z-index: 1;
}
В этом проекте сначала добавим perspective
к родительскому элементу, затем к дочернему преобразование анимации (animation: transform
)
.parent{
perspective: 1000px;
}
.child{
animation: transform 5s infinite ease-in-out alternate-reverse;
}
@keyframes transform{
0%{
transform: translateZ(-200px)
}
100%{
transform: translateZ(200px)
}
}
И в результате мы увидим:
Такая анимация проиграется в случае применения оператора perspective()
. Если же вы воспользовались функцией rotate()
, то исход был бы другим.
Давайте рассмотрим пример в котором мы повернем дочерний объект вдоль оси X:
.child{
transform: perspective(10px) rotateX(2deg);
}
В скриншоте это выглядит следующим образом:
Поэкспериментируем с небольшим смещением по оси Z:
Интересно, насколько далеко можно «растянуть» границы объектов:
Создается впечатление нахождения на поверхности элемента. Но с устройством витруально реальности все выглядело бы совершенно по другому.
В своем проекте мы также можем использовать автономное свойство:
.parent {
perspective: 10px;
}
.child {
transform: rotateX(2deg) translateZ(5px);
}
Результат будет аналогичным, но объект не выйдет за границы области просмотра. Как мы уже заметили, у каждого подхода есть свои преимущества. В следующих разделах мы подробно рассмотрим остальные операции transform
.
Важно отметить, что значение perspective
в данном примере использовалось для усиления 3D-эффекта, чтобы вы могли увидеть, как работает свойство. Поскольку мы смотрим на элемент сверху, значение perspective
не превышает 1000px
. Небольшие значения перспективы создают более заметный эффект глубины.
Здесь вы можете посмотреть код с анимацией 3D-преобразования:
Перейдем к самой интересной части — созданию 3D-эффектов с помощью CSS!
Эффект отражения и тень
Взаимодействие света позволяет нам легко определить местоположение объекта в трехмерном пространстве. Чтобы создать иллюзию отражения и тени в CSS, мы можем использовать оператор perspective()
, что придаст элементу эффект плавания в трехмерном пространстве.
3D-отражение текста
На примере мы используем свойство text, но вы можете выбрать и другие HTML-элементы:
<div class="content">
<h1>Text in space</h1>
</div>
Свет нам поможет создать отражение и для этого мы воспользуемся свойством text-shadow
(тень текста):
.content h1 {
position: relative;
font-size: 5rem;
font-weight: 600;
color: #fff;
margin: 3px;
text-shadow: 0px 0px 10px #b393d350, 0px 0px 20px #b393d350;
text-transform: uppercase;
}
Результатом будет эффект светящегося текста:
Теперь добавим отражение с помощью псевдоэлемента:
.content h1::before {
content: "";
position: absolute;
top: 80%;
left: 0;
height: 100%;
width: 100%;
background: #b393d3;
transform: perspective(10px) rotateX(10deg) scale(1,0.2);
filter: blur(1em);
opacity: 0.5;
}
Сначала мы применяем к псевдоэлементу те же размеры и цвет фона, что и к основному объекту — тексту. Затем используем свойство transform
с операторами perspective
, rotateX
и scale
.
С первыми двумя операторами мы уже знакомы. Остановимся на scale
(масштабирование). В предыдущем примере мы видели, как изображение выходило за границы области просмотра. Чтобы избежать этого, можно изменить размер элемента по осям X и Y.
В нашем примере созданное отражение сохраняет свой первоначальный размер по оси X, но уменьшается примерно в два раза по оси Y. Благодаря непрозрачности и фильтру создается ощущение потери света.
В результате мы увидим парящий текст и исходящее от него отражение.
3D-тень (3D shadow)
Используя тот же метод, что и для создания эффекта освещения, мы можем создавать тени. В этом примере мы поработаем с изображением. Вот какое изображение мы добавим в проект:
Работать станет проще, если тень будет соответствовать форме и размеру основного элемента. В нашем примере мы видим ракету, поэтому тень должна быть круглой. В этом случае нам не потребуется использовать оператор perspective()
.
Пропишем код HTML:
<div class="content">
<div class="rocket">
<img src="rocket.png" alt="">
</div>
</div>
В блоке кода CSS мы определим нужные нам размеры, а затем добавим псевдоэлемент:
.rocket::before {
content: "";
position: absolute;
bottom: -10%;
left: 0;
height: 50px;
width: 100%;
border-radius: 50%;
background: radial-gradient(rgba(0, 0, 0, 0.8), transparent, transparent);
transition: 0.5s;
}
Свойство border-radius: 50%
придает тени овальную форму. Вы можете самостоятельно определять высоту или ширину объекта. Тени обычно рисуются в более темных тонах, чем фон, и границы делаются размытыми с помощью радиального градиента, переходящего от черного к прозрачному.
Вот пример того, как выглядит наше изображение на данный момент:
И добавим в код немного анимации:
.rocket:hover img{
transform: translateY(-40px);
}
.rocket:hover::before {
opacity: 0.8;
transform: scale(0.8);
}
С анимацией наша ракета перемещается вверх и вниз, тем самым ее тень будет уменьшаться или увеличиваться.
Полный код и результат вы увидете ниже:
Анимация текста 3D
Создать 3D-текст мы сможем с помощью свойства CSS box-shadow
. Для этого мы воспользуемся несколькими слоями теней.
Для примера возьмем этот код HTML:
<div class="content">
<h1>3D text in 3D space</h1>
</div>
Чтобы превратить его в 3D-текст нам понадобится CSS. Мы наклоним текст под углом, используя perspective
и transform
.
.content {
position: relative;
transform: translate(-50%, -50%);
display: flex;
align-items: center;
justify-content: center;
text-align: center;
perspective: 1500px;
transform-style: preserve-3d;
}
.content h1 {
font-size: 5rem;
font-weight: 600;
color: #b393d3;
text-shadow: 1px 4px 1px #480d35,
1px 5px 1px #480d35,
1px 6px 1px #480d35,/* to create the sides*/
1px 10px 5px rgba(16, 16, 16, 0.5),
1px 15px 10px rgba(16, 16, 16, 0.4),
1px 20px 30px rgba(16, 16, 16, 0.3); /* real shadow */
margin: 3px;
transform: rotateX(15deg) rotateY(-20deg) rotateZ(10deg);
text-transform: uppercase;
На данном этапе это будет выглядеть следующим образом:
Добавляем анимацию:
.content:hover h1{
transform: rotateX(2deg) rotateY(0deg) rotateZ(0deg);
font-size: 4rem;
transition: 500ms ease-in-out;
}
Вот такой результат мы увидим:
Эффект 3D наклона
На данном этапе предлагаем поэксперементировать с изображениями. Для примера возьмем изображение:
В работу возьмем следующий код HTML:
<div class="text">
<h2>Hover on the image</h2>
<p>It uses a combination of all the rotate operators</p>
<div class="tilt-img">
<img src="7.jpg" alt="">
</div>
</div>
Можно использовать изображение для фона, но необходимо учитывать четкое разграничение родительских элементов и дочерних.
Чтобы наклонить изображение под углом и вернуть его в исходное положение при наведении курсора, используйте свойство transform
в CSS:
.tilt-img {
width: 600px;
height: auto;
margin-top: 20px;
perspective: 1000px;
}
.tilt-img img {
width: 100%;
height: 100%;
object-fit: contain;
border-radius: 10px;
transform: rotateX(15deg) rotateY(-5deg) rotateZ(1deg);
box-shadow: 5px 5px 2px rgba(0, 0, 0, 0.5);
transition: 2s;
}
.tilt-img:hover img{
transform: none;
box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.5);
}
Вы можете изменять наклон (tilt
) и добавлять при наведении курсора мыши или же скорректировать значения transform
:
Продемонстрируем наклон 3D-изображения с помощью CSS:
Наклон и отслеживание мыши
В этом примере мы научимся наклонять элемент и следить за движением мыши при наведении на него. Для этого мы воспользуемся vanilla-tilt.js — библиотекой JavaScript.
Так выглядит результат, к которому мы будем стремиться:
Создадим карточку и добавим немного текста с HTML:
<div class="box">
<div class="elements">
<h2>Hello!</h2>
<p>I'm a 3D card</p>
</div>
<div class="card">
</div>
</div>
Следующим шагом мы задаем стили с помощью CSS:
.box {
position: relative;
border-radius: 20px;
transform-style: preserve-3d;
}
.box .card {
position: relative;
background: rgba(255, 255, 255, 0.07);
width: 300px;
min-height: 400px;
backdrop-filter: blur(10px);
border: 0.5px solid rgba(255, 255, 255, 0.15);
border-radius: 20px;
box-shadow: 0 25px 45px rgba(0,0,0,0.05);
}
.elements{
position: absolute;
top: 100px;
left: 50px;
width: 200px;
height: auto;
text-align: center;
background: transparent;
transform: translateZ(80px);
}
.elements h2{
font-size: 3rem;
font-weight: 600;
color: #f6d8d5;
text-transform: uppercase;
}
.elements p{
font-size: 1.5rem;
color: #b393d3;
}
В этом коде два ключевых свойства CSS отвечают за создание 3D-эффекта на карточке: transform
и transform-style
. В котором:
transform-style: preserve-3d
определяет, что карточка находится в трехмерном пространстве.transform: translateZ(80px)
применяется к элементуelements
(родительскому элементу текста) и сдвигает текст на 80 пикселей в направлении зрителя.
Сочетание этих свойств создает эффект парящего текста над карточкой.
Для подключения библиотеки, вам необходимо перейти на сайт cdnjs.com и найти CDN Vanilla-tilt.js. Далее поставить ссылку на библиотеку в секцию <head>
вашего HTML-документа. Чтобы инициализировать Vanilla-tilt мы на сайте main site скопируем функцию VanillaTilt.init()
, которая управляет наклоном и добавим ее непосредственно перед закрывающим тегом </body>
в нашем HTML.
<script type="text/javascript">
VanillaTilt.init(document.querySelector(".your-element"), {
max: 25,
speed: 400
});
</script>
Теперь нам всего лишь нужно заменить .your-element
на имя класса нашего элемента, чтобы применить эффект 3D-наклона.
По умолчанию максимальный угол наклона и скорость перехода задаются параметрами max
и speed
соответственно. Вы также можете добавить блик (glare
), сглаживание (easing
) или указать направление (tilt
) и угол наклона (angle
).
Пример того, как получить эффект, приведенный выше
<script>
VanillaTilt.init(document.querySelector(".box"), {
max: 10,
speed: 200,
easing: "cubic-bezier(.03,.98,.52,.99)",
reverse: true,
glare: true,
"max-glare": 0.1,
});
</script>
Библиотека выполняет не всю работу, и важно использовать свойства transform
и transform-style
для 3D-эффекта. Без применения данных свойств все выглядело бы примерно так:
В текущем варианте текст отображается на одном уровне с карточкой, и остается только эффект наклона. Это выглядит неплохо, но не так впечатляюще, как 3D-эффект, который мы получаем при включении transform
и transform-style
.
Давайте рассмотрим еще один практический пример использования этого 3D-эффекта.
Используя ту же карточку, мы добавим фоновое изображение и подпись, которая будет появляться при наведении курсора мыши:
.box .card {
position: relative;
background: url(/Captions/8.jpg) center;
background-size: cover;
background-repeat: no-repeat;
width: 300px;
min-height: 400px;
border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 10px;
box-shadow: 0 25px 45px rgba(0,0,0,0.05);
z-index: 0;
}
.elements{
position: absolute;
top: 60%;
left: 30%;
width: 250px;
height: auto;
padding: 10px;
border-radius: 5px;
text-align: center;
background: rgba(255, 255, 255, 0.25);
transform: translateZ(80px);
z-index: 2;
opacity: 0;
transition: opacity 500ms;
}
.box:hover .elements{
opacity: 1;
}
Так выглядит результат создания 3D-карточки с подписью, появляющейся при наведении.
3D-кнопки
Кнопки — это неотъемлемая часть веб-дизайна. Они бывают разных форм, размеров и функций, но у всех есть одно общее: чтобы активироваться, их нужно нажать. Но как часто вы видите, чтобы кнопки действительно "нажимались"?
Добавим небольшое 3D-взаимодействие, которое даст пользователю мгновенную обратную связь и ощущение нажатия.
Для этого мы будем использовать CSS-свойство transform
.
Мы замечаем, что кнопка состоит из отдельных частей — первая с текстом «Click Me» и вторая с нижним и боковым светлым фоном.
Код HTML для кнопки:
<button class="btn"><span class="txt">Click Me</span></button>
В CSS же мы начнем со второй части, с button
с именем класса btn
:
.btn {
position: relative;
background: #17151d;
border-radius: 15px;
border: none;
cursor: pointer;
}
И после мы оформляем верхнюю часть кнопки:
.text {
display: block;
padding: 10px 40px;
border-radius: 15px;
border: 1px solid rgba(255, 255, 255, 0.15);
background: #480d35;
font-size: 1.5rem;
font-weight: 500;
color: #b393d3;
transform: translateY(-6px);
transition: transform ease 0.1s;
}
Ключевым элементом создания 3D-эффекта при нажатии на кнопку является свойство transform
.
Все, что нам нужно сделать, это немного «сдвинуть» кнопку при нажатии, используя transform
на несколько пикселей:
.btn:active .text{
transform: translateY(-2px);
}
Вот пример 3D-кнопки, которую вы можете попробовать прямо сейчас:
Кроссбраузерная совместимость
Свойство transform
и его операторы отлично поддерживаются всеми основными браузерами, за исключением Internet Explorer. Вы можете проверить совместимость самостоятельно на сайте CanIuse:
В браузере Firefox наблюдается небольшая проблема с отображением границ карточки во время анимации. Причина этого пока не ясна. В остальных браузерах анимация работает плавно.
Рекомендуем сравнить производительность в разных браузерах и попробовать использовать разную толщину границ, чтобы найти оптимальное решение.
Веб-дизайн — это творчество! Веб — это ваша творческая площадка, а CSS — ваша кисть. В этой статье вы узнали, как создавать интересные 3D-эффекты с помощью свойства transform
. Попробуйте придумать другие интересные эффекты!