2.24. CSS3 3D-трансформации

css3-3d-transformCSS3 3D-трансформации создают объемные реалистичные эффекты на веб-страницах.

3D-трансформации работают аналогично с 2D-трансформациями с разницей в том, что элементы могут перемещаться вдоль оси Z, вглубь экрана и из него.

Чтобы активизировать 3D-пространство, нужно установить свойство perspective для родительского контейнера.

CSS3 3D-трансформации элементов

Поддержка браузерами

IE: 10.0
Firefox: 16.0, 10. -moz-
Chrome: 36.0, 12.0 -webkit-
Safari: 4.0 -webkit-
Opera: 23.0, 15.0 -webkit-
iOS Safari: 9, 7.1 -webkit-
Opera Mini:
Android Browser: 44, 4.1 -webkit-
Chrome for Android: 44

See the Pen Beautiful 3D-animation by Elena Nazarova (@nazarelen) on CodePen.

1. Установка 3D-перспективы perspective

Свойство активирует 3D-пространство для элемента. Свойство perspective и функция perspective() добавляют глубину элементу, увеличивая его размеры по оси Z, сам элемент при этом становится визуально меньше. Чем меньше значение, тем ближе Z-пространство к зрителю и тем больше эффект, заданный с помощью свойства transform.

Если 3D-перспектива задается с помощью функции perspective(), 3D-пространство активизируется только для одного элемента. Свойство perspective активирует 3D-пространство внутри элемента, содержащего дочерние трансформированные элементы и применяется к ним. Свойство не наследуется.

perspective
Значения:
длина Задает глубину просмотра, т.е. расстояние по оси Z. Значение может быть любым положительным числом. Если единица измерения не указана, по умолчанию она считается в px. Чем больше значение, тем менее выражен эффект. 0 означает отсутствие перспективы.
none Значение по умолчанию. Означает отсутствие перспективы.
initial Устанавливает значение свойства в значение по умолчанию.
inherit Наследует значение свойства от родительского элемента.

Синтаксис

ul {perspective: 500px;}

li {transform: rotateX(50deg);}
li:hover {transform: perspective(900px) rotate3d(180,-45,0,-135deg);}
perspective-3d
Рис. 1. Примеры разных значений 3D-перспективы

2. Задание точки трансформации для 3D-элемента perspective-origin

Свойство устанавливает точку начала координат для свойства perspective. Значение по умолчанию perspective-origin: 50% 50%;. Позволяет изменять направление трансформации дочернего 3D-элемента. Свойство должно использоваться вместе со свойством perspective для блока-контейнера и свойством transform для дочернего элемента. Не наследуется.

perspective-origin
Значения:
значение по оси X/значение по оси Y Первое значение указывает положение элемента по оси X. Может задаваться в единицах длины, в % или одним из трех ключевых слов: left (эквивалентно 0% по оси X), center (эквивалентно 50% по оси X) или right (эквивалентно 100% по оси X).
Второе значение указывает положение по оси Y. Задается в единицах длины, в % или одним из трех ключевых слов: top (эквивалентно 0% по оси Y), center (эквивалентно 50% по оси Y) или bottom (эквивалентно 100% по оси Y).
initial Устанавливает значение свойства в значение по умолчанию.
inherit Наследует значение свойства от родительского элемента.

Синтаксис

ul {
perspective: 150px;
perspective-origin: 10% 10%;
}
li {transform: rotateX(50deg);}
perspective-origin
Рис. 2. Примеры задания точки трансформации

3. Стиль 3D-преобразований transform-style

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

transform-style
Значения:
flat Значение по умолчанию. Все дочерние элементы отображаются плоскими в двухмерной плоскости блока-контейнера.
preserve-3d Располагает элементы в трехмерном пространстве.
initial Устанавливает значение свойства в значение по умолчанию.
inherit Наследует значение свойства от родительского элемента.

Синтаксис

div {
transform: rotateY(60deg);
transform-style: preserve-3d;
}

See the Pen JRodpX by Elena (@html5book) on CodePen.

4. Видимость обратной стороны элемента backface-visibility

Свойство определяет, будет ли видна пользователю обратная сторона преобразованного элемента. У непреобразованного элемента к пользователю обращена передняя сторона. Не наследуется.

backface-visibility
Значения:
visible Значение по умолчанию. Указывает, что обратная сторона видна.
hidden Скрывает обратную сторону элемента.
initial Устанавливает значение свойства в значение по умолчанию.
inherit Наследует значение свойства от родительского элемента.

Синтаксис

div {backface-visibility: hidden;}

See the Pen PGPKKv by Elena (@html5book) on CodePen.

5. Функции 3D-трансформации transform

Свойство задает вид как 2D, так и 3D-преобразований элемента. 3D-преобразования описываются с помощью функций трансформации, перечисленных в таблице ниже. Не наследуется.

See the Pen EgVvww by Elena (@html5book) on CodePen.

Функция Описание
matrix3d
(n,n,n,n,
n,n,n,n,
n,n,n,n,
n,n,n,n)
Функция задает трехмерное преобразование как однородную матрицу размером 4×4 с шестнадцатью значениями в столбцах. Все другие функции преобразований основаны на данной функции.
translate3d(x,y,z) Функция задает перемещение элемента в 3D-пространстве. Движение происходит по вектору [tx, ty, tz], где tx перемещение вдоль оси X, ty — перемещение вдоль оси Y, а tz — вдоль оси Z. Значения могут задаваться в единицах длины или в %. Отрицательные значения будут перемещать элемент в противоположном направлении.

transform: translate3d(100px, 100px, -200px);
transform: translate3d(50%, -100%, 10%);
transform: translate3d(-100px, -30px, 50px);

translateZ(z) Функция задает перемещение элемента на заданное расстояние в направлении оси Z. Значения могут задаваться в единицах длины или в %. Отрицательные значения будут перемещать элемент в противоположном направлении.

transform: translateZ(300px);
transform: translateZ(-50%);
transform: translateZ(150%);

scale3d(x,y,z) Функция задает операцию трехмерного масштабирования по вектору масштабирования [sx,sy,sz], описываемому тремя параметрами. Отрицательные значения отображают элемент зеркально вдоль трех осей.

transform: scale3d(2, 1, 3);
transform: scale3d(-1, -2, -1);

scaleZ(z) Функция масштабирует элемент в направлении оси Z, делая его больше или меньше. В качестве значения задается число. Результат функции наиболее выражен при совместном использовании с такими функциями, как rotate() и perspective().

transform: scaleZ(3);
transform: scaleZ(-1);

rotate3d(x,y,z,угол) Функция вращает элемент по часовой стрелке относительно трех осей. Элемент поворачивается под углом, задаваемым последним параметром относительно вектора направления [x,y,z]. Отрицательные значения поворачивают элемент против часовой стрелки.

transform: rotate3d(1, 1, 2, 45deg);

rotateX(угол) Функция задает поворот по часовой стрелке под заданным углом относительно оси X.
Функция rotateX(180deg) эквивалентна rotate3d(1,0,0,180deg).

transform: rotateX(30deg);
transform: rotateX(-135deg);

rotateY(угол) Функция задает поворот по часовой стрелке под заданным углом относительно оси Y.
Функция rotateY(180deg) эквивалентна rotate3d(0,1,0,180deg).

transform: rotateY(30deg);
transform: rotateY(-135deg);

rotateZ(угол) Функция задает поворот по часовой стрелке под заданным углом относительно оси Z.
Функция rotateZ(180deg) эквивалентна rotate3d(0,0,1,180deg).

transform: rotateZ(30deg);
transform: rotateZ(-135deg);

perspective(n) Функция меняет перспективу обзора элемента, создавая иллюзию глубины. Чем больше значение функции перспективы, тем дальше от смотрящего расположен элемент. Значение должно быть больше нуля.

transform: perspective(300);
transform: perspective(300px);

initial Устанавливает значение свойства в значение по умолчанию.
inherit Наследует значение свойства от родительского элемента.

Синтаксис

div {transform: rotateX(150deg);}
  • Inveresr.PRO

    Замечательная статья, благодарю!

  • nariaran

    Отличный гайд по 3D трансформации! Спасибо за проделанную работу!

    • Пожалуйста! Сама изучала и писала с удовольствием 🙂

      • Farhod Tojimatov

        Здравствуйте! помогите пожалуйста сделать анимацию как на этом сайте https://brand.denso.com/en/

        • Здравствуйте. Под помощью вы подразумеваете сделать всё за вас? Или же вы начали разрабатывать и у вас возникли трудности?

          • Farhod Tojimatov

            нет не за меня конечно )))
            я начал но у меня трудности возникли. Дело в том что у меня опыт не большой в анимации

          • Ясно. На выходных постараемся разобраться.

          • Farhod Tojimatov

            Спасибо. я начал но видимо я не понимаю что да как.

          • Начнем с того, что это не сайт, а приложение, написанное на react. Анимация сделана с помощью GreenSock. С этим я вам уже помочь не смогу ((

  • Владимир

    Елена, спасибо Вам за труд. Изучил 3Dтрансформацию по вашему уроку, но на практике столкнулся с проблемой: http://codepen.io/VLAD_IMIR/pen/JRxOyB . Блок «earth» оказывается плоским, несмотря на все старания повернуть его по оси Х на 90″. Может подскажите, как это сделать?

    • Пожалуйста!
      Вы взялись сразу за сложный пример, до многих вещей доходишь только в процессе длительной практики и экспериментов со свойствами, так как спецификация не содержит каких-либо значимых пояснений. Сделала пример http://codepen.io/html5book/pen/GjLLgb, чтобы было наглядно, добавила границы для элементов-контейнеров.
      Для элемента earth нужно две дополнительные обёртки: первый блок вращается по оси Z на 360°, второй блок является обёрткой непосредственно для маленького круга.

      • Владимир

        Спасибо

        • Пожалуйста. Лучше экспериментировать с такими прототипами, чтобы понять, как это работает. А потом уже стилизовать внешний вид элементов. Если контейнер поворачиваем под одним углом, то элементы внутри него поворачиваем под противоположным (со знаком минус) значением. Если контейнер вращается в одном направлении, то элемент внутри него вращаем в противоположном, чтобы он всегда был к нам лицом.
          Когда делаете анимацию, обратите внимание, что если для элемента в первоначальном состоянии задана трансформация, например, transform: rotate(45deg), а в @keyframes указываете transform: translateX(100px), то первоначальная трансформация заменяется указанной в @keyframes. Поэтому в @keyframes нужно указывать обе трансформации transform: rotate(45deg) translateX(100px).

  • Илья Цедрик

    https://codepen.io/WEBCedrik/pen/QdWpev Оцените мой первый опыт в анимации))

  • userAlexander

    При задании perspective:1000px; увеличивает дочерние элементы на которых задан transform-style:preserve-3d;
    Кто то пытался решить данную ошибку?

    • Можно ваш пример? Не видя, сложно давать рекомендации.

      • userAlexander

        Конечно, Елен.
        Ссылка на код: http://codepen.io/userAlexander/pen/Qdgvzp
        Ссылка на скриншот ошибки: http://joxi.ru/Dr895GvSgE3pm6.png
        при наложении элементов в фотошопе видно, что есть увеличение элемента, это происходит за счет использования perspective:1000px;

        Ссылка на скриншот того, как должно быть: http://joxi.ru/KAgJ4bkiPJ0k2l.png
        Все в порядке, если не использовать perspective:1000px; но тогда перспектива теряется.

        • Вижу, да, увеличивает при вращении. Мы уже экспериментировали с таким эффектом, посмотрите наш вариант https://codepen.io/html5book/pen/vKraZy, на первый взгляд увеличение не наблюдается.

          • userAlexander

            Да, но у вас же отсутствует свойство perspective, поэтому увеличения не наблюдается.

          • но эффект тот же самый

          • userAlexander

            это все ясно, НО возможно кто то пофиксил данный момент оставив эффект объема, вот, что хотелось бы узнать))

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

          • Может попробовать так:

            .nav__button:hover .nav__button-title{
            	transform:rotateX(90deg) translateY(-50%) scale(.98);
            }
          • userAlexander

            Елена, вы словно видите мой код)))
            Это костыльное решение, так как значение в scale(.98) нужно подстраивать в зависимости от размера элемента с которым работаем)

          • Согласна, костыль. Но вы именно его и просили, так как сломать суть эффекта по- другому не получится.

          • userAlexander

            Нужно еще кого нибудь подключить, коллективный разум способен на многое)

          • )) Просто не используйте перспективу, а только transform-origin и transform (можно matrix3d). И вы получите нужный эффект без каких-либо танцев с бубном.

          • Свойство perspective используется для создания для объёмных фигур, чтобы они не выглядели плоскими. В вашем случае фигура не объёмная, поэтому нет необходимости в использовании этого свойства. И да, перспектива в любом случае будет увеличивать элемент, потому что она создаёт иллюзию глубины. Иллюзия глубины достигается за счёт того, что на заднем плане элемент выглядит меньше, чем на переднем, а в точке схождения он исчезает совсем. Чем меньше значение перспективы, тем больше эффект глубины и тем больше увеличение объекта на переднем плане. https://uploads.disquscdn.com/images/bccc5d805b020bbdbb395a572d89f91593c7c2a6a2e9c0a059798e72f1ce3190.png

            На рисунке все грани куба имеют одинаковый размер, но как вы можете видеть, задняя грань визуально меньше передней грани.
            https://uploads.disquscdn.com/images/f0ab06d5bd0e3e07868e8f1c056e03c0b7b39ae32d8a05af258dc444af95d744.png

  • Влад Чмель

    Боже бабочка как же это круто
    СПАСИБО ЗА НЕЕ!

  • evg1401

    Здравствуйте, извините, что так часто беспокою)) но ваши примеры ввели меня в заблуждение некоторое. К примеру rotateY() поворачивает элемент от центра направо в доль оси Х, разве не наоборот, т.е. наверх по Y? То же и с rotateX. Т.е. надписи на них заменить местами и тогда будет соответствие. Ну это по моему представлению координатной плоскости.

    • Если вам так будет понятнее: вращение относительно оси Х — это как вы совершаете поклон, вращение относительно оси У — это как вы смотрите по сторонам.

      • evg1401

        Это-то меня и вводит взаблуждение,ведь когда я совершаю поклон моя спина наклоняется относительно вертикальной оси Y. В любом случа на практике результат зафиксирую, если ошибка в данном описании нет. Спасибо вам.

        • Вы путаете двухмерное и трехмерное вращение. В плоскости объект вращается вокруг центра (или точки) вращения. В трёхмерном пространстве объект вращается вокруг линии, называемой осью.

  • Генри Миллер

    Если у элемента с transform-style: preserve-3d прозрачность вынести из rgba в отдельное свойство, стиль перестанет работать. Зависимость z-index от opacity ещё более-менее понятна, но здесь ребята из W3C явно перестарались. Впрочем, завтра на свежую голову может и станет яснее…

    • Все верно, в спецификации так и написано, что любое значение opacity, отличное от 1 делает элемент плоским.

  • светлана

    спасибо. отличные все статьи

  • Антон Браим

    Спасибо, очередная страничка к понимания css открыта, но есть вопрос не по теме — где можно почитать, как используется селектор тильда в коде .class1:hover ~ .class2 — что он означает и к чему приводит.
    А по теме — вот простой крутящийся кубик
    https://codepen.io/Alefers/pen/QqLXPR

  • Телемастер

    Класс!