
Привет, Хабр!
Я люблю помогать фронтендерам больше узнать о 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 ООО «МТ ФИНАНС»