
Привет, Хабр!
Я в течение нескольких лет рассказываю вам, как сделать интерфейс лучше для пользователя. Например, в прошлом месяце я поделился простыми HTML и CSS лайфхаками, которые помогают сделать интерфейс дружелюбнее к пользователю.
А недавно я подумал: а вдруг есть фронтендеры, которые хотят сделать ужасный интерфейс? Ну не любят они пользователей. Или хотят сделать пакость работодателю, который их обидел. Где им взять советы?
Надо помочь! Я собрал вредные HTML и CSS техники. Они супер простые, но очень действенные. Я уверен на сто процентов, что благодаря им интерфейс вашего проекта заставит пользователя вспомнить несколько «ласковых» слов.
Давайте посмотрим, что я вам подготовил.
▍ Всегда используйте type="text"
для всех полей ввода данных
В интерфейсах есть несколько типов данных, которые пользователь может ввести. Для этого придумали атрибут type
. Особенно важно знать, что браузеры используют его, чтобы показать более подходящую виртуальную клавиатуру.
Забудьте. Для всех полей ввода данных используйте значение text
. Вам даже его не надо писать. Оно используется по умолчанию. Всегда используйте его, и браузеры отобразят виртуальную клавиатуру с буквами и цифрами.
Это будет жутко бесить пользователя во многих ситуациях. Например, при вводе номера паспорта ему будет нужно нажимать по маленьким цифрам.

<div class="input input--small-label ">
<label class="input__label" for="id_0.2013064072314139">Серия и номер</label>
<div aria-expanded="false" class="input__text has-error">
<input type="text" title="Серия и номер" class="input__text-input" aria-describedby="passenger-number" maxlength="14" autocomplete="one-time-code" id="id_0.2013064072314139">
</div>
</div>
То же самое при вводе номера телефона.

<div class="input input--label-hide">
<label for="id_0.37648949029345546_number" class="input__label">Ваш номер телефона</label>
<div class="phone__wrapper">
<span class="phone__code">+7</span>
<div class="input__text">
<input type="text" class="input__text-input" id="id_0.37648949029345546_number" autocomplete="new-password" maxlength="15">
</div>
</div>
</div>
При вводе электронной почты стандартная клавиатура заставит пользователя переключить её, чтобы ввести специальные символы.

<div class="input">
<label class="input__label" for="id_0.5944244514014756">Эл. почта</label>
<div class="input__text">
<input type="text" class="input__text-input" id="id_0.5944244514014756" autocomplete="new-password" maxlength="59">
</div>
</div>
Это замечательные вредные примеры. Но я хочу предупредить вас. Вам также нужно избегать использования атрибута inputmode
. Браузеры тоже используют его, чтобы отобразить более подходящую виртуальную клавиатуру. Его не должно быть в вашем коде.
▍ Элемент <button>
не должен существовать вне элемента <form>
Переходим к моей любимой теме. Я верстаю давно. Треть жизни. Раньше была замечательная вредная практика. Большинство верстальщиков использовали элемент <button>
только внутри элемента <form>
.
Их не волновало, что в интерфейсах есть множество других кнопок. Как бы было логично использовать элемент <button>
, но нет. Большинство предпочитало либо элемент <span>
, либо элемент <div>
.
А потом на конференциях, подкастах и статьях начали говорить, что так нельзя. И верстальщики послушали, но хорошо, что не все. Мне удалось найти несколько примеров.
Начну я с кнопки «Закрыть». Например, вы её можете встретить для модального окна.

<div class="d-modal__close-button">
<div class="icon icon_cross-thin-white icon_direction-down" title="Закрыть"></div>
</div>
Вторая популярная кнопка — это «Показать пароль».

<div class="auth__input-wrap">
<input class="auth__input" name="password" type="password" id="signInInputPassword101">
<label for="signInInputPassword101" class="auth__input--placeholder">Пароль</label>
<div class="btn-show-hide-password">
<span data-v-a713a5e8="" class="icon"></span>
</div>
</div>
Этот кейс — моя личная боль. У меня четыре пароля. Они отличаются последними символами. Конечно, я не помню, где какой используется. Вот когда пароль не подходит, я хочу посмотреть его. Жму клавишу Tab
и мимо кнопки «Показать пароль». А потом матюгаюсь и тянусь за мышкой.
Здорово же? Так, что пользуйтесь возможностью усложнить мне жизнь.
▍ При стилизации нестандартных элементов управления используйте свойство background
Вы шаман вёрстки, поэтому стремитесь сделать всё с помощью CSS. Особенно нестандартные элементы управления. Кнопки, радиокнопки, чекбоксы и так далее.
В этой задаче надо использовать свойство background
при написании стилей. В этом случае ваши элементы не отобразятся в режиме принудительных цветов. Например, на этом сайте есть кнопка «Гамбургер».

.menu-toggler__burger,
.menu-toggler__burger::after,
.menu-toggler__burger::before {
width: 2.3rem;
height: 0.2rem;
border-radius: 10rem;
background-color: #050625;
}
Я нажал сочетание клавиш левый ctrl
, левый alt
и PrtSc
, чтобы включить режим высокой контрастности Windows. Попробуйте найти кнопку на этом экране.

Она визуально не отображена. Думаете, это случайность? Нет! Разработчики сайта знают, что в режиме высокого контраста используется одно и то же значение для всех мест, где есть свойство background
.
Это очень тонкая работа специалистов. Они хотели помочь пользователю весело провести время, ищя кнопку. А главное, тыкнуть по ней случайно — это единственный способ её найти. Если бы они использовали векторную графику или свойство border
для вёрстки кнопки, то так не получилось бы. Хорошая работа!
▍ Все изображения должны приводить к скачкам контента
Изображения — это отличный пособ подбесить пользователя. Они должны долго загружаться, и при этом вызывать скачки контента вокруг. Чтобы всё прыгало!
Мне сложно в рамках статьи показать динамический пример. По этой причине я покажу с помощью скриншотов. Я нашёл страницу с новостями. У каждого блока есть изображение.

Обратите внимание, как красиво выровнены заголовки. Все на одной линии. Далее нам это пригодится.
Теперь исправлю путь к одному из изображений, чтобы оно не загрузилось.

Заголовок теперь отобразился выше, чем другие. На самом деле я наблюдал скачок. Теперь представьте, как прекрасно скачет текст при загрузке страницы. Жутко бесит!
Так должно быть и в вашем проекте. А если кто-то попытается рассказать вам про свойство aspect-ratio
, не слушайте их. Они ничего не понимают в ужасных интерфейсах.
▍ У вас должно быть ограничение на количество введённых символов
Данный совет прекрасно подходит для проектов, где пользователи покупают билеты. У некоторых людей могут быть двойные фамилии. Здесь у вас появляется возможность не дать им это сделать. Используйте атрибут maxlength
для поля ввода фамилии. Люди не смогут заполнить форму и купить билеты!
Такой случай был у моей знакомой Екатерины. После замужества у неё стала фамилия «Михайличенкова-Павлюченкова». На латинице «Mikhailichenkova-Pavlyuchenkova».
Она попыталась её ввести при покупке авиабилетов.

<input type="text" maxlength="30" value="MIKHAILICHENKOVA-PAVLYUCHENKOV" title="Фамилия" class="input__text-input" aria-describedby="passenger-name"autocomplete="one-time-code" id="id_0.5152585184040783">
Не получилось ввести последний символ. Она попыталась вставить фамилию, но браузеры обрезали её, чтобы соответствовать лимиту. Безупречное решение от разработчиков!
Правда, мы можем улучшить и этот пример. Можно добавить атрибут minlength
. Тогда люди с короткими фамилиями, например, иностранцы, тоже не смогут заполнить форму. Но тут уже смотрите сами.
▍ Сделайте всё, но не используйте свойство outline
Я уверен, что вы можете сами сделать ужасный интерфейс. Но с напарником же лучше? Попросите дизайнера сделать нестандартную обводку для интерактивных элементов, находящихся в состоянии «Фокус».
В этом случае у вас появится возможность навредить мне. Ваша задача — не использовать свойство outline
. Вместо него сделайте обводку с помощью свойства box-shadow
.

.news-container :focus-visible {
border-radius: 1px;
box-shadow: 0 0 0 3px #68d;
}
В этом случае я её не увижу, если буду использовать режим принудительных цветов. Например, так будет отображена обводка из предыдущего примера в режиме высокой контрастности Windows.

Очень действенный метод! Я часто использую клавиатуру, и это очень сильно осложнит мне жизнь. Но вы мне можете сказать, что мало кто использует такой режим. Ладно, не буду спорить. Есть ещё способ сделать пакость мне.
Вы можете дополнительно поиздеваться надо мной, если ваша обводка будет обрезана. Я нашёл прекрасный пример.

Вот я же не с первого раза пойму, что это за две линии сверху и справа. Буду думать. Так что обязательно сделайте так же. Для этого добавьте свойство overflow
со значением hidden
к любому родительскому элементу.

.mCustomScrollBox {
direction: ltr;
height: 100%;
max-width: 100%;
outline: none;
overflow: hidden;
position: relative;
}
▍ Всегда заполняйте бессмысленной информацией атрибут alt
Конечно, я не мог оставить в покое пользователей скринридера. Они тоже должны мучаться. В этом вам поможет атрибут alt
. Ваша задача заключается в том, чтобы абсолютно для всех изображений добавить в него текст. Неважно, является оно декоративным или нет.
А ещё лучше, если вы туда добавите бессмысленный текст. Например, разработчики добавили текст «Участник сообщества 2».

<img alt="Участник сообщества 2" class="_image_1fz8s_65" src="https://opis-cdn.tinkoffjournal.ru/mercury/ugc_soqmcc_userpic?preset=icon_30x30_2x">
Какого сообщества? Почему он второй? Вот такие вопросы задаст пользователь скринридера. Но на этом не стоит останавливаться. Пусть пользователь будет конфужен полностью.
В современных интерфейсах часто используется аватарки. Вот добавьте для них текст «Аватар пользователя».

<img alt="Аватар пользователя" class="_image_jfgqc_12" width="90" height="90" src="https://opis-cdn.tinkoffjournal.ru/ip/SCMpowFpEL5LW7xeI9FmjqJKjIJO2-qvsYH6S1VQhYU/h:600/w:600//ZjIzMmVlYl8zMl8y/LmpwZw">
Таким решением вы только заспамите озвучку текста. Никакой пользы не будет. Вот что сказал мой незрячий знакомый Илья:
«Для меня — это спам. У меня весь день ридер болтает в телефоне и ноуте. Бывает, к вечеру едет крыша. Да и слух притупляется. Поэтому всё лишнее стараюсь отбрасывать».
Напоследок я хочу позаботиться о вас. Буду честен, у меня есть серия статей, где мы с Ильёй рассказали, как правильно поступать. Ни в коем случае не читайте эти статьи. Тогда сделаете хорошо. А это же против ваших интересов.
▍ Заключение
Надеюсь, теперь вы знаете, как сделать ужасный интерфейс. Конечно, я не показал все техники, но эти уже очень сильно усложнять жизнь пользователям. Ваша задача будет решена.
Но вы действительно хотите приносить неудобства людям? Надеюсь, что нет. И вы будете использовать эту статью, как чек-лист багов, которые нужно исправить.
Кстати, поделитесь, пожалуйста, своими примерами, когда интерфейс бесит вас. Мне будет интересно прочитать.
На этом я прощаюсь. Спасибо за чтение!
P.S. Помогаю больше узнать про CSS в своём ТГ-канале CSS isn't magic. Присоединяйтесь. Ссылка в профиле.
© 2025 ООО «МТ ФИНАНС»
Telegram-канал со скидками, розыгрышами призов и новостями IT ?

Комментарии (34)
baldr
03.06.2025 09:37Справедливости ради, не всё из статьи относится к UI непосредственно, часть из этого - больше юзабилити.
Немного ссылок по теме:
kenomimi
03.06.2025 09:37Все изображения должны приводить к скачкам контента
Это не только косяк глупца, но и вполне себе специально запиливаемый маркетинговый dark pattern, направленный на мисклик пользователя по рекламе. Беспалевно, если не наглеть, и дает отличный конверт, и отдельный котел в аду с прыгающей кнопкой выключения огня
Habrahog
03.06.2025 09:37Номер паспорта так-то включает и буквы. Не знаю, как в РФ, но в очень многих странах. Поэтому спрятать буквы на клавиатуре тут будет равно потерять пользователя или получить неверные данные.
melnik909 Автор
03.06.2025 09:37в РФ только цифры. Если бы были и буквы, то я бы не включил кейс в статью
nvladik
03.06.2025 09:37Очень странный "кейс", а что иностранцы не могут пользоваться сервисами в РФ ? Вы же сами ниже про фамилию пишите...
melnik909 Автор
03.06.2025 09:37В этом случае пользователь может переключиться на стандартную клавиатуру. Если сервисом пользуются большинство с российским паспортом, то в нем нет букв.
redfox0
03.06.2025 09:37В военном билете РФ есть буквы, и он является документом, удостоверяющим личность.
Aggle
03.06.2025 09:37Однако, большинство всё-таки использует паспорта. В целом, интерфейс должен быть нацелен в первую очередь на удобство большинства юзеров. Это из разряда выбора города - вначале списка нормальные люди ставят самые крупные города, а не располагают их в алфавитном порядке. Т. е. "Москва, Санкт-Петербург", а не "Альметьевск, Боровичи".
Astroscope
03.06.2025 09:37В целом, интерфейс должен быть нацелен в первую очередь на удобство большинства юзеров.
Но, есть такое мнение, что удобство большинства необязательно должно достигаться ценой потери меньшинства. Не ценой неудобства меньшинства - иногда это неизбежный компромисс, а именно ценой недоступности, невозможности использовать меньшинством.
ncix
03.06.2025 09:37Т. е. "Москва, Санкт-Петербург", а не "Альметьевск, Боровичи".
Ага, ткнул на выбор города (которых там тысячи), не глядя по привычке (привитой теми, кто соритрует по алфавиту) открутил в середину, а там нет Москвы на букву "М". Поматерился, крутя обратно.
grivova
03.06.2025 09:37В целом, интерфейс должен быть нацелен в первую очередь на удобство большинства юзеров.
Тогда и мнение незрячих не учитываем. И юзеров с контрастностью. Да по такой логике можно статью удалить
Astroscope
03.06.2025 09:37Статья про то, как сделать плохо. Любые советы как сделать еще хуже - очевидно приветствуются. А вот следовать ли им буквально - да, вопрос не из самых простых.
BanderasPRO
03.06.2025 09:37Паспорт может содержать любые символы, так как иностранцы такие же пользователи информационных систем, особенно сейчас, когда контроль за цифровой средой усилился. А такие советы реально сломали мне день, когда какие-то идиоты в Сбере ввели это ограничение в своей банковской системе, и я не смог внести деньги за кредит моего друга из Казахстана, так как поле принимало только цифры, да еще и только одного формата. Даже переключателя не добавили, как часто делают "паспорт иностранного гражданина".
Так что ваш этот совет про паспорт, крайне однобокий.
Aggle
03.06.2025 09:37Там речь про изначальный выбор виртуальной клавы, а не ограничения на ввод (это, кстати, в копилку ужасных интерфейсов), т. е. буквы ввести можно после переключения клавиатуры. Но большинству удобнее начинать с цифровой.
Maliglood
03.06.2025 09:37Мне кажется, для таких случаев нужно вводить доп. поле "Тип документа", и уже в зависимости от него выбирать тип ввода.
vanxant
03.06.2025 09:37Что касается режима высокой контрастности, камень не по адресу. Если уж ОС и браузер корячат сайт на своё усмотрение, они должны делать это нормально, а не "мы сейчас половину отрежем, вторую перекорячим, а вы там приседайте как хотите".
Всё равно что взять какую-нибудь игру, удалить файлы из папки с текстурами и удивляться странным результатам.
melnik909 Автор
03.06.2025 09:37А как им нужно сделать, если этот режим для людей с особенностями зрения? Например, со светобоязнью
monochromer
03.06.2025 09:37Никогда не пишите статьи в таком стиле. Есть налёт хамства и токсичности. Хуже воспринимается "инвертированная" информация, из-за чего она становится менее доступной.
i_home
03.06.2025 09:37К полю ввода фамилий, ещё один любимый многими разработчиками лайфхак
Ограничить ввод только алфавитными символами, чтобы никто не мог ввести двойную фамилию, которая пишется через тире например
wodjudidkw982uj
03.06.2025 09:37Спасибо, я как раз делал максимально не удобную страничку для развлечения, та и чего нового узнать
gun_dose
Многие любят разбить поле ввода телефона на два поля: код + телефон. Из-за этого автодополнение по адресам срабатывает некорректно. Браузер помнит мой телефон вместе с кодом и вставляет его одной строкой в поле телефона. Потом валидация формы просит вставить код, и можно пропустить, что код оказывается вставлен дважды, а последние цифры номера потеряны.
Маска ввода на телефонных полях тоже бывает глючная. Знаю один сервис, там кликаешь мышкой в середину поля ввода, и курсор оказывается в средней позиции. Приходится через backspace загонять его в начало.
baldr
gun_dose
Ну это уже перебор. Обычного ползунка достаточно.