Стилизуем кнопки правильно, создание CSS-компонента кнопки

5184

Стилизуем кнопки правильно

Кнопки есть практически в любом приложении. В их роли могут выступать самые разные элементы — собственно кнопки, ссылки и даже простые спаны. В любом случае важно правильно их оформить. В этом руководстве мы займемся созданием 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 элементов, однако, так мы лишимся фоллбэка на тот случай, если скрипт не сработает.

источник