Стилизуем кнопки правильно
Кнопки есть практически в любом приложении. В их роли могут выступать самые разные элементы — собственно кнопки, ссылки и даже простые спаны. В любом случае важно правильно их оформить. В этом руководстве мы займемся созданием CSS-компонента кнопки.
Сброс стилей элемента <button>
99.9% кликабельных элементов на сайте — это ссылки (<a>
) или кнопки (<button>
). Если вы не знаете, какой тег выбрать для конкретной ситуации, следуйте правилам:
- Если при клике происходит переход на другой URL или изменяется большая часть контента на странице, используйте ссылку (
<a href="some_url">...</a>
); - В остальных случаях подойдет обычная кнопка (
<button type="button">...</button>
).
Выбор правильного элемента имеет несколько преимуществ: это SEO-friendly и делает ваш сайт более доступным при работе с клавиатуры и для скринридеров.
Однако разработчики редко используют элемент <button>
. На большинстве сайтов кнопки представлены тегами <div>
, <span>
или <a>
. В чем причина такой нелюбви?
- Незнание. Некоторые разработчики даже не догадываются, что тег
button
можно использовать вне форм. - Сложности стилизации. У кнопок очень много стилей по умолчанию, которые мешают созданию кастомного дизайна.
К счастью, у нас есть CSS reset. Давайте сбросим стили кнопки и сделаем ее похожей на обычный текст:
See the Pen
Reset button styles by FurryCat (@mohnatus-the-lessful)
on CodePen.
Минус этого подхода заключается в том, что стиль сбросился у ВСЕХ кнопок, и теперь посетитель сайта не сможет опознать их на странице.
Можно воспользоваться препроцессором (SCSS) и написать миксин для использования в нужных местах:
See the Pen
Reset button styles (mixin) by FurryCat (@mohnatus-the-lessful)
on CodePen.
Создание CSS-компонента кнопки
Теперь, когда мы удалили все лишнее, давайте определим собственные стили для кнопки. Создадим для этого отдельный класс .btn
, который можно будет указать и для button
, и для a
, и для любого другого элемента.
Внимание: при разработке CSS-компонента кнопки важно учитывать, что он может быть применен к ссылкам. Значит, необходимо изменить также дефолтные свойства ссылок.
See the Pen
Button component by FurryCat (@mohnatus-the-lessful)
on CodePen.
Избегайте использования для кнопок цветов с малым контрастом. Часть ваших пользователей может иметь проблемы со зрением, а другая изучает сайт в неблагоприятных условиях (например, на телефоне под светящим солнцем) — не затрудняйте им жизнь.
Стилизация различных состояний
Кнопка уже выглядит неплохо, но кое-чего не хватает. Это интерактивный элемент, имеющий несколько состояний. Мы должны стилизовать и их.
У браузеров есть собственные дефолтные стили для состояний :focus
(фокус на кнопке) и :active
(нажатие), но часть из них мы уже сбросили. Не забудем также про состояние :hover
(наведение курсора).
- Для нажатой кнопки создадим олдскульный эффект «утопления» с небольшим изменением насыщенности.
- При наведении курсора поменяем местами цвета фона и текста и добавим рамку.
- Для обозначения фокусировки используем такой же стиль.
Обратите внимание: стили фокуса очень важны. Многие пользователи по разным причинам пользуются клавиатурой для навигации по странице. Только стилизованный :focus помогает им понять, где они находятся в данный момент.
Только после того как мы позаботились о собственном оформлении фокуса можно убрать у кнопки дефолтные браузерные стили (outline
).
See the Pen
Button states styling by FurryCat (@mohnatus-the-lessful)
on CodePen.
Разбираемся с «липким» фокусом
Осталось решить еще одну небольшую проблему.
В ряде браузеров когда вы кликаете на ссылку или кнопку, она получает два псевдокласса: :active
и :focus
.
:active
убирается сразу после того, как вы перестали нажимать на кнопку мышки или трекпад. Но :focus
зачастую остается до тех пор, пока вы не кликнете на какой-нибудь другой элемент страницы.
Это поведение можно пофиксить с помощью нового псевдокласса :focus-visible.
Поддержка псевдокласса :focus-visible на CanIUse
Это свойство еще не принято официально, но идея заключается в том, что состояние :focus-visible
устанавливается для элемента только при получении фокуса с клавиатуры (а не при клике).
При необходимости можно использовать JS-полифилл.
Давайте разделим состояния :hover
и :focus
в нашем компоненте:
.btn:hover { color: #9050AA; border-color: currentColor; background-color: white; } .btn:focus { outline: none; box-shadow: 0 0 0 3px rgba(255, 105, 180, 0.5), 0 0 0 1.5px rgba(255, 105, 180, 0.5); }
Теперь подключим полифилл focus-visible.js. Он добавит элементу body
класс js-focus-visible
. Используем его, чтобы удалить тень с элементов, у которых нет класса focus-visible (то есть тех элементов, на которых сфокусировались не с клавиатуры):
.js-focus-visible .btn:focus:not(.focus-visible) { box-shadow: none; }
Кажется, было бы проще установить стили только для .focus-visible
элементов, однако, так мы лишимся фоллбэка на тот случай, если скрипт не сработает.