Пользовательский интерфейс в CSS
Optional Advanced только что наложил трафарет на одно фото. Этот урок — другой набор: пользовательский интерфейс. Вы меняете указатель, каретку и нативный хром виджета. Здесь не дырявят постер и не режут статью на газетные колонки.
Прямой ответ
Свойства интерфейса CSS намекают на взаимодействие. cursor выбирает форму мыши (pointer, wait, help, not-allowed…). resize позволяет тянуть угол — обычно у textarea. outline с outline-offset рисует кольцо фокуса, не занимая место в раскладке (outline из блочной модели вы уже знаете; здесь это привычка клавиатуры). user-select ограничивает случайное выделение. caret-color окрашивает мигающую каретку. appearance (и -webkit-appearance) может снять нативную «кожу», чтобы вы переоформили контрол. Фокус оставляйте видимым. Не превращайте всю страницу в невыделяемый плакат.
Почему это не маска и не колонки
Маска решает, какие пиксели одной коробки остаются видимыми. Многоколоночность дробит поток текста. Свойства UI не делают ни того ни другого. Ширина и высота остаются, пока не вмешается resize. Фильтры и mask-image по-прежнему про картинку. Вопрос здесь: «Похоже ли это на кликабельное? Можно ли печатать? Можно ли увеличить коробку? Видит ли пользователь клавиатуры, где он?»
cursor — говорите правду
cursor — обещание. pointer значит «сюда можно кликнуть». Ставьте на настоящие кнопки и ссылки. Не вешайте руку на заголовок, который ничего не делает.
a.nav-link,
button.save {
cursor: pointer;
}
button[disabled] {
cursor: not-allowed;
}
.help-hint {
cursor: help;
}
.busy-panel {
cursor: wait;
}
default — стрелка. text — I-образный курсор над выделяемым текстом. grab / grabbing — для ручек перетаскивания. Свои url(...)-курсоры держите мелкими и всегда указывайте запасное ключевое слово. Лживый курсор хуже отсутствия: кликают слоган — и ничего.
resize — растите коробку, не макет
resize работает на коробках с overflow. Повседневный случай — поле заметок:
textarea.notes {
min-height: 6rem;
min-width: 16rem;
max-width: 100%;
resize: vertical;
overflow: auto;
}
Значения: none, both, horizontal, vertical. Сочетайте с overflow не visible, иначе ручка может не появиться. Не сыпьте resize: both на все карточки. min-height / max-width не дают полю сжаться или взорваться.
outline как кольцо фокуса
В блочной модели outline сидит снаружи рамки и не занимает место. В наборе UI вы оставляете это кольцо для клавиатурного фокуса — часто с :focus-visible, чтобы мышь не обводила каждый клик:
button.save:focus-visible {
outline: 3px solid #2563eb;
outline-offset: 3px;
}
button.save:focus:not(:focus-visible) {
outline: none;
}
Не отправляйте глобальный *:focus { outline: none; }, пока у каждого контрола нет столь же заметной замены. outline-offset отодвигает кольцо, не сдвигая соседей. Это не border (меняет размер) и не масочное затухание подписи кнопки.
user-select — меньше случайного выделения
Выделение — возможность. Ослабляйте его только там, где двойной клик не должен красить синим — подпись панели, чип перетаскивания — не статья.
.toolbar-label {
user-select: none;
}
article.body {
user-select: text;
}
none блокирует подсветку. text — обычный читаемый режим. all выделяет весь элемент одним кликом. Префиксы (-webkit-user-select) ещё встречаются в старом WebKit. Не запрещайте копировать юридический текст, цены и сообщения об ошибках.
caret-color — цвет каретки
Каретка — мигающая полоска в поле. Подстройте её под бренд не пряча:
input.email,
textarea.notes {
caret-color: #0f766e;
color: #0f172a;
}
caret-color: auto следует цвету текста. caret-color: transparent «для чистоты» — ловушка. Это не color всей страницы и не mask-image на глифе.
appearance — переоденьте нативный виджет
Браузеры рисуют чекбоксы и поля поиска нативным хромом. appearance: none (плюс -webkit-appearance: none при необходимости) снимает эту кожу:
input.search {
appearance: none;
-webkit-appearance: none;
border: 1px solid #94a3b8;
border-radius: 0.5rem;
padding: 0.5rem 0.75rem;
}
input[type="checkbox"].tick {
appearance: none;
-webkit-appearance: none;
width: 1.15rem;
height: 1.15rem;
border: 2px solid #334155;
border-radius: 0.25rem;
}
После none вы должны рамку, состояние «отмечено» и кольцо фокуса. Невидимый чекбокс — не кастомный контрол. Поддержка зависит от типа; проверяйте настоящий виджет. appearance не чинит маску и не заменяет колонки.
UI против маски, колонок и outline коробки
📊 UI vs mask vs columns vs outline
| Tool | Job | Poor fit |
|---|---|---|
cursor / resize / caret-color / appearance |
Interaction chrome on controls | Stenciling a photo; newspaper columns |
user-select |
Limit highlight on chrome, not articles | Hiding copy people must paste |
outline + :focus-visible |
Keyboard focus ring (no layout space) | Replacing border math; fading labels with a mask |
mask-image |
Soft holes on one element’s pixels | Pointer shape; growing a textarea |
Multi-column (column-*) |
Fragment flowing text | Cursors, carets, native widget skin |
Optional Advanced уже брал колонки для прозы и маски для картинок. Интерфейс — слой контролов. column-count на форме настроек или mask-image на кнопке отправки не делает форму «более UI».
Что не стоит стирать
Не снимайте все нативные подсказки. Полосы прокрутки, каретки и кольца фокуса нужны. Если контрол выключен, cursor: not-allowed плюс настоящий атрибут disabled спокойнее маски, прячущей подпись.
.ok-ui {
cursor: pointer;
outline-offset: 2px;
}
.not-a-stencil {
/* don't: mask-image on the submit label to “soften” the click */
}
.not-a-newspaper {
/* don't: column-count on a login form to look advanced */
}
Край фото — вернитесь к маске. Длинная статья — к колонкам или обычному потоку блоков. «Не ощущается кликабельным» — начните с cursor и настоящего контрола, не с декоративного фильтра.
Попробуйте сами
cursor: pointerна настоящую<button>иnot-allowedна[disabled].textarea:resize: vertical,min-height,overflow: auto.- Outline с
:focus-visibleиoutline-offset— дойдите Tab. user-select: noneтолько на чипе панели; статья остаётся выделяемой.- Покрасьте
caret-colorво input. Не маскируйте поле и не ставьтеcolumn-count.
Частые ошибки
cursor: pointerна тексте, который не ссылка и не кнопкаresize: bothна карточках макета и панелях навигации- Глобальный
outline: noneбез замены:focus-visible user-select: noneна целых страницах, ценах или ошибкахcaret-color: transparent«ради чистого вида»appearance: noneбез рамки, состояния «отмечено» и кольца фокуса- Путать маску или колонки с полировкой интерфейса
Кратко
- CSS интерфейса намекает на взаимодействие: указатель, resize, каретка, нативный хром
cursorдолжен говорить правду;resize— для полей, не для оболочки страницы- Держите видимым кольцо фокуса;
user-selectиcaret-colorтрогайте легко appearance: noneтолько когда переоформляете виджет целиком- Это не трафарет маски и не газетные колонки
- Optional Advanced дальше: 3D-трансформации (
transforms-3d)
🧠 Проверьте Свои Знания
Проверьте Свои Знания
Бросьте себе вызов с помощью этой интерактивной викторины и узнайте, насколько хорошо вы понимаете тему
📝 Инструкции
- Внимательно прочитайте каждый вопрос
- Выберите лучший ответ на каждый вопрос
- Вы можете пересдавать тест столько раз, сколько захотите
- Ваш прогресс будет показан вверху