
Привет, Хабр!
Я люблю помогать фронтендерам больше узнать о HTML и CSS. Общаясь, я составил список HTML и CSS фич, которые полезные, но почему-то о них мало кто знает. В этой статье я пришёл поделиться ими.
Давайте посмотрим, что я вам подготовил.
Элемент search
Поиск — один из самых используемых элементов. Сложно найти более-менее популярный сервис, у которого нет поиска. Так что верстать его это обычная задача.
В целом хорошо в разметке использовать элемент form. В него вложить элемент input и button. Для примера я скопировал HTML со страницы популярного маркетплейса и оставил основные элементы.
<body> <form action="/search"> <!-- Текст для атрибута placeholder изменён для статьи --> <input placeholder="Искать на сайте" type="text"> <button type="submit" aria-label="Поиск"><!-- Здесь иконка лупы --></button> </form> </body>
Только в такой разметке есть проблема. Пользователи с особенностями зрения не сразу поймут, что это поиск. Для них это форма, потому что для скринридеров это так. Конечно, они не дураки. Дополнительно потыкают на элементы и потом поймут, что форма является поиском.
Несколько лет назад в стандартах появился замечательный элемент search. Его задача — показать область страницы, в которой есть элементы, связанные с поиском или фильтрацией.
Давайте добавим его в нашу разметку.
<body> <search> <form action="/search"> <!-- Текст для атрибута placeholder изменён для статьи --> <input placeholder="Искать на сайте" type="text"> <button type="submit" aria-label="Поиск"><!-- Здесь иконка лупы --></button> </form> </search> </body>
Вот теперь так лучше. Скринридеры поймут, что перед ними поиск, и сообщат пользователям.
Атрибут enterkeyhint
Как фронтендеры, мы не можем влиять на то, как будет отображена виртуальная клавиатура. Почти не можем. Одна возможность у нас всё-таки есть!
Давайте сразу перейдём к примеру. Я создал разметку для формы, состоящей из полей для ввода имени и пароля.
<body> <form> <div class="field"> <label class="field__label" for="login">Логин</label> <input class="field__input" type="text" id="login"> </div> <div class="field"> <label class="field__label" for="password">Пароль</label> <input class="field__input" type="password" id="password"> </div> <button type="submit">Отправить</button> </form> </body>
Начав заполнять пароль, я увижу в правом нижнем углу кнопку. Она подписана, как «Перейти».

Я предлагаю изменить эту подпись. Поможет в этом атрибут enterkeyhint.
Мне кажется, что в моём примере лучше подходит подпись «Отправ.». Для этого укажу для поля ввода пароля атрибут со значением send.
<body> <form> <div class="field"> <label class="field__label" for="login">Логин</label> <input class="field__input" type="text" id="login"> </div> <div class="field"> <label class="field__label" for="password">Пароль</label> <input class="field__input" type="password" id="password" enterkeyhint="send"> </div> <button type="submit">Отправить</button> </form> </body>
Как видите, теперь в правом нижнем углу отображается нужная подпись. А главный прикол в том, что если язык интерфейса будет английский, то подпись поменяется сама. Мы увидим «Send».

К сожалению, мы не можем использовать любую подпись. Всего есть семь предопределённых значений. Это enter, done, go, next, previous, search и send. Из них можно выбирать.
Несмотря на скромное количество доступных вариантов, я считаю этот атрибут отличным микроулучшением. Он позволяет использовать более контекстно-ориентированную подпись. Это улучшает пользовательский опыт. Что супер!
Отдельные свойства трансформации rotate, translate и scale
Представим, что перед вами стоит задача сделать анимацию. В ней требуется вращать элемент вокруг своей оси и одновременно плавно приближать и отдалять его.
Понятно, что вы будете использовать свойство animation и правило @keyframes. Но мне интересно, какими свойствами вы реализуете трансформации.
Допустим, вы выберете свойство transform с функциями rotate() и scale().
.awesome-block { width: 2rem; height: 2rem; background-color: tomato; animation: rotation 5s infinite; } @keyframes rotation { 0%, 100% { transform: rotate(0deg) scale(0); } 25%, 75% { transform: rotate(0deg) scale(1); /* на этом этапе мне нужен 0deg. Поэтому я вынужден использовать rotate(0deg). Без этого браузеры уже рассчитают другое значение */ } 50% { transform: rotate(360deg) scale(1); /* здесь мне нужен масштаб 1. Для этого я использую scale(1). Без этого браузеры будут рассчитывать другое значение */ } }
В этой реализации обязательно требуется дублировать значения rotate(0deg) и scale(0). Без этого анимация не получится, потому что переопределение значения для свойства transform сломает её.
Так что если вы до сих пор делаете так, то у меня есть кое-что новое. А именно свойства translate, rotate и scale.
Они являются полной альтернативой функциям translate(), rotate() и scale(). Таким образом длинное значение для свойства transform из предыдущего кода можно легко сократить.
.awesome-block { width: 2rem; height: 2rem; background-color: tomato; animation: rotation 5s infinite; } @keyframes rotation { 0%, 100% { scale: 0; } 25%, 75% { rotate: 0deg; scale: 1; } 50% { rotate: 360deg; } }
Как же лаконично! У меня постоянное случалась ситуация, когда значение свойства transform не умещалось в одну строку. Приходилось дробить его на несколько строк. Жутко бесило. По этой причине я быстренько перешёл на отдельные свойства трансформации. Вам тоже советую!
Значение contents
При работе с позиционированием или определением размеров элементов, я всегда мечтал о способе стилизовать дочерний элемент, игнорируя его непосредственного родителя. И мои мечты сбылись!
Для демонстрации мы разберём пример. У нас будет элемент button, который будет вложен в несколько элементов.
<body> <div class="intro"> <div class="intro__container"> <button type="button" class="intro__control">Показать</button> </div> </div> </body>
.intro { display: grid; }
Представим, по дизайну нужно растянуть кнопку на всю ширину элемента с классом .intro. Поскольку у него уже используется свойство display со значением grid, то его дочерние именно это и делают. Но, к сожалению, не элемент button, поскольку он не прямой потомок.
Давайте его таким сделаем! Для этого есть значение contents для свойства display. Его применим к элементу с классом .intro__container.
.intro { display: grid; } .intro__container { display: contents; }

Идеально! Работает, как задумано. Главное, в этом решении используются встроенные возможности свойства display. Я люблю такую лаконичность.
Псевдо-класс :nth-child()
За мои тринадцать лет в вёрстке я убедился, что даже в самых привычных вещах всегда найдётся что-то новое. Недавно, готовя материал о синтаксисе of S для псевдо-класса :nth-child, я снова ощутил это на собственном опыте.
Казалось бы, я работаю с этим псевдо-классом уже более десяти лет, но всё равно обнаружил для себя кое-что совершенно неожиданное. Рассмотрим пример с разметкой из нескольких элементов.
<body> <span class="awesome-box">1</span> <span class="awesome-box">2</span> <span class="awesome-box">3</span> <span class="awesome-box">4</span> <span class="awesome-box">5</span> </body>
У меня к вам вопрос: «Как написать стили так, чтобы они применялись от второго до четвёртого элемента?».
Ещё месяц назад мне казалось невозможным реализовать это без добавления дополнительных классов. Всегда, в течение моей карьеры, я сталкивался только с таким подходом. Но сегодня я раскрою секрет. Мы можем использовать комбинацию псевдо-классов :nth-child, создав диапазон элементов.
Для демонстрации сделаю так, чтобы свойство outline применялось, начиная со второго и заканчивая четвёртым элементом.
.awesome-box:nth-child(n+2):nth-child(-n+4) { outline: 4px dashed coral; outline-offset: 5px; }

Первый псевдо-класс, :nth-child(n+2), устанавливает счётчик, который начинает отсчёт с 2 и увеличивается. Таким образом, мы определяем минимальное значение для нашего диапазона.
Максимальное значение достигается благодаря второму псевдо-классу :nth-child(-n+4). Объявив -n, я сделал так, чтобы счётчик в нём работал в обратном направлении, начиная с 5.
В результате браузеры используют пересечение значений этих счётчиков для поиска нужных элементов, выделяя таким образом все элементы, начиная со второго и заканчивая четвёртым.
Свойства text-decoration и text-underline-offset
Как я заметил, многие фронтендеры знают два, три способа создать подчёркивание у ссылки. Обычно называется свойство border, а потом метод с помощью псевдо-элементов.
Потом я спрашиваю: «А можно ли использовать свойство text-decoration?». Тут у людей ступор. Они либо вообще ни разу не использовали это свойство, кроме случая сброса стандартного подчёркивания у ссылок, либо говорят, что оно ограниченное. А дальше начинается мой рассказ о том, чем свойство text-decoration полезно.
Вы чаще всего встречаете его у ссылок, когда сбрасывается подчёркивание по умолчанию с помощью значения none. Действительно, раньше это был единственный полезный кейс, потому что свойство отвечало только за вид линии.
Теперь же оно дополнительно позволяет определить толщину, стиль и цвет линии. За всё это отвечают свойства: text-decoration-line (вид), text-decoration-thickness (толщина), text-decoration-style (стиль) и text-decoration-color (цвет). Они являются частями свойства text-decoration.
a:not([class]) { text-decoration: underline 2px solid purple; /* свойство text-decoration разворачивается в следующие свойства: text-decoration-line: underline; text-decoration-thickness: 2px; text-decoration-style: solid; text-decoration-color: purple; */ }
Также у свойства text-decoration есть классный напарник — свойство text-underline-offset. С помощью него мы можем задать позицию подчёркивания.
a:not([class]) { text-decoration: underline 2px solid purple; text-underline-offset: 4px; }
Данная парочка очень полезна, когда нужно сделать простое подчёркивание текста. Например, у ссылок в контентных частях страницы. Когда не нужна анимация.
Заключение
Давайте подведём итог. В этой статье мы рассмотрели:
возможность изменения виртуальной клавиатуры с помощью атрибута
enterkeyhint,значение
contents, позволяющее пропустить родительский элемент,технику диапазонов элементов с помощью псевдо-класса
:nth-child(),как сделать код лаконичнее благодаря отдельным свойствам трансформации,
создание подчёркивания у текста свойствами
text-decoration-line,text-decoration-thickness,text-decoration-style,text-decoration-colorиtext-underline-offset.
На этом всё. Спасибо за чтение!
P. S. Помогаю больше узнать про CSS в своём ТГ-канале CSS isn't magic. Присоединяйтесь. Ссылка в профиле.
Ещё посмотрите, какие странности есть в CSS, и как их избежать.
© 2025 ООО «МТ ФИНАНС»

