Неизвестно полезный CSS. Часть 2

от автора

Привет, Хабр. Я продолжаю рассказывать про неизвестные широкому кругу разработчиков CSS-фишки. Я отбираю их так, чтобы они были полезны в разного рода проектах. Неважно, верстаете ли вы сайт для малого бизнеса или создаёте супермодное React-приложение. Они поддерживаются большинством браузеров. Отдельно отмечу, что я не считаю IE11 современным браузером. По этой причине я не учитывал его.

Сегодня мы рассмотрим:

  • загрузку фоновых изображений для экранов с повышенной плотностью пикселя с помощью функции image-set();
  • как с помощью неё же ускорить загрузку страницы;
  • можно ли использовать нестандартный шрифт без его загрузки;
  • чем полезен псевдо-класс :focus-within при вёрстке кастомных чекбоксов;
  • мой любимый лайфхак на основе пользовательских CSS-свойств.

Больше не буду затягивать. Давайте посмотрим, что я вам подготовил.

▍ Функция image-set() и новые оптимизации загрузки фоновых изображений

За 13 лет разработки атрибут srcset и элемент <picture> были одними из самых долгожданных для меня фишек. Я помешан на оптимизации. А тогда уже нужно было использовать изображения в разных условиях. Мобильные устройства, экраны с повышенной плотностью пикселя или как способ ускорения загрузки страницы. Во всех этих случаях я применял новые возможности. Так что они очень нравились мне.

Только так нельзя было делать с фоновыми изображениями, вставленными через свойство background-image. Например, нельзя было использовать дескриптеры, как у атрибута srcset. В итоге по-прежнему приходилось загружать одно тяжёлое по весу изображение для всех устройств. Хорошо, что теперь везде работает функция image-set().

Я не помню, когда она появилась. Точно знаю, что с префиксом она работала в Google Chrome в 2012 году. А с 2021 года поддержка стала позволять использовать её в продакшене. С помощью функции мы можем подсказать браузерам, какое изображение им загружать в зависимости от условий. В целом её работа напоминает работу атрибута srcset.

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

.container {   background-image: image-set(     url("eiffel-tower-1x.jpg") type("image/jpg") 1x,     url("eiffel-tower-2x.jpg") type("image/jpg") 2x   ); } 

В этом примере браузеры, используя дескриптер 2х, загрузят изображение eiffel-tower-2x.jpg для экранов с двойной и более плотностью пикселя. А для обычных будет загружено изображение eiffel-tower-1x.jpg. Здорово же? А это ещё не всё! Есть другой пример, где функция image-set() будет полезной.

Скорее всего, вы слышали о формате изображений WEBP и AVIF. Если нет, то обязательно прочитайте. Сейчас я ограничусь тем, что их используют для ускорения загрузки страницы, потому что изображения этих форматов в большинстве случаев весят меньше, чем JPG и PNG.

Конечно, есть нюанс с разной поддержкой браузерами. Эту проблему решает элемент <picture>. По этой причине в интернете можно встретить примерно следующий фрагмент кода:

<body>   <picture>     <source srcset="eiffel-tower.avif" type="image/avif">     <source srcset="eiffel-tower.webp" type="image/webp">     <img src="eiffel-tower.jpg" alt="Эйфелева башня. Вид с реки Сены">   </picture> </body> 

Если браузер поддерживает AVIF-формат, то загрузится первое изображение. Если нет, то браузер проверит, можно ли погрузить WEBP-версию. Если можно, то она будет загружена. Если нет, то уже JPG-версия.

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

.container {   background-image: image-set(     url("eiffel-tower.avif") type("image/avif"),     url("eiffel-tower.webp") type("image/webp"),     url("eiffel-tower.jpg") type("image/jpeg")); } 

Алгоритм работы точно такой же, как в случае с элементом <picture>. Надеюсь, этот подход станет постоянным для вас. Только представьте, насколько быстрее станет ваше приложение. Оно будет как Флэш!

▍ Функция local() экономит трафик пользователя

При оптимизации скорости загрузки страницы, кроме изображений, ещё значительным пунктом являются шрифты. Поскольку они весят много. И каково было моё удивление, когда я узнал о существовании функции local().

В чём суть. С помощью функции мы можем проверить, установлен ли нестандартный шрифт на устройстве пользователя. Если установлен, то не загружать его по сети. Для этого её нужно использовать при объявлении правила @font-face. Например, я подключаю шрифт Cherry Bomb One.

@font-face {   font-family: 'Cherry Bomb One';   font-style: normal;   font-weight: 400;   font-display: swap;   src: local("CherryBombOne Regular"),        local("CherryBombOne-Regular"),        url("CherryBombOne-Regular.woff2") format('woff2'); } 

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

▍ Более надёжные кастомные чекбоксы с псевдо-классом focus-within

Каждый верстальщик делал или сделает кастомный чекбокс. Как у любого элемента управления, нам нужно стилизовать состояние focus. Большинство примеров строятся на использовании соседнего родственного комбинатора +.

<body>   <div class="custom-checkbox">     <input id="cb" type="checkbox" class="custom-checkbox__input">     <label class="custom-checkbox" for="cb">Запомнить данные</label>   </div> </body> 

.custom-checkbox__input:focus + .custom-checkbox__label::before {   outline: 3px solid #222; } 

Есть специалисты, которые нашли недостаток этого способа. По их мнению, часто происходит так, что люди случайно вставляют элемент <input> в другое место. По этой причине селектор перестаёт работать.

Думая над решением этой проблемы, ко мне пришла мысль: «А почему бы не заменить соседнего родственного комбинатора + на псевдо-класс focus-within?». Ведь данный псевдо-класс срабатывает, когда сам элемент или кто-то из его дочерних элементов находится в фокусе. И в случае использования его в нашей задаче, получится так, что позиция элемента <input> неважна.

Заменим фрагмент кода с комбинатором + на псевдо-элемент :focus-within.

.custom-checkbox:focus-within .custom-checkbox__label::before {   outline: 3px solid #222; } 

Мне кажется, даже код выглядит «красивее». А вы как думаете? Напишите в комментариях.

▍ Пользовательские CSS-свойства спасают от «причуд» дизайнеров

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

Представим абстрактные разделы на странице. Например, «О нас», «Наши проекты» и «Контакты».

<body>   <section class="section" aria-labelledby="about-us-heading">     <h2 id="about-us-heading">О нас</h2>     <!-- здесь контент раздела -->   </section>   <section class="section" aria-labelledby="projects-heading">     <h2 id="projects-heading">Наши проекты</h2>     <!-- здесь контент раздела -->   </section>   <section class="section section_size-l" aria-labelledby="contacts-heading">     <h2 id="contacts-heading">Контакты</h2>     <!-- здесь контент раздела -->   </section> </body> 

Дизайнер захотел так, чтобы у первых двух разделов отступ от верхней границы раздела и заголовка был 2.5rem, а у последнего — 5rem. Я создам класс .section, в котором определю наиболее часто встречающееся значение 2.5rem. А для значения 5rem буду использовать класс section_l.

.section {   padding-top: 2.5rem; }  .section_size-l {   padding-top: 5rem; } 

Всё работает, как задумывалось. Только в коде есть проблема. Если случайно правила поменяются местами, то у нас будет ошибка. Значение 2.5rem переопределит значение 5rem. В итоге у раздела «Контакты» будет неправильный отступ.

.section_size-l {   padding-top: 5rem; }  .section {   padding-top: 2.5rem; } 

В такие моменты к нам на выручку приходят пользовательские CSS-свойства. При правильном их использовании мы можем перестать зависеть от порядка правил. Всё сводится к нескольким деталям.

Во-первых, нам нужно определить их для основного элемента.

.section {   padding-top: var(--section-padding-gap); } 

Второй шаг заключается в том, что нужно определить значение по умолчанию. Я предлагаю использовать наиболее часто встречающиеся. В моём примере это 2.5rem.

.section {   padding-top: var(--section-padding-gap, 2.5rem); } 

Последний шаг — определить значение для класса .section_l не через свойство padding, а через пользовательское свойство --section-padding-gap.

.section {   padding-top: var(--section-padding-gap, 2.5rem); }  .section_size-l {   --section-padding-gap: 5rem; } 

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

Создам класс .section_size-xl и добавлю его для раздела «Наши проекты».

<body>   <section class="section" aria-labelledby="about-us-heading">     <h2 id="about-us-heading">О нас</h2>     <!-- здесь контент раздела -->   </section>   <section class="section section_size-xl" aria-labelledby="projects-heading">     <h2 id="projects-heading">Наши проекты</h2>     <!-- здесь контент раздела -->   </section>   <section class="section section_size-l" aria-labelledby="contacts-heading">     <h2 id="contacts-heading">Контакты</h2>     <!-- здесь контент раздела -->   </section> </body> 

.section_size-l {   --section-padding-gap: 5rem; }  .section {   padding-top: var(--section-padding-gap, 2.5rem); }  .section_size-xl {   --section-padding-gap: 7.5rem; } 

Отлично. Работает. Данный лайфхак полезен при вёрстке новых проектов или при рефакторинге. Им можно задавать отступы, размеры текста, цвет, да вообще всё. Я использовал его для лендингов, дизайн-систем и проектов с сотней компонент. Он выручал меня везде.

▍ Заключение

Давайте подведём итог. Сегодня мы можем с помощью CSS:

  • использовать дескрипторы плотности пикселя экрана для отображения специальных фоновых изображений в свойстве background-image;
  • загружать более лёгкие форматы изображения при оптимизации скорости загрузки страницы;
  • подсказать браузерам, что нужно проверить, установлен ли нестандартный шрифт на пользовательском устройстве, чтобы избежать его загрузки;
  • сделать более надёжными кастомные чекбоксы;
  • использовать пользовательские CSS-свойства для упрощения поддержки кода.

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

Оставляю ссылки на все выпуски:

P.S. Присоединяйтесь к моему ТГ каналу CSS isn’t magic. Ссылка в профиле.

Telegram-канал со скидками, розыгрышами призов и новостями IT ?


ссылка на оригинал статьи https://habr.com/ru/articles/803757/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *