
Привет, Хабр!
Давно я ничего не писал для джунов. А ведь HTML и CSS не стали проще для них. Всё так же есть сложности, и мне надо как-то помочь людям.
Я выделил несколько привычек, от которых лучше избавиться в самом начале карьеры фронтендера — главное, просто сделать это. Надеюсь, вам будет полезно.
Давайте посмотрим, что я вам подготовил.
Не думать о порядке интерактивных элементов
Обращаете ли вы внимание на расположение элементов? Например, вы верстаете модальное окно.

Где в разметке вы расположите кнопку, которая будет закрывать его?
Обычно разработчики оценивают визуально. Как элементы находятся в макете, так они их переносят в код.

Проблема заключается в том, что при таком стиле написания HTML мы не задумываемся о пользователях. Для примера расскажу о себе.
У меня есть травма руки. Я очень редко использую мышку. В основном переключаюсь клавиатурой. Представим, что я захотел авторизоваться с помощью формы из нашего примера.
Первым элементом, на который я попаду клавишей Tab, будет кнопка «Закрыть». Так получится, потому что в разметке она находится первым интерактивным элементом. Потом уже идут элементы input и другие.
Более дружелюбным было бы сделать так, чтобы пользователь попал на поле ввода телефона. Для этого нужно поменять местами элементы button и form.
<body>
<!-- элементы -->
<div class="app-catalog-2nyjv3-Content--StyledContent">
<form method="post">
<!-- здесь элементы формы -->
</form>
<button class="e1ag7yxm0" type="button">
<!-- здесь иконка и подпись -->
</button>
</div>
<!-- элементы -->
</body>
В этом случае я попаду на первый элемент input после нажатия клавиши Tab. Сразу смогу ввести номер телефона и авторизоваться. Красота!
Так что обязательно задумывайтесь о том, в каком порядке идут интерактивные элементы. Ваши пользователи мысленно поблагодарят вас.
Использовать неинформативные значения для атрибута alt
Я заметил у джунов одну замечательную штуку. Они стараются следовать всем лучшим практикам, которые могут найти. Но поскольку они недавно начали разрабатывать, им не хватает опыта в применении этих практик.
Взять, к примеру, атрибут alt. Очень много информации, говорящей о том, что его всегда нужно заполнять. В результате на практике я встречаю разные примеры.
<body>
<img src="pic.webp" alt="Аватар пользователя" height="90" width="90">
</body>
Пожалуйста, не надо так. Я уважаю ваше стремление к тому, что вы думаете о пользователях скринридера. Но в этих случаях вы делаете медвежью услугу. Хотите как лучше, а получается плохо.
Проблема заключается в том, что такие описания не несут полезной информации. Но почему многие разработчики так делают? Да, потому что они не знают, что вписать в атрибут alt, но они слышали, что его надо обязательно чем-то заполнить. Вот чем-то и заполняют. Какие есть альтернативные варианты в этой ситуации?
Просто оставить атрибут alt без значения.
<body>
<!-- атрибут alt пустой. Скринридеры не заметят декоративную картинку -->
<img src="pic.webp" alt="" height="90" width="90">
</body>
Это отличное решение для случаев, когда вы не знаете, какое значение написать в атрибут или не уверены. Отдельно замечу, что обязательно атрибут alt надо объявлять. Без него скринридеры озвучат значение из атрибута src.
<body>
<!-- не надо так. Скринридеры озвучат значение из атрибута src -->
<img src="pic.webp" height="90" width="90">
</body>
В окончании темы я дам вам совет.
По общению с незрячими людьми я понял, что основная потребность в атрибуте alt у них возникает в контентных частях приложений. Например, когда мы выбираем одежду, то смотрим на её фотографии.
Пользователи скринридера тоже так хотят делать. Здесь как раз уместно альтернативное описание, передающее недостающую информацию, которую зрячие люди получают глазами.
Дублировать стили от состояния :hover для состояния :focus
К сожалению, многие дизайнеры не думают о стилизации элементов при состоянии :focus. В последние годы дело обстоит лучше, чем раньше, но проблема всё ещё есть. По этой причине фронтендеру часто приходится самому придумывать, как будет выглядеть элемент, когда на него сфокусировались.
Тут может прийти гениальное решение. Стилизовать элемент так же, как при состоянии :hover. Тем более про него дизайнеры не забывают.
.button:hover, .button:focus-visible {
background-color: #fed330;
}
/* или
.button:is(:hover, :focus-visible) {
background-color: #fed330;
}
*/
Такой подход не универсальный. В нашем примере меняется цвет фона. Это изменение не заметит пользователь со слабым зрением. Или в режиме высокой контрастности ничего не произойдёт, потому что в нём не меняется цвет фона.
В общем, есть множество случаев, когда подход копирования стилей при состоянии :hover не сработает.
По этой причине я лично использую для состояния :focus свойство outline. Обводка, созданная им, хорошо заметна в разных условиях.
.button:hover {
background-color: #fed330;
}
.button:focus-visible {
outline: 3px solid #fbc604;
}
Если вы работаете с дизайнером, который продумывает такие нюансы, то мой пример можно ещё улучшить. Подойдите к нему и вместе подберите цвет обводки. Я уверен, что так будет ещё лучше.
Объявлять значения, которые не требуется
В CSS во многих случаях есть несколько способов установить значение для одной задачи. Взять, к примеру, установку цвета фона элемента. Какое свойство вы будете использовать?
/* вариант 1 */
.awesome-block {
background: #e1bfe9;
}
/* вариант 2 */
.awesome-block {
background-color: #e1bfe9;
}
Если вы используете первый подход, то давайте разбираться, чем он плох.
Может, вы слышали разговоры более опытных фронтендеров, что CSS сложно поддерживать. Есть много причин, почему это так. Одна из них, что разработчики не задумываются о методе объявлений значений.
В нашем примере с использованием свойства background мы установили не просто цвет фона. Мы заодно объявили целую группу свойств.
.awesome-block {
background: #e1bfe9;
/*
background-color: #e1bfe9;
background-image: initial
background-size: initial
и оставшиеся background-* свойства
*/
}
У нас была задача установить только цвет фона элемента. Зачем мы ещё устанавливаем его повторяемость, размер и другие значения? Вопрос риторический.
В программировании есть термин «побочные эффекты» (side effects). Вот мне нравится говорить, что в CSS есть «побочные свойства». Мы их объявляем, не задумываясь о них. Не надо так.
Есть другой пример, когда мы устанавливаем значение, которое не нужно нам. Это свойства margin и padding. Представим, что нужно установить отступ с трёх сторон. Какой способ вы выберете?
/* вариант 1 */
.awesome-block {
margin: 1rem 2rem 0 3rem;
}
/* вариант 2 */
.awesome-block {
margin-top: 1rem;
margin-right: 2rem;
margin-left: 3rem;
}
Снова первый? Значит, я повторюсь.
Вы будете мучаться от установленного 0 в будущем. Вы будете вынуждены его переопределить. А потом ещё раз. И так далее. По этой причине я фанат второго способа. Я лучше напишу три строчки, объявив значение с трёх сторон.
И кстати, уже можно сократить и эту запись. Логические CSS-свойства здесь отлично подходят.
.awesome-block {
margin-top: 1rem;
margin-inline: 3rem 2rem;
}
В общем, всегда задумывайтесь о том, какое свойство вы объявляете. Нет ли у него побочных эффектов.
Добавлять свойство display на всякий случай
Свойство display — самое таинственное свойство. Многие думают, что вся его польза —это значения flex и grid. Но это далеко не так. Самый прикол заключается в том, что оно ещё взаимодействует с другими свойствами.
Оно заставляет браузеры изменять алгоритмы расчётов свойств или вообще трансформирует значение. Взять, например, комбинацию свойств display и position.
.awesome-block {
position: relative;
}
.awesome-block::before {
content: "";
display: block;
width: 1rem;
height: 1rem;
background-color: tomato;
position: absolute;
top: 0;
left: 0;
}
Делали так же? Если да, то у меня есть новость. Свойство display тут лишнее. Код будет работать с тем же результатом и без него.
.awesome-block {
position: relative;
}
.awesome-block::before {
content: "";
/ * display: block; удалив эту строку, мы получим такой же визуальный результат */
width: 1rem;
height: 1rem;
background-color: tomato;
position: absolute;
top: 0;
left: 0;
}
Дело в том, если у свойства position используются значения absolute или fixed, браузеры автоматически анализируют значение свойства display у этого элемента.
Если у него была установлена строчная альтернатива (значения inline-*), она будет изменена на блочную. В моём примере у псевдо-элемента ::before по умолчанию объявлено значение inline для свойства display. Браузеры, увидев значение absolute, сразу его заменят на block. По этой причине, если мы удалим строку display: block, то результат не изменится.
Ещё одним примером такого поведения будет случай, когда используется значения flex, inline-flex, grid или inline-grid у родительского элемента.
.awesome-block {
display: flex; /* или inline-flex, grid, inline-grid */
}
.awesome-block::before {
content: "";
display: block;
width: 1rem;
height: 1rem;
background-color: tomato;
}
Здесь браузеры также проверят значение свойства display у псевдо-элемента ::before. Всё так же, как с примером со свойством position.
.awesome-block {
display: flex; /* или inline-flex, grid, inline-grid */
}
.awesome-block::before {
content: "";
/ * display: block; удалив эту строку мы получим такой же визуальный результат */
width: 1rem;
height: 1rem;
background-color: tomato;
}
Так что не объявляйте свойство display со значеним block в этом случае. Всё будет работать и без него!
Заключение
Давайте подведём итог. В этой статье я поделился следующими советами:
Не торопитесь заполнять атрибут
altлюбым значением — можно его оставить пустым.Всегда думайте о том, как вы объявляете CSS-свойства.
Объявляйте только то, что необходимо вам.
Не делайте копию стилей псевдо-класса
:hoverдля состояния:focus.Если используете значения
absoluteилиfixedдля свойстваposition, то не объявляйте значениеblockдля свойстваdisplay.Также помните про трансформацию значения свойства
displayвнутри элемента с установленным свойствомdisplayсо значениямиflex,inline-flex,gridилиinline-grid.Учитывайте порядок интерактивных элементов так, чтобы пользователям было комфортно.
Мне также интересно, какие бы вы дали советы по HTML и CSS для джунов. Что, по вашему мнению, является плохой привычкой? Поделитесь, пожалуйста, в комментариях.
На этом я прощаюсь. Спасибо за чтение!
P. S. Помогаю больше узнать про CSS в своём ТГ-канале CSS isn't magic. Присоединяйтесь. Ссылка в профиле.
© 2025 ООО «МТ ФИНАНС»
Комментарии (31)

RulenBagdasis
14.10.2025 15:14Первым элементом, на который я попаду клавишей Tab, будет кнопка «Закрыть». Так получится, потому что в разметке она находится первым интерактивным элементом. Потом уже идут элементы input и другие.
А почему сразу фокус в input не установить при показе модалки, чтобы вам вообще Tab нажимать не нужно было?

melnik909 Автор
14.10.2025 15:14Да, так надо сделать. Это поможет при открытии окна в первый раз. Но также нужен и порядок элементов.
1. Если перенос по какой-то причине не сработал
2. Он помогает, когда прошелся по всем элементам формы и еще раз заходишь "на круг"

qrKot
14.10.2025 15:14Зачем чинить то, что не сломано?
Я читаю контент, всплывает модальное окно "подпишитесь на новостную рассылку" или "зарегистрируйтесь". Я по табу попадаю на кнопку "закрыть", жму в нее и читаю дальше. Что не так? Идеальный флоу, ничего не сломано

melnik909 Автор
14.10.2025 15:14Вы говорите о другом примере. В целом поднимаете непростой вопрос. У меня в черновиках есть статья на эту тему. В будущем постараюсь написать.
Если отвечать на ваш вопрос, то все зависит от конкретного примера, потому что паттерны поведения в них разные. Следовательно и перенос фокуса будет разный. Где-то нужно поле ввода, где-то кнопка.

Driver86
14.10.2025 15:14Но почему многие разработчики так делают? Да, потому что они не знают, что вписать в атрибут alt
Странная проблема. А сами картинки ои где берут? Может там возьмут и то, что вписать?

Alonerover
14.10.2025 15:14Товарищи верстальщики, будьте уважительны к пользователям - не замусоривайте неудаляемыми ни с помощью uBlock, ни с Adnauseam графическими элементами, замусоривающими текст. Даже рекламные поля зачастую скрыть оказывается легче, чем эти бессмысленные картиночки ни о чём посреди текста. Даже когда удаляется скрыть саму картинку - зачастую остается просто пустое пятно.
Рекламодатели уже усвоили, что если чел не хочет смотреть рекламу он в любом случае либо заблокирует ее, либо при невозможности скрыть - просто уйдет. Это приучило их основную массу хоть к какой-то адекватности. Но вот владельцы сайтов и верстальщики еще не уяснили этой просто истины.

porcelanosa
14.10.2025 15:14В первом примере и вообще во всех формах tabindex="0" и т.д.
Это must have атрибут для инпутов и прочего.

radtie
14.10.2025 15:14Интерактивные элементы фокусируемы по умолчанию, к ним не надо писать tabindex, если это не tabindex="-1" обусловленный логикой приложения.

porcelanosa
14.10.2025 15:14Как мы видим в предложенном автором примере, по табу идет переход на кнопку/блок "Закрыть". Поэтому tabindex тут помог бы. Но это не отменяет, автофокусировки на первом поле формы, при открытии модального окна.

ifap
14.10.2025 15:14В этом случае я попаду на первый элемент input после нажатия клавиши Tab. Сразу смогу ввести номер телефона и авторизоваться. Красота!
А кто-то скажет, что у него уже сохранен номер телефона в браузере, и первым должен идти Submit ;-)

MamaLuyba
14.10.2025 15:14По общению с незрячими людьми я понял, что основная потребность в атрибуте
altу них возникает в контентных частях приложений. Например, когда мы выбираем одежду, то смотрим на её фотографии.Пользователи скринридера тоже так хотят делать. Здесь как раз уместно альтернативное описание, передающее недостающую информацию, которую зрячие люди получают глазами.
и каким же образом разраб должен знать, что будет на картинке очередного товара тысячного продавца из маркетплейса?

yri066
14.10.2025 15:14Мой любимый кейс, вместо всевозможных тэгов использовать один только dvi, как кнопку, картинку, поле ввода и прочее.
sfi0zy
Можно посмотреть на избыточные свойства и с другой стороны. Они не создают побочные эффекты. Они делают их явными. Помогают писать тупой и непробиваемый код.
Сказал block - значит block. И точка. Никаких связей с чем-то, что где-то там у родителя может когда-то поменяться каким-то модификатором пойди еще пойми где.
Стандартный набор отступов у компонента? Вот такой. Как написано, так и читать. Никаких связей с чем-то, что мы откуда-то унаследуем и расширим, а может и не будем, а может будем, но где-то потом. Нет. По умолчанию все явно. А если где-то магия и происходит, то ее сразу видно по неполным наборам свойств.
Я бы не сказал, что такой код становится однозначно плохим из-за своей формальной избыточности. Можно постоянно помнить скрытую логику в CSS, адаптироваться к ней, а можно перебивать ее, и продавливать свою систему мышления. Такой подход вполне имеет право на жизнь, если его целенаправленно везде применять.
dom1n1k
Да, я тоже именно из таких соображений явно пишу
display: blockvanxant
В примере с background ровно то же самое. Если бы автор хотел установить только цвет, наследуя что-то ещё, он бы так и написал. В данном примере он явно отменяет всякие картинки и прочее, что там может вылезти из наследования.
melnik909 Автор
Я совсем не пишу свойство backrgound.Всегда определяю только то, что мне нужно
delicious
Новичок, значит, или проект не сильно сложный.
heaventold
Тоже себе интересный момент себе подметил про атрибуты alt, думаю не следует его оставляться пустым:
1) как минимум никогда нельзя исключать того факта что ссылка перестанет работать, и что тогда у пользователей будет? Ничего. Поэтому если даже писать плохой alt - то это лучше, чем если у пользователей при ситуации когда не будет картинки, будет пустой блок.
2) если рассматривать с точки зрения seo, если мы пропустим на картинке допустим атрибут alt, то w3c - будет не соблюдено и будет ругаться
melnik909 Автор
Вы говорите о контентных изображения. В статье пример декоративных. Для них принятая практика оставлять пустой alt
Названный вами валидатор не будет ругаться на пустой alt
heaventold
Да вы правы в целом.
Для джунов думаю полезнее было бы:
1) Сохранять Семантику header, footer, section
2) Сохранять структуру БЭМ - оооочень много кто это упускает и пишет нейминг для class или id, как ему в голову взбредет
3) Не трать время на выписывание всех возможных атрибутов куда-нибудь в блокнот(я так делал мне стыдно), соблюдай семантику и БЭМ, а корректность и валидность проверяй валидатором (validator.w3.org)
-----
Все что стоит запомнить Семантика + БЭМ + элементарная стилизация с адаптивом, не стой долго на HTML + CSS, максимум недели 3-4 не более, все нужны теги или атрибуты придут со временем. Вот что я бы посоветовал джунчикам
HimikoRiver
вот сколько ни пытаюсь писать бэм, никак до конца понять его не могу. Вроде бы и пишу теги, как мне строго говорят в правилах и думаю, а вдруг другой человек пишет совсем по-другому, может бэм - бэму рознь?..
FODD
Имхо - БЭМ уже давно устарел и не особо нужен. И я даже не про новомодных подход атомарного CSS, а про фронтовые фреймворки с компонентным подходом. Все они позволяют писать CSS, не опираясь на глобальные стили. Лично я стараюсь даже классы не писать, просто пишу div {} и поехали стилизовать
dom1n1k
То есть вы фактически наделяете div свойствами id, потому что второго в разметке появиться не может? Понятно, что только в пределах компонента, но тем не менее. Прэлэстно! (голосом вороны из мультика про Кешу)
Gluber
Я джун и я так и не понял, почему в примере указание alt «аватар пользователя» это хуже, чем без указания. Особенно в условиях читалки для слепых.
winorun
аватар пользователя gluber семь часов назад ниже я джун и я так и не понял, почему в примере указание alt открывающая двойная кавычка аватар пользователя закрывающая двойная кавычка это хуже, чем без указания. Особенно в условиях читалки для слепых.
nyxandro
аватар пользователя не декоративный элемент. в данном случае альт заполнять нужно было. даже если это иконка.
melnik909 Автор
почему это не декоративный элемент?