24 Модуль 5 Живой современный сайт 15 мин урок 24 из 25

3D и эффекты

perspective и preserve-3d, повороты по осям, filter и backdrop-filter, режимы наложения и появление блоков при прокрутке.

Что ты научишься делать

  • Сделаешь карточку-перевёртыш на чистом CSS
  • Разберёшься, что делает perspective и почему без неё нет объёма
  • Настроишь появление блоков при прокрутке без единой строчки JavaScript

#perspective: откуда смотрит зритель

Поворот rotateY(45deg) без перспективы выглядит как простое сжатие: элемент просто становится уже. Объём появляется только тогда, когда браузер знает, с какого расстояния мы смотрим.

Это и задаёт perspective. Значение — расстояние от зрителя до плоскости экрана. Чем меньше число, тем ближе «камера» и сильнее искажение.

Лаборатория перспективы

Куб на настоящем 3D-преобразовании и ползунки поворота и глубины.

СвойствоЧто делает
perspectiveНасколько близко «камера»: меньше значение — сильнее эффект
rotateX/Y/ZПоворот вокруг соответствующей оси
translateZСдвиг к зрителю или от него
transform-stylepreserve-3d сохраняет объём у детей

#Где писать perspective

Есть два способа, и они дают разный результат.

  • Свойство perspective у родителя — все дети видны из одной точки, как объекты в одной сцене. Это то, что нужно почти всегда.
  • Функция perspective() внутри transform — у каждого элемента своя камера. Элементы выглядят одинаково, независимо от положения.
CSSОбщая сцена
.scene {  perspective: 900px;  perspective-origin: 50% 40%;  /* откуда смотрим */}.scene__item {  transition: transform .4s ease-out;}.scene__item:hover {  transform: rotateY(18deg) translateZ(30px);}

#preserve-3d: объём для вложенных элементов

По умолчанию дети «сплющиваются» в плоскость родителя: повернул родителя — дети повернулись вместе с ним, но собственной глубины у них нет.

transform-style: preserve-3d сохраняет объём: каждый ребёнок живёт в трёхмерном пространстве родителя. Без этого свойства не собрать ни куб, ни карточку-перевёртыш.

#Карточка-перевёртыш

Классический эффект собирается из трёх вещей: перспектива у обёртки, preserve-3d у вращающегося слоя и backface-visibility: hidden у сторон, чтобы не просвечивала изнанка.

Наведи курсор на карточку
В песочницу

#Фильтры

filter обрабатывает сам элемент, backdrop-filter — то, что находится под ним. Второй и даёт эффект матового стекла.

CSSЧастые фильтры
filter: blur(4px);            /* размытие */filter: brightness(1.2);      /* ярче */filter: grayscale(1);         /* обесцветить */filter: saturate(1.4);        /* насыщеннее */filter: drop-shadow(0 8px 12px rgb(0 0 0 / .3));  /* тень по форме, а не по коробке *//* Несколько сразу — через пробел */filter: grayscale(1) brightness(1.1);/* Размытие того, что под элементом */backdrop-filter: blur(14px) saturate(160%);

#Режимы наложения

mix-blend-mode смешивает элемент с тем, что под ним, — как слои в графическом редакторе. Самые полезные значения: multiply (затемняет, белый становится прозрачным), screen (осветляет, чёрный становится прозрачным) и overlay.

Текст, вырезанный из фона
В песочницу

#Появление при прокрутке — без JavaScript

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

CSSПоявление по мере входа в экран
@keyframes reveal {  from { opacity: 0; transform: translateY(24px); }  to   { opacity: 1; transform: translateY(0); }}.card {  animation: reveal linear both;  /* привязываем ход анимации к появлению элемента на экране */  animation-timeline: view();  animation-range: entry 0% cover 30%;}

Похожая история с View Transitions API — плавными переходами между страницами. Одна строка @view-transition { navigation: auto; } добавляет анимацию перехода там, где браузер это умеет, и ничего не делает там, где нет. Это идеальный пример прогрессивного улучшения: работает — хорошо, не работает — тоже нормально.

#will-change: обещание браузеру

will-change: transform заранее готовит элемент к анимации, вынося его на отдельный слой. Иногда это убирает подтормаживание в первый момент.

Но каждый такой слой съедает память видеокарты. Ставить will-change «на всякий случай» всем элементам — верный способ замедлить страницу вместо ускорения.

Где спотыкаются почти все

Поворот без perspective

Почему rotateY(45deg) без перспективы выглядит как обычное сжатие: объёма нет.

Как надо Задай perspective родителю-сцене. Обычно подходит 600–1200px.

Забыт transform-style: preserve-3d

Почему Дети сплющиваются в плоскость родителя, и куб или перевёртыш не собирается.

Как надо Свойство ставится вращающемуся контейнеру, а не сценe и не сторонам.

Эффект только на :hover

Почему На телефоне наведения нет вовсе, а с клавиатуры приходит фокус. Половина людей эффекта не увидит.

Как надо Добавь :focus-within и сделай элемент фокусируемым. Важную информацию не прячь за наведением.

will-change на всём подряд

Почему Каждый элемент отправляется на отдельный слой видеокарты. Память заканчивается, страница начинает тормозить.

Как надо Ставь только на то, что действительно анимируется прямо сейчас, и убирай после.

Перспектива perspective
Расстояние от зрителя до плоскости экрана. Чем меньше, тем сильнее эффект объёма.
Сохранение объёма transform-style: preserve-3d
Позволяет детям жить в трёхмерном пространстве родителя.
Видимость изнанки backface-visibility
Показывать ли обратную сторону повёрнутого элемента.
Фильтр filter
Графическая обработка элемента: размытие, обесцвечивание, тень по форме.
Режим наложения mix-blend-mode
Способ смешивания элемента с тем, что под ним.
Анимация по прокрутке scroll-driven animation
Анимация, ход которой определяется положением элемента на экране.

Проверь себя

  1. Что произойдёт с <code>rotateY(45deg)</code> без perspective?

    Без точки зрения браузер рисует плоскую проекцию — выглядит как сжатие, а не поворот.

  2. Какому элементу задают <code>transform-style: preserve-3d</code> в карточке-перевёртыше?

    Свойство нужно тому элементу, чьи дети должны сохранить объём, — то есть вращающемуся слою.

  3. Чем backdrop-filter отличается от filter?

    Именно поэтому <code>backdrop-filter: blur()</code> даёт эффект матового стекла: размывается фон, а не сам элемент.

  4. Почему <code>filter</code> у родителя может сломать <code>z-index</code> у ребёнка?

    Контекст наложения из восемнадцатого урока создают <code>transform</code>, <code>filter</code>, <code>opacity</code> и ещё несколько свойств.

  5. Что будет в браузере, который не поддерживает <code>animation-timeline</code>?

    Неизвестное свойство игнорируется, остальная часть правила работает. Главное — не завязывать на нём видимость контента.

Задание

Карточка-перевёртыш

Собери карточку, которая переворачивается при наведении и при получении фокуса:

  • обёртке — perspective;
  • внутреннему слою — transform-style: preserve-3d и переход;
  • сторонам — position: absolute, inset: 0 и backface-visibility: hidden;
  • задней стороне — стартовый rotateY(180deg);
  • переворот срабатывает и на :hover, и на :focus-within.
Открыть в песочнице
    Подсказка 1

    Обёртке: .flip { perspective: 900px; } — без неё поворот будет плоским.

    Подсказка 2

    Внутреннему слою нужны position: relative, размеры 100%, preserve-3d и transition: transform 600ms.

    Подсказка 3

    Переворот пиши так: .flip:hover .flip__inner, .flip:focus-within .flip__inner { transform: rotateY(180deg); }

    Показать решение
    HTMLindex.html
    <div class="flip" tabindex="0">  <div class="flip__inner">    <div class="flip__face flip__face--front">      <h3>Раф на кокосовом</h3>      <p>240 ₽</p>    </div>    <div class="flip__face flip__face--back">      <p>Кокосовое молоко, ваниль, двойной эспрессо.</p>    </div>  </div></div>
    CSSstyle.css
    * { box-sizing: border-box; }.flip {  perspective: 900px;  width: 240px;  height: 160px;}.flip__inner {  position: relative;  width: 100%;  height: 100%;  transform-style: preserve-3d;  transition: transform 600ms cubic-bezier(.22, 1, .36, 1);}.flip:hover .flip__inner,.flip:focus-within .flip__inner {  transform: rotateY(180deg);}.flip__face {  position: absolute;  inset: 0;  display: grid;  place-content: center;  padding: 18px;  text-align: center;  border-radius: 14px;  backface-visibility: hidden;}.flip__face--front { color: #fff; background: linear-gradient(135deg, #7c5cff, #b06cff); }.flip__face--back {  color: #16181d;  background: #f0eefb;  border: 1px solid #d9d3f5;  transform: rotateY(180deg);}.flip h3 { margin: 0 0 6px; font-size: 17px; }.flip p { margin: 0; font-size: 14px; }

    Проверь себя