
Привет, Хабр.
Мне нравится, когда красивые и дружелюбные интерфейсы радуют пользователя. Хоть я уже не создаю их, но я стараюсь помочь коллегам создавать более качественный пользовательский опыт. И, конечно, с вами тоже всегда рад поделиться идеями.
Сегодня хочу рассказать про простые CSS-техники, которые помогут сделать любой интерфейс более дружелюбным к пользователю. Не важно, какие фреймворки и библиотеки вы используете. Мои советы универсальны и могут быть реализованы везде.
Давайте посмотрим, что я вам подготовил.
Функция image-set() поможет адаптировать фоновые изображения для экранов с разной плотностью пикселя
Мы привыкли использовать элемент picture для адаптации изображений под экраны с разной плотностью пикселя. Но почему-то мало кто так делает с декоративными изображениями. Очень зря!
Вы можете оптимизировать загрузку фоновых изображений с помощью функции image-set(). Для демонстрации сделаем это для экранов с обычной плотностью пикселя и с двойной.
.awesome-screen-hero { background-image: image-set( url("awesome-hero-background-1x.webp") type("image/webp") 1x, url("awesome-hero-background-2x.webp") type("image/webp") 2x ); background-color: #919191; }
Псевдо-класс ::spelling-error поможет пользователю найти опечатки в словах
Я постоянно делаю опечатки. Думаю, если вы читаете мои статьи, то заметили это. По этой причине я особенно люблю новый псевдо-класс ::spelling-error. Он позволяет выделить слово, если в нём есть опечатка.
::spelling-error { background-color: rgba(255, 42, 81, 0.2); text-decoration: underline 1px wavy rgba(255, 42, 81, 1); text-underline-offset: 3px; }
Псевдо-классы :user-valid и :user-invalid помогают стилизовать элементы формы при валидации
Стилизация элементов форм при валидации — важная штука. Нужно же показывать сообщения об ошибке или выделять поля соответствующим цветом. Раньше приходилось использовать JavaScript, а теперь для этой задачи отлично подходят псевдо-классы :user-valid и :user-invalid.
input:user-invalid { box-shadow: 0 0 1rem red; } input:user-valid { box-shadow: 0 0 1rem green; }
Свойство background-color не позволяет спрятаться контенту при загрузке фоновых изображений
Фоновые изображения могут очень долго загружаться. Или вообще не отобразиться. По этой причине стандартный набор стилей может привести к тому, что контент сольётся с основным фоном страницы.
В итоге пользователи получат игру, в которой нужно найти белые буквы на белом фоне.
.page { color: #fefefe; } .page__banner { background-repeat: no-repeat; background-size: cover; background-image: url("awesome-hero-background.jpg"); }
Мне нравится, когда для исправления этой проблемы разработчики добавляют контрастный фон под фоновое изображение. Это поможет контенту быть заметным даже тогда, когда изображение ещё не загрузилось.
.page { color: #fefefe; } .page__banner { background-repeat: no-repeat; background-size: cover; background-image: url("awesome-hero-background.jpg"); background-color: #222; }
Анимации без необязательной перерисовки можно сделать с помощью свойств трансформации
Анимации могут привести к проблемам в производительности, если вы используете свойства, вызывающие перерисовку элемента. Например, так произойдёт со свойством left.
.awesome-block { width: 2rem; height: 2rem; background-color: lightblue; position: absolute; animation: move 5s infinite alternate; } @keyframes move { 0% { left: 0; } 100% { left: 2rem; } }
Это отлично видно, если включить в инструментах разработчика функцию «Paint flashing». Это поможет нам заметить, что элемент постоянно отображается зелёным, т.е. перерисовывается.

Хорошо, что эту ошибку можно исправить. Достаточно использовать свойства трансформации, такие как transform, translate, scale и rotate. Браузеры не перерисовывают их при анимации.
В нашем примере отлично подойдёт свойство translate.
.awesome-block { width: 2rem; height: 2rem; background-color: lightblue; position: absolute; animation: move 5s infinite alternate; } @keyframes move { 0% { translate: 0; } 100% { translate: 2rem; } }
Медиа-функция prefers-reduced-motion спасает пользователей от неожиданной тошноты и головной боли
Многие любят плавную прокрутку, и хорошо, что её реализуют с помощью свойства scroll-behavior.
html { scroll-behavior: smooth; }
Я уверен, что вы встречали такую реализацию. Только есть нюанс. В данном решении плавная прокрутка будет всегда, даже если пользователи её отключили в операционной системе.
Давайте уважать их выбор. Добавим плавную прокрутку так, чтобы она работала только тогда, когда она не отключена в настройках операционной системы. Для этого достаточно объявить медиа-функцию prefers-reduced-motion со значением no-preference.
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }
Также медиа-функция будет полезна, если вы делаете анимацию приближения и отдаления элемента с помощью свойства scale или свойства transform с функцией scale().
Ключевое слово system-ui делает альтернативный шрифт красивым
Многие привыкли указывать семейство sans-serif в качестве альтернативного шрифта.
body { font-family: 'Roboto', sans-serif; }
В итоге пользователи операционной системы Windows видят известный мемный шрифт Times New Roman. Не мне рассказывать, насколько он страшный.
Уже давно в операционных системах есть более красивые шрифты. Давайте их использовать. Для этого объявите ключевое слово system-ui. Тогда браузер будет использовать красивый шрифт из операционной системы, если по какой-то причине основной не загрузится.
body { font-family: 'Roboto', system-ui; }
Привычка дублировать стили при наведении для сфокусированного состояния мешает пользователям клавиатуры
Если к вам попал макет дизайна, в котором нет фокусированного состояния у интерактивных элементов, то к вам может прийти идея продублировать стили из состояния наведения. Например, у вашей ссылки меняется фон при наведении, и вы также сделаете это для фокусированного состояния.
a:hover, a:focus-visible { background-color: #fed330; } /* или так a:is(:hover, :focus-visible) { background-color: #fed330; } */
Пожалуйста, не надо так делать. Я как пользователь клавиатуры могу сказать, что, когда вы используете стили при наведении для сфокусированного состояния, их очень часто сложно заметить. Также такой подход приводит к тому, что постоянно нужно думать: «А почему ссылка поменяла фон?»
Лучше добавьте обводку с помощью свойства outline, которая будет для всех интерактивных элементов одинаковой. Также используйте свойство outline-offset. Оно не даст обводке слиться с фоном элемента.
a:hover { background-color: #fed330; } a:focus-visible { outline: 2px solid #fed330; outline-offset: 3px; }
Медиа-функция forced-colors помогает правильно использовать свойство outline со значением none
Буду честен. Обводка из предыдущего способа может не понравится дизайнеру или менеджменту. Скорее всего, вас заставят сделать нестандартную обводку с помощью свойства box-shadow. В итоге вы добавите свойство outline со значением none.
a:focus-visible { outline: none; box-shadow: 0 0 2px 3px lightblue; }
Можно спорить с ними, что такой способ не очень хорош. Я на вашей стороне. Да, обводка не отобразится в специальных режимах операционных систем, используемых людьми с особенностями зрения. Это, безусловно, плохо.
Поэтому давайте поступим хитрее. Мы отключим обводку, созданную свойством outline, для дизайнера, а для специальных режимов добавим её с помощью медиа-функции forced-colors. Так мы угодим коллегам и пользователям.
a:focus-visible { outline: none; box-shadow: 0 0 2px 3px lightblue; } @media (forced-colors: active) { a:focus-visible { outline: 2px solid #fed330; outline-offset: 3px; } }
Заключение
Давайте подведём итог. В этой статье мы рассмотрели:
дублирование стилей при наведении для сфокусирования состояния не заменяет стандартную обводку, созданную с помощью свойства
outline;правильное использование свойства
outlineсо значениемnoneбез создания проблем длядля пользователей специальных режимов высокой контрастности;функцию
image-set, позволяющая загружать специальные изображения для экранов с разной плотностью пикселей;добавление свойства
background-colorк элементу с фоновым изображением;почему свойства трансформации
transform,translate,scaleиrotateлучше подходят для создания анимации;псевдо-класс
::spelling-error, помогающий подсветить слово с опечаткой;использование свойства
scroll-behaviorбез создания неприятных сюрпризов для пользователей;стилизацию элементов форм при валидации с помощью псевдо-классов
:user-validи:user-invalid;ключевое слово
system-uiпозволяющее использовать стандартный шрифт из операционной системы в качестве альтернативы к основному.
Вот такой список лайфхаков у меня получился. Надеюсь, вы нашли что-то полезное для себя и внедрите в свои проекты.
Ещё мне интересно будет узнать, что я упустил. Поделитесь, пожалуйста, в комментариях своими лайфхаками для улучшения пользовательского опыта.
На этом всё. Спасибо за чтение!
P. S. Помогаю больше узнать про CSS и дружелюбные интерфейсы в своих закрытых ТГ-каналах CSS isn't magic и UX + Dev = a11y. Присоединяйтесь. Как вступить, написано в профиле.
© 2026 ООО «МТ ФИНАНС»

