Хабр, привет! Я снова пришёл к вам со статьёй, где показываю мои любимые техники вёрстки. Моя цель — поделиться опытом с вами. Я использую не только трюки известных экспертов, есть лично мои придумки. Но пожалуйста, относитесь к этому контенту, как просто к альтернативному мнению. Мои техники не являются единственными правильными решениями.
Сегодня мы рассмотрим:
- почему декоративные элементы, сделанные с помощью чистого 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
. Оно берётся из настроек операционной системы из пункта «Фон».
В итоге получается, что у всех элементов со свойством 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
, если установлены атрибуты 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 ?
Комментарии (31)
Spaceoddity
10.09.2024 09:46Не, ну рекомендация инлайновых стилей в 2024 - это, конечно, за гранью уже...
Я, конечно, понимаю ваш восторг по поводу новых css-свойств, но привязываться к соотношению сторон и фигачить разметку в структуру кода - какой-то просто-напросто вредный совет!
Ну есть же
object‑fit
...Вообще тема с размерами элементов настолько необъятная... Там столько подводных камней... Целый цикл статей нужен только по одной этой теме!
melnik909 Автор
10.09.2024 09:46Я, конечно, понимаю ваш восторг по поводу новых css-свойств, но привязываться к соотношению сторон и фигачить разметку в структуру кода
Эту мысль совсем не понял. Поясните, пожалуйста, что вы имеете ввиду?
Spaceoddity
10.09.2024 09:46+1Что именно вам не понятно в этой фразе?
Привязываться к соотношению сторон - некорректно. Потому что при одном разрешении картинка, например, может иметь квадратную форму, а при другом - прямоугольную.
Вот как это понимать - В каждом проекте я устанавливаю нужное мне значение...
--ds-typography-img-aspect-ratio: 1.78
?У вас в проекте все изображения с одинаковым соотношением сторон? Серьёзно?
Ну а про инлайновые стили вам уже выше объяснили.
melnik909 Автор
10.09.2024 09:46+1Мне не понятна эта фраза "фигачить разметку в структуру кода". Поясните?
Вот как это понимать - В каждом проекте я устанавливаю нужное мне значение...
--ds-typography-img-aspect-ratio: 1.78
?Как пример того, как задаются значение для свойств. Если вам не понравился мой пример, то он из моего проекта. Так я задаю стили для изображений, у которых нет атрибута class.
У вас в проекте все изображения с одинаковым соотношением сторон? Серьёзно?
У меня в проектах много, что есть. Есть блоки, где изображения одного размера. Есть блоки, в которых другого размера.
Вы конкретнее сформулируйте свой вопрос. Я отвечу.
P.S. Отдельно хочу поблагодарить вас за чтение моих статей. Вы ни одной не пропускаете. Мне приятно. Спасибо
Spaceoddity
10.09.2024 09:46Мне не понятна эта фраза "фигачить разметку в структуру кода". Поясните?
Ну инлайновые стили же.
P.S. Отдельно хочу поблагодарить вас за чтение моих статей. Вы ни одной не пропускаете. Мне приятно. Спасибо
Немножко сарказмом пахнуло)) Ну да ладно, возможно мне показалось. А что тут удивительного? Я на тех же материях специализируюсь - разумеется у меня в ленте будут ваши статьи. Как минимум, чтобы не пропустить что-то новое/вкусное. К сожалению, статьи по вёрстке на Хабре в последнее время очень редки - вы вроде единственный кто с завидным постоянством что-то пишет по этой теме. Так что это вам респект! ;) Да, кое с чем я бываю не согласен (ну у меня свой "верстальный бэкграунд"), но кое-что и я бывает схороню))
melnik909 Автор
10.09.2024 09:46Ну инлайновые стили же.
Все, дошло. Моя цель поделиться тем, что мне кажется интересным. Я об этом пишу во вступлении. Я не говорю, что мой способ самый лучший. Но я хочу, чтобы о нем узнали, потому что для него есть случаи, когда он может быть полезен.
Немножко сарказмом пахнуло)) Ну да ладно, возможно мне показалось.
Никакого сарказма. Вам показалось. На Хабре есть несколько человек, включая вас, постоянно читающих и комментирующих. Я ценю это.
Так что это вам респект! ;) Да, кое с чем я бываю не согласен (ну у меня свой "верстальный бэкграунд"), но кое-что и я бывает схороню))
Спасибо. Как раз для этого я занимаюсь контентом.
ionicman
10.09.2024 09:46+1Не, ну рекомендация инлайновых стилей в 2024 - это, конечно, за гранью уже...
Конечно! Лучше все тащить в стили, даже если это единоразово для какого-то фикса и короче class="something", и да - обязательно SASS. Про производительность и progressive enhancement тоже надо забыть в 2024, да? ))) Любители догм.
И хоть я и не оборяю aspect-ratio для этого тоже, object-fit, если что, вообще не про указывание высоты - так, на всякий.
Spaceoddity
10.09.2024 09:46Что это вас так порвало?))
Да, лучше! Это всё обсосано было ещё лет 20 назад. И причём здесь SASS вообще? Есть такое понятие - семантика. Любители всего нового. Вот и имеем кадавров а-ля CSS-in-JS...
И на всякий случай вам - aspect-ratio, если что, вообще не про указывание высоты ;)
ionicman
10.09.2024 09:46Что это вас так порвало
Не надо мне ваше состояние приписывать)
Про SASS был сарказм, спасибо что не поняли)
Что такое семантика, вы, судя по тому что пишите - не знаете.
aspect-ratio, если что, вообще не про указывание высоты
Ага, но я отвечал про ваш object-fit, а не на автора)
Spaceoddity
10.09.2024 09:46Про SASS был сарказм, спасибо что не поняли)
Вообще не понял. Тут то адепты препроцессоров, то лютые противники встречаются. Я не слепая мёртвая болгарская бабка.
Что такое семантика, вы, судя по тому что пишите - не знаете.
Аналогично;) Но судя по вашей "аргументации" в стиле "сам дурак" - даже распинаться не имеет смысла. Зашёл в тред, нагадил в комментах, перешёл на личности и слился)) В игнор!
Кстати, пишЕте - это не просто орфографическая ошибка. Это как раз семантическая ошибка))
Ага, но я отвечал про ваш object-fit, а не на автора)
Ага, только я-то отвечал не вам. Учить он меня вёрстке будет)))
sfi0zy
Указание атрибутов высоты и ширины для картинки в html - это решение, которое легко интегрируется и может работать на стороне сервера для каждой картинки. Сегодня у вас 337 пикселей по высоте, завтра 376, потом 334. Вариант хардкодить
aspect-ratio
в штатном CSS моментально теряет индивидуальный подход. Старый вариант прост и надежен. Новый же зависит от тех, кто будет заполнять сайт контентом, и может сломаться на ровном месте.melnik909 Автор
Иван, почему вы говорите "хардодить"? Через пользовательские свойства можно все изменить. Поясните, пожалуйста
sfi0zy
Т.е. вы предлагаете на стороне сервера задавать CSS custom properties в inline-стилях? Это, конечно, интересный подход, но он выглядит сложным для восприятия. Прелесть пикселей в том, что они никак не зависят от технологий и контекстов и при этом надежно решают изначальную задачу. А custom properties создаст зависимости между штуками на клиенте и сервере, которые вообще ничего про друг друга знать не должны. Магия CSS красива до тех пор, пока она не завязана на сервер.
melnik909 Автор
Иван, я пока не предлагаю, а спрашиваю, что вы имели ввиду. В частности, почему вы использовали слово "хардкодить". Ответьте, пожалуйста
sfi0zy
Вот это:
чистой воды хардкод.Посмотрите на картинки прям здесь, на хабре. Даже в вашей статье они все разных пропорций. Жестко заданное 1.78 тут не прокатит. Эту property можно переписать на сервере под каждое изображение индивидуально, но получим то, что описано выше.
melnik909 Автор
Спасибо. Теперь я понял. По моей практике изображения специально подготавливают. В этом случае проблем я лично не вижу. Может вы видите?
Конечно, так было не всегда. Пример с Хабром тот случай, когда мой способ может не подойти. Я же не говорил, что мой способ универсальный и подходит для всего.