Что ещё нового в современном CSS
hard

Что ещё нового в современном CSS

Ещё моднее, удобнее и красивее

Недавно мы рассказывали про CSS-свойства, которые появились в 2023 году. Но нового так много, что мы сделали продолжение. 

Пока эти свойства поддерживаются не всеми браузерами. Прежде чем использовать что-то в своём проекте, проверьте поддержку свойства на сайте Can I Use.

Динамические единицы измерения области просмотра

В CSS есть относительные единицы измерения, которые зависят от viewport — размера окна браузера, то есть видимой части документа:

  • vh — viewport height, высота;
  • vw — viewport width, ширина;
  • vmin — размер в процентах от меньшей размерности;
  • vmax — размер в процентах от большей размерности.

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

Динамические единицы измерения области просмотра
Так контент на один экран может выходить за область просмотра. Источник: web.dev

Для решения этой проблемы были определены новые состояния: большой экран просмотра и малый экран просмотра — и введены новые единицы:

  • svh и svw — наименьший активный размер области просмотра (small viewport height/width);
  • lvh и lvw — наибольший активный размер области просмотра (large viewport height/width).

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

Также есть новые динамические единицы dvh и dvw:

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

Посмотреть, как работают динамические единицы в реальности, можно в этом видео:

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

Динамические единицы измерения области просмотра
Наименьший активный размер области просмотра (1), наибольший активный размер области просмотра (2), 100dvh адаптируется как к большому, так и к маленькому размеру области просмотра (3 и 4). Источник: web.dev

Тригонометрические функции

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

Раньше это делали в препроцессорах, а теперь тригонометрические функции доступны прямо в CSS.

Что появилось:

  • cos() возвращает косинус угла, значение которого находится в диапазоне от –1 до 1;
  • sin() возвращает синус угла, значение которого находится в диапазоне от –1 до 1;
  • tan() возвращает тангенс угла, значение которого находится в диапазоне от –∞ до ∞.

Также есть функции, которые выполняют вычисления в обратном порядке: asin(), acos(), atan() и atan2()

Представим, что мы хотим нарисовать треугольник — в качестве элемента дизайна сайта или для иллюстрации статьи о треугольниках. Для этого нам нужно знать размер угла, длину гипотенузы, противолежащей и прилежащей сторон. Зададим угол 30° и гипотенузу (самую длинную сторону треугольника), равную 8rem, то есть в 8 раз больше, чем шрифт корневого элемента. Дальше может быть немного сложно, поэтому следите за руками.

Прописываем HTML-структуру нашего элемента:

 <figure>
   <div class="triangle"></div>
   <figcaption>
     <span>Угол: 30 градусов</span> <span>Гипотенуза: 8rem</span>
   </figcaption>
 </figure>

Задаём стили для размера области рисунка в CSS-файле:

figure {
 --size: 20rem;
 width: var(--size);
 height: var(--size);
}

Мы определили переменную --size и через неё задали высоту и ширину рисунка.

Далее внутри элемента triangle задаём переменные, с которыми будем работать, и стили:

.triangle {
 --hypotenuse: 8rem;
 --angle: 30deg;
 --opposite: calc(sin(var(--angle)) * var(--hypotenuse));
 --adjacent: calc(var(--hypotenuse) / 2);

Здесь мы описали основные элементы треугольника:

  • --hypotenuse: установили длину гипотенузы треугольника.
  • --angle: задали угол между гипотенузой и одним из катетов треугольника.
  • --opposite: использовали математическую функцию calc(), которая умножает значение синуса угла, вычисленного с помощью функции sin(), на длину гипотенузы. Так мы получили длину противолежащей стороны треугольника.
  • --adjacent: вычислили длину прилежащей стороны треугольника.

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

 --startPosX: calc(var(--size) / 2 - var(--adjacent));
 --startPosY: calc(var(--size) / 2 - var(--opposite) / 2);
 --endPosX: calc(var(--size) / 2 + var(--adjacent));
 --endPosY: calc(var(--size) / 2 + var(--opposite) / 2);

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

Теперь осталось нарисовать треугольник. В том же элементе .triangle прописываем:

--clip: polygon(
   var(--startPosX) var(--endPosX),
   50% var(--startPosY),
   var(--endPosX) var(--endPosY)
 );
 clip-path: var(--clip);
 height: inherit;
 background: deeppink;
}

  • --clip: задали переменную, которая используется для создания строки с координатами вершин треугольника для свойства clip-path. Так мы формируем треугольник с помощью координат вершин.
  • clip-path: установили обрезку элемента в форме треугольника с использованием значения переменной --clip.
  • height: высота треугольника наследуется от родительского элемента, в данном случае от figure.
  • background: цвет фона.

Тригонометрические функции

Теперь в зависимости от требований можно менять угол и размер треугольника, а функции calc() и sin() всё посчитают за нас.   

Есть интересный проект — анимированная лента Мёбиуса Аны Тюдор. В нём cos() и sin() используются для управления компонентами функции цвета hsl().

Можно посмотреть пошаговое создание такой анимации и сделать свою:

Индивидуальные свойства трансформации

Теперь трансформации (свойство transform) можно разделять и применять по отдельности.

Представим, что мы хотим сместить треугольник из предыдущего примера и добавить дополнительное свойство при наведении курсора — изменение масштаба.

Тогда нужно было бы писать так:

.triangle {
 transform: translateX(50%) rotate(30deg) scale(1.2);
}
.triangle:hover {
 transform: translateX(50%) rotate(30deg) scale(2);
}

При ховере изменяется только масштаб, но мы должны повторить для него все свойства transform. Код дублируется.

Теперь же можно написать более компактный код:

.triangle {
 translate: 50% 0;
 rotate: 30deg;
 scale: 1.2;
}

.triangle:hover {
 scale: 2;
}
Индивидуальные свойства трансформации

При ховере перезаписалось только свойство scale, а остальные свойства трансформации так и остались применёнными к элементу.

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

Продвинутый синтаксис nth-child

Псевдоклассы группы child позволяют выбирать дочерние элементы не по классу или тегу, а по порядковому номеру. Например, такой синтаксис :nth-child(2) — обращается ко второму дочернему элементу в родительском контейнере.

Новый продвинутый синтаксис nth-child позволяет добавлять ещё и класс элемента. Для этого используется ключевое слово of в скобках.  

Представим, что у нас есть секция с фигурами:

 <section class="main">
   <div class="circle"></div>
   <div class="circle"></div>
   <div class="square"></div>
   <div class="square"></div>
   <div class="circle"></div>
   <div class="square"></div>
   <div class="circle"></div>
 </section>

Внутри секции мы хотим обратиться ко второму элементу square

Тогда мы пишем так:

section :nth-child(2 of .square) {
 background: rgb(0, 207, 83);
}
Что ещё нового в современном CSS

Мы сказали браузеру зайти в контейнер section, выбрать там все элементы .square и поменять цвет фона у второго элемента.

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

Стили с ограниченной областью видимости

Ключевое слово @scope позволяет создавать пространства имён и задавать стили с ограниченной областью видимости, например, чтобы они применялись в определённой части страницы, ограниченные выбранными элементами. Так можно явно задавать границы стиля и не множить в проекте селекторы с высокой специфичностью, которые потом будет сложно переопределить, если макет изменится.

Область действия задается двумя параметрами: корнем области и пределом области. Корень области действия (<scope-start>) определяет узел документа, где начинают применяться стили. Ограничение области (<scope-end>) определяет узлы, на которые не влияет область действия. Этот параметр необязателен.

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

 <div class="article-section">
   <p>Основная часть: <a target="_blank" href="#">читать</a></p>
   <div class="quote-section">
     <p>Дополнительная информация: <a target="_blank" href="#">перейти</a></p>
   </div>
   <div class="news-section">
     <p>Комментарии: <a target="_blank" href="#">оставить</a></p>
   </div>
 </div>

Для всех ссылок внутри раздела .article-section мы задаём стиль через ключевое слово @scope:

@scope (.article-section) {
 a {
   color: blue;
 }
}
Стили с ограниченной областью видимости

Теперь нам нужно поменять цвет ссылки в разделе .quote-section. Чтобы не писать селектор .quote-section a с высокой специфичностью, можно задать ограничение области видимости для селектора а, чтобы стили применялись только в определённом блоке:

@scope (.quote-section) to (.news-section .quote) {
 a {
   color: red;
 }
}
Что ещё нового в современном CSS

Это удобно, когда есть много однотипных блоков и нужно применять уникальные стили к отдельным элементам этих блоков, например для обеспечения доступности или определённой цветовой схемы. Но пока что поддержка @scope браузерами ограничена.

Редактор:

Инна Долога

Обложка:

Алексей Сухов

Корректор:

Ирина Михеева

Вёрстка:

Мария Дронова

Соцсети:

Юлия Зубарева

Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию
Вам может быть интересно
hard