Хабр, привет! Я снова пришёл к вам со статьёй, где показываю мои любимые техники вёрстки. Моя цель — поделиться опытом с вами. Я использую не только трюки известных экспертов, есть лично мои придумки. Но пожалуйста, относитесь к этому контенту, как просто к альтернативному мнению. Мои техники не являются единственными правильными решениями.


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

  • почему декоративные элементы, сделанные с помощью чистого CSS могут не отобразиться в режиме повышенной контрастности Windows;
  • чем можно заменить объявления свойства height со значением auto для изображений;
  • какой есть нюанс при установке максимальной ширины у группы элементов;
  • плавную прокрутку без неприятных ситуаций для пользователя;
  • чего не хватает при использовании фоновых изображений.

Давайте посмотрим, что я вам подготовил.


▍ Свойство border не позволяет пропасть линиям


Мне нравится реализовывать декоративные элементы только с помощью CSS. Чаще всего приходится делать прямолинейную линию. Например, дизайнеры любят её добавлять к заголовкам.


Раздел проекты. Перед заголовком есть сиреневая линия.

Кажется, нет ничего сложного в реализации. Свойства width, height и background-color сделают всю работу.


.heading {
  position: relative;
}

.heading::before {
  content: "";
  width: 5rem;
  height: 2px;
  background-color: #b87eef;

  position: absolute;
  left: 0;
  bottom: 1rem;   
}

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


Раздел проекты. Линия не отображается перед заголовком

Линии не видно. Браузеры в данном режиме насильно добавляют значение для свойства background-color. Оно берётся из настроек операционной системы из пункта «Фон».


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

В итоге получается, что у всех элементов со свойством background-color значение будет одинаковым. По этой причине линия становится незаметной.


Можно, конечно, не париться и оставить пользователей без неё. Правда, этот подход мне не близок. Я стараюсь не ломать задумку дизайнера, если это возможно. Тем более, что в этом случае сделать линию просто. Достаточно использовать свойство border.


Есть два варианта. Первый — само свойство border. Только есть нюанс. Поскольку свойство устанавливает границу со всех сторон, то нам нужно изначальную высоту линии в 2px разделить пополам. И уже полученное значение использовать.


Другой вариант — установить границу только с одной стороны. Для этого использовать либо свойство border-top, либо — border-bottom.


Мне лень делать какие-то вычисления. Хочется сделать просто. По этой причине возьму вариант со свойством border-top. Им заменю свойства height и background-color.


.heading {
  position: relative;
}

.heading::before {
  content: "";
  width: 5rem;
  border-top: 2px solid #b87eef;

  position: absolute;
  left: 0;
  bottom: 1rem;   
}

Линия стала белой и отображается перед заголовком

Линия на месте. Задумка дизайнера сохранилась. Надеюсь, теперь при создании линий вы сохраните их для режима повышенной контрастности Windows.


▍ Да хватит уже переопределять высоту изображений


Прыжки контента — самое раздражительное явление для меня. Знаете, начинаешь читать текст, а он упрыгивает. У данного явления даже есть умное название «Cumulative Layout Shift».


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


По этой причине многие известные разработчики советуют добавлять атрибуты width и height для элемента <img>. Так браузеры узнают размеры области, где им нужно отрисовать изображение.


<body>
  <img src="eiffel-tower.webp" width="600" height="337" alt="Эйфелева башня. Вид с реки Сены">
</body>

В этом способе обязательно нужно сбросить установленное ранее значение у свойства height.


img {
  max-width: 100%;
  height: auto;
}

Я этой рекомендации не следую. Мне кажется странным сначала что-то устанавливать, а потом сбрасывать. Я любитель только устанавливать.


Мой любимый способ — это свойство aspect-ratio. Я даже стал его добавлять по умолчанию ко всем изображениям.


img {
  display: var(--ds-typography-img-display, block);
  max-width: var(--ds-typography-img-max-width, 100%);
  aspect-ratio: var(--ds-typography-img-aspect-ratio);
}

В каждом проекте я устанавливаю нужное мне значение.


img:not([class]) {
  --ds-typography-img-aspect-ratio: 1.78;
}

В моём решении атрибут height больше использовать не нужно.


<body>
  <img src="eiffel-tower.webp" width="600" alt="Эйфелева башня. Вид с реки Сены">
</body>

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


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


Отображается правило с селектором по атрибуту. В нем добавлено свойство aspect-ratio. Значение auto 600 / 337

Браузеры сами устанавливают свойство aspect-ratio, если установлены атрибуты width и height. Получается, я придумал то, что уже было сделано. Надо было только посмотреть в инструменты разработчика.


▍ К какому элементу надо устанавливать максимальную ширину блока


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


Для примера возьмём блок с приветствием на сайте разработчика.


Заголовок, краткий рассказ о себе и кнопка для связи

При вёрстке макета разработчику требуется сделать так, чтобы максимальная ширина всего блока была равна ширине текста с рассказом о себе. Где здесь может быть ошибка?


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


Для демонстрации заменю текст заголовка «Стас Мельников» на «Ростислав Михальниченко».


Заголовок стал шире, чем краткий текст с рассказом о себе

Мы получили результат, когда текст из заголовка занимается больше пространства, чем предполагал дизайнер. В итоге нас бы заставили переделывать. Чтобы такого не происходило, нужно заранее предполагать, как будет меняться текст.


Работая над макетом, дизайнер сразу показывает, какой блок занимает максимальную ширину. Правильным решением будет взять ширину такого блока и добавить её к родительскому блоку. В нашем случае к блоку, где находится заголовок, текст с рассказом о себе и кнопка «Связаться с нами».


Заголовок отображается в две строки. На первой Ростислав, на второй Михальниченко. Он уже, чем блок с кратким рассказом о себе

Подводя итог, сформулирую правило. Максимальную ширину нужно устанавливать родительскому элементу. Значение нужно брать по максимально широкому дочернему элементу.


При таком варианте текст в нашей вёрстке всегда будет сохранять ту ширину, какая есть в макете. Так мы соблюдём все требования.


▍ Сниппет для создания плавной прокрутки без проблем для пользователя


Я постоянно замечаю образовательный контент, в котором авторы используют свойство scroll-behavior. Они используют его для элемента <html> для добавления плавной прокрутки на странице.


html {
  scroll-behavior: smooth;
}

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


По этой причине существует медиафункция prefers-reduced-motion. Она помогает браузерам определить, выключил ли пользователь анимацию движения в настройках операционной системы. Если он это сделал, то медиафункция поможет браузерам не показывать её.


В итоге если используется плавная прокрутка, то свойство scroll-behavior нужно обвернуть медиафункцией prefers-reduced-motion.


@media (prefers-reduced-motion: no-preference) {

  html {
    scroll-behavior: smooth;
  }
}

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


▍ Свойство background-color не даёт тексту и кнопке спрятаться


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


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


Правда есть и плюс. Эта ситуация зародила в моей голове памятку. Она звучит так: «Если есть фоновое изображение, всегда делай контрастный к тексту фон». По этой причине в моём коде всегда рядом со свойством background-image, есть свойство background-color.


.my-awesome-screen {
  background-image: image-set(
    url("eiffel-tower-1x.webp") type("image/webp") 1x,
    url("eiffel-tower-2x.webp") type("image/webp") 2x
  );
  background-color: #919191;
}

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


▍ Заключение


Давайте подведём итог. В этой статье мы рассмотрели:

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

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

Спасибо за чтение!


P.S. Помогаю больше узнать про CSS в своём ТГ-канале CSS isn't magic. Присоединяйтесь. Ссылка в профиле.


© 2024 ООО «МТ ФИНАНС»


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

Комментарии (6)


  1. sfi0zy
    10.09.2024 09:46
    +1

    Указание атрибутов высоты и ширины для картинки в html - это решение, которое легко интегрируется и может работать на стороне сервера для каждой картинки. Сегодня у вас 337 пикселей по высоте, завтра 376, потом 334. Вариант хардкодить aspect-ratio в штатном CSS моментально теряет индивидуальный подход. Старый вариант прост и надежен. Новый же зависит от тех, кто будет заполнять сайт контентом, и может сломаться на ровном месте.


    1. melnik909 Автор
      10.09.2024 09:46

      Сегодня у вас 337 пикселей по высоте, завтра 376, потом 334. Вариант хардкодить aspect-ratio в штатном CSS моментально теряет индивидуальный подход.

      Иван, почему вы говорите "хардодить"? Через пользовательские свойства можно все изменить. Поясните, пожалуйста


      1. sfi0zy
        10.09.2024 09:46

        Т.е. вы предлагаете на стороне сервера задавать CSS custom properties в inline-стилях? Это, конечно, интересный подход, но он выглядит сложным для восприятия. Прелесть пикселей в том, что они никак не зависят от технологий и контекстов и при этом надежно решают изначальную задачу. А custom properties создаст зависимости между штуками на клиенте и сервере, которые вообще ничего про друг друга знать не должны. Магия CSS красива до тех пор, пока она не завязана на сервер.


  1. Spaceoddity
    10.09.2024 09:46

    Не, ну рекомендация инлайновых стилей в 2024 - это, конечно, за гранью уже...

    Я, конечно, понимаю ваш восторг по поводу новых css-свойств, но привязываться к соотношению сторон и фигачить разметку в структуру кода - какой-то просто-напросто вредный совет!

    Ну есть же object‑fit...

    Вообще тема с размерами элементов настолько необъятная... Там столько подводных камней... Целый цикл статей нужен только по одной этой теме!


    1. melnik909 Автор
      10.09.2024 09:46

      Я, конечно, понимаю ваш восторг по поводу новых css-свойств, но привязываться к соотношению сторон и фигачить разметку в структуру кода

      Эту мысль совсем не понял. Поясните, пожалуйста, что вы имеете ввиду?


    1. ionicman
      10.09.2024 09:46

      Не, ну рекомендация инлайновых стилей в 2024 - это, конечно, за гранью уже...

      Конечно! Лучше все тащить в стили, даже если это единоразово для какого-то фикса и короче class="something", и да - обязательно SASS. Про производительность и progressive enhancement тоже надо забыть в 2024, да? ))) Любители догм.

      И хоть я и не оборяю aspect-ratio для этого тоже, object-fit, если что, вообще не про указывание высоты - так, на всякий.