Стилизуем кнопки правильно
Если вы создаёте сайт или веб-приложение, там наверняка есть кнопки. А может быть ссылки, выглядящие как кнопки? В любом случае важно правильно их сделать.
Этап 1: Сброс стилей у .
Этап 2: Создание CSS-компонента «button».
Этап 3: Стилизация активного, ховер- и фокус-состояния.
Этап 4: Разбираемся с прилипшим фокусом.
Сброс стилей у
- Если при клике открывается другая страница или изменяется большая часть контента на странице — используйте ссылку ( … ).
- В остальных случаях используйте обычную кнопку ( ).
Использование правильного элемента имеет ряд преимуществ: это благоприятно для SEO (особенно для ссылок!), хорошо для навигации с клавиатуры и улучшает доступность для всех пользователей.
Несмотря на это, разработчики редко используют . По всему интернету можно встретить кучу кнопок, которые вызывают действия через JavaScript, но на деле оказывается, что это , или .
Почему же так редко используется?
- Знание: многие разработчики просто не знают о нём (выучить более 100 HTML-элементов не так-то просто).
- Стилизация: по умолчанию у сложные стили, из-за которых трудно добиться собственного вида.
К счастью, стилизацию поправить не так уж сложно!
/** * Сброс стилей у кнопки. * Придётся немного поработать, чтобы получить нейтральный вид. */ button padding: 0; border: none; font: inherit; color: inherit; background-color: transparent; /* отображаем курсор в виде руки при наведении; некоторые * считают, что необходимо оставлять стрелочный вид для кнопок */ cursor: pointer; >
В итоге мы получаем кнопки, которые выглядят как обычный текст.
Минус в том, что при таком подходе необходимо стилизовать все кнопки, или пользователь не распознает их (см.: возможности). Ещё один вариант — использовать этот стиль как миксин (Sass или другой препроцессор) и применять его выборочно:
@mixin button-reset padding: 0; border: none; font: inherit; color: inherit; background-color: transparent; cursor: pointer; > .my-custom-button @include button-reset; padding: 10px; background-color: skyblue; >
button type="button"> У меня браузерные стили по-умолчанию. button> button type="button" class="my-custom-button"> А я использую собственные стили. button>
Создание CSS-компонента «button»
Теперь, когда мы сбросили дефолтные стили, можем приступить к написанию своих. Вот что мы сделаем:
- «кнопочный» стиль, который можно применять и к ссылкам и кнопкам;
- применять мы хотим выборочно, потому что у нас есть другие ссылки и кнопки с разными стилями на странице.
Напрашивается CSS-компонент. CSS-компонент — это стиль или набор стилей, которые применяются, используя классы, к различным типам HTML-элементов. Вам должно быть знакомо это понятие, если вы используете CSS-фреймворки Bootstrap или Foundation.
Назовём этот компонент .btn (как в Bootstrap, но мы ограничимся одним цветом и размером, чтобы было проще).
.btn /* по-умолчанию для , но пригодится для */ display: inline-block; text-align: center; text-decoration: none; /* создаём маленькие отступы, если кнопки перенесутся на две строки */ margin: 2px 0; /* невидимая граница (понадобится для цвета при наведении/фокусе) */ border: solid 1px transparent; border-radius: 4px; /* размер строится из текста и отступов (без width/height) */ padding: 0.5em 1em; /* убедитесь, что достаточно контраста! */ color: #ffffff; background-color: #9555af; >
Вот что у нас получилось:
Вам, возможно, интересно, почему контраст так важен. Ведь кнопки на второй строке выглядят красиво: кому не нравятся пастельные цвета?
Проще говоря: с хорошим контрастом, вы охватите больше пользователей. Некоторые пользователи — слабовидящие. Другие могут просматривать ваш сайт с телефона, на ходу, а под дневным светом труднее читать. Вы можете проверить коэффициент контрастности и почитать о контрастности текста.
Стилизация активного, ховер- и фокус-состояния
Круто, когда ваша кнопка выглядит красиво, но… пользователи будут взаимодействовать с ней, и поэтому требуется визуальный отклик, когда состояние кнопки изменяется.
У браузеров свои стили по-умолчанию для «активного» (т.е. нажатого) и «фокусного» состояния, но, сбросив стили у кнопки, мы избавились от некоторых из них. Не хватает ещё стилей при наведении мышкой, да и в целом хочется, чтобы все стили были видны и соответствовали нашему дизайну.
Начнём со стилей для состояния :active, которое срабатывает при клике кнопки или ссылки:
/* олдскульный эффект «нажатия» + цветовые правки */ .btn:active transform: translateY(1px); filter: saturate(150%); >
Мы могли бы изменять цвет кнопки, но я хочу использовать этот эффект при наведении:
/* инвертируем цвета при наведении */ .btn:hover color: #9555af; border-color: currentColor; background-color: white; >
Давайте добавим теперь и фокусные стили. Пользователи вашего сайта или веб-приложения могут использовать обычную или виртуальную клавиатуру (на iOS и Android), чтобы «сфокусировать» и активировать поле в форме, кнопки, ссылки и другие интерактивные элементы.
- Для некоторых пользователей это ускоряет заполнение форм.
- Для других использование мышки или тач-указателя невозможно или затруднительно. Они пользуются клавиатурой или специальным устройством.
Во многих веб-проектах, которые я видел, дизайнеры задают стили только для наведения мышки, но не для фокуса. Что же нам делать? Простое решение — использовать :hover стили для :focus.
/* инвертируем цвета при наведении и фокусе */ .btn:hover, .btn:focus color: #9555af; border-color: currentColor; background-color: white; >
И когда у нас будут стили для фокуса (только не до!), мы можем сбросить браузерные стили для кнопки:
.btn /* . */ /* все браузеры: сбрасываем дефолтный outline, так как у нас уже есть собственные стили */ outline: none; > /* Firefox: сбрасываем внутреннюю границу при фокусе */ .btn::-moz-focus-inner border: none; >
Попробуйте сами: если вы за компьютером, используйте Tab и Shift+Tab для навигации между кнопками:
Разбираемся с прилипшим фокусом
Есть небольшой недочёт. В некоторых браузерах, если кликнуть по ссылке или кнопке, применяются два псевдокласса:
«Активный» псевдокласс убирается сразу после того, как отпускается кнопка мыши или трекпада после нажатия. Но в некоторых браузерах после этого остаётся :focus стиль, пока пользователь не кликнет где-нибудь на странице.
В моих тестах, такое происходит в Chrome (66), Edge (16), и Firefox (60, только для ссылок). Safari (11.1), кажется, поумнее, и там нет такой проблемы.
Мы можем исправить это, используя новый псевдокласс :focus-visible (черновик спецификации). Этот элемент ещё не полностью проработан, но идея в том, что браузеры должны применять состояние :focus-visible только при взаимодействии с клавиатуры или подобных устройств, а не при клике.
Так как :focus-visible ещё не внедрён в браузеры, нам придётся использовать решение на JavaScript, такой как этот полифилл. Он действует по всей странице и добавляет класс focus-visible только элементам, которые получают фокус при использовании клавиатуры.
Давайте изменим стили, чтобы отделить стили :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, он будет добавлять класс js-focus-visible элементу .* Мы можем использовать это, чтобы убрать стили фокуса с элементов, которые не имеют класс _focus-visible*:
/* скрываем фокусные стили, если используется не клавиатура */ .js-focus-visible .btn:focus:not(.focus-visible) box-shadow: none; >
Более простой способ — определить фокусные стили только для класса focus-visible, но если полифилл неактивен (например, если JS не смог загрузится), то стили не применятся.
Окончательный вариант можно посмотреть на сайте Флоренса Вёршелда.
Следить за обновлениями можно через RSS или телеграм-канал.
Современный сброс стилей CSS
В этой статье вы узнаете о том, как сбрасывать CSS в наши дни.
Мой Твиттер — там много из мира фронтенда, да и вообще поговорим. Подписывайтесь, будет интересно: ) ✈️
Если честно, то кажется я слишком много и через чур увлеченно забиваю голову всякой нудной чепухой из CSS. Одним из таких моментов является сброс CSS, это возможно тот момент, который забрал у меня слишком много времени за последние годы.
В эпоху современной веб разработки, нам не так то и нужен загруженный сброс стилей или вообще совсем не нужен, поскольку проблемы совместимости CSS в браузерах сейчас встречаются куда реже, чем это было в дни старого доброго IE6. Это был момент времени, когда появились такие реализации сброса стилей в CSS, как normalize.css и спасли нас от ада с бесконечной вознёй при правке стилей. Но эти дни уже прошли и сейчас мы вполне можем доверять браузерам в этом плане, так что подобные подходы к сбросу стилей, в большинстве своём, уже довольно излишне.
Сброс разумных настроек по умолчанию
Мне до сих пор нравится делать сброс, так что я долго и усердно, годами ковырялся, как одержимый в Code golf (прим. это когда побеждает самый короткий и действенный подход в программировании ) стиле на этом направлении. Я всё объясню, что в этом коде где и как, но сначала посмотрите на него целиком:
/* Указываем box sizing */
*,
*::before,
*::after box-sizing: border-box;
>
/* Убираем внутренние отступы */
ul[class],
ol[class] padding: 0;
>
/* Убираем внешние отступы */
body,
h1,
h2,
h3,
h4,
p,
ul[class],
ol[class],
li,
figure,
figcaption,
blockquote,
dl,
dd margin: 0;
>
/* Выставляем основные настройки по-умолчанию для body */
body min-height: 100vh;
scroll-behavior: smooth;
text-rendering: optimizeSpeed;
line-height: 1.5;
>
/* Удаляем стандартную стилизацию для всех ul и il, у которых есть атрибут class*/
ul[class],
ol[class] list-style: none;
>
/* Элементы a, у которых нет класса, сбрасываем до дефолтных стилей */
a:not([class]) text-decoration-skip-ink: auto;
>
/* Упрощаем работу с изображениями */
img max-width: 100%;
display: block;
>
/* Указываем понятную периодичность в потоке данных у article*/
article > * + * margin-top: 1em;
>
/* Наследуем шрифты для инпутов и кнопок */
input,
button,
textarea,
select font: inherit;
>
/* Удаляем все анимации и переходы для людей, которые предпочитай их не использовать */
@media (prefers-reduced-motion: reduce) * animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
>
>
Ну, а теперь разбираемся
Начинаем мы с box-sizing . Тут я простым и элегантным движением сразу же сбрасываю все элементы и псевдоэлементы на box-sizing: border-box .
*,
*::before,
*::after box-sizing: border-box;
>
Кто-то считает, что псевдоэлементы должны наследовать параметры блочной модели, но я считаю это глупым. Если вы хотите использовать другое значение для box-sizing , то просто укажите его — ну это то, как я делаю, в любом случае. Я написал про box-sizing больше в CSS From Scratch.
/* Убираем внутренние отступы */
ul[class],
ol[class] padding: 0;
>
/* Убираем внешние отступы */
body,
h1,
h2,
h3,
h4,
p,
ul[class],
ol[class],
li,
figure,
figcaption,
blockquote,
dl,
dd margin: 0;
>
После box-sizing , я сбрасываю margin и padding , даже там, где они выставлены дефолтными настройками браузеров. Тут и так всё понятно, так что я не буду уделять этому моменту много внимания.
-
или
, то я хочу, чтобы он выглядел реально как список. Тут главное не переусердствовать, охватив всё, как в предыдущем моменте, что удалит все отступы.
body min-height: 100vh;
scroll-behavior: smooth;
text-rendering: optimizeSpeed;
line-height: 1.5;
>
Идем дальше: стили для body . Тут у меня всё просто. Очень полезно указать для body занять весь viewport , даже когда он пуст, делаю я это, выставляя min-height на 100vh . Ещё мне нравится плавный скролл к анкорам, так что тут я выставлю scroll-behavior: smooth .
Ещё, я выставил только два текстовых стиля. line-height на 1.5 , потому что по-дефолту стоит 1.2 , чего откровенно недостаточно в плане доступности и читабельности текста. Так же я выставил text-rendering на optimizeSpeed . Используя optimizeLegibility вы делаете ваш текст приятнее на вид, но можете столкнуться с серьёзными проблемами производительности, такими как задержки в 30 секунд при загрузке, так что я его стараюсь избегать. Хотя, я иногда добавляю его для секций с микротекстом.
ul[class],
ol[class] list-style: none;
>
Как и с отступами, я сбрасываю стилизацию списков только у элементов, у которых указан class .
a:not([class]) text-decoration-skip-ink: auto;
>
Для ссылок без указания класса, я выставлю text-decoration-skip-ink: auto , так что подчеркивание будет рендериться куда читабельнее. Вообще, это можно было бы выставить всем ссылкам, но у меня возникло несколько конфликтов, так что я оставил так, как написано выше.
img max-width: 100%;
display: block;
>
Дальше идут старые добрые резиновые изображения. Я решил сделать все изображения блочными элементами, потому что, откровенно говоря, жизнь слишком коротка, чтобы мириться с этим мелким, стрёмным отступом снизу и вообще, в реальности, изображения — особенно те, с которыми я работаю — обычно подразумевают под собой блочное поведение.
article > * + * margin-top: 1em;
>
Мне очень нравится этот трюк в CSS и я наконец-то осмелился добавить его в сброс. Так называемый “lobotomized owl selector” выбирает прямых потомков article и добавляет им сверху внешний отступ в 1em . Это указывает понятную периодичность в потоке контента у article . Вообще, на самом деле, я использую удобную штуку с .flow , сейчас уже почти в каждом проекте. Вы можете больше прочитать про это на 24 Ways. Да и вообще, мне так кажется, что это сейчас мой самый используемый CSS.
input,
button,
textarea,
select font: inherit;
>
Ещё одна вещь, которую я наконец то решился выставить по дефолту это font: inherit для инпутов, которые, проще говоря, делают то, что и должны делать. Хватит уже этого мелкого (mono, в некоторых случаях) текста!
@media (prefers-reduced-motion: reduce) * animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
>
>
Последнее, но уж точно не менее важное, это один @media запрос, который сбрасывает анимации, переходы и поведенческие настройки для скролла, но только в тех случаях, когда пользователь предпочитает как можно меньше всяких движений на странице. Мне нравится такая штука в сбросе стилей, с побеждающим специфичность селекторов !important , потому что в современных реалиях, если пользователь не хочет видеть лишних переходов и т.п., то он и не должен их видеть, вне зависимости от CSS при сбросе стилей.
Заключение
Вот и всё, вот он маленький и сброс для стилей, который делает жизнь куда проще. Если он вам приходится по вкусу, то смело можете его брать на вооружение! Берите его на GitHub или в NPM.
Стилизуем кнопки правильно
Кнопки есть практически в любом приложении. В их роли могут выступать самые разные элементы — собственно кнопки, ссылки и даже простые спаны. В любом случае важно правильно их оформить. В этом руководстве мы займемся созданием CSS-компонента кнопки.
Сброс стилей элемента
- Если при клике происходит переход на другой URL или изменяется большая часть контента на странице, используйте ссылку ( . );
- В остальных случаях подойдет обычная кнопка ( ).
Выбор правильного элемента имеет несколько преимуществ: это SEO-friendly и делает ваш сайт более доступным при работе с клавиатуры и для скринридеров.
Однако разработчики редко используют элемент . На большинстве сайтов кнопки представлены тегами , или . В чем причина такой нелюбви?
- Незнание. Некоторые разработчики даже не догадываются, что тег button можно использовать вне форм.
- Сложности стилизации. У кнопок очень много стилей по умолчанию, которые мешают созданию кастомного дизайна.
К счастью, у нас есть CSS reset. Давайте сбросим стили кнопки и сделаем ее похожей на обычный текст:
Минус этого подхода заключается в том, что стиль сбросился у ВСЕХ кнопок, и теперь посетитель сайта не сможет опознать их на странице.
Можно воспользоваться препроцессором (SCSS) и написать миксин для использования в нужных местах:
Создание CSS-компонента кнопки
Теперь, когда мы удалили все лишнее, давайте определим собственные стили для кнопки. Создадим для этого отдельный класс .btn , который можно будет указать и для button , и для a , и для любого другого элемента.
Внимание: при разработке CSS-компонента кнопки важно учитывать, что он может быть применен к ссылкам. Значит, необходимо изменить также дефолтные свойства ссылок.
Избегайте использования для кнопок цветов с малым контрастом. Часть ваших пользователей может иметь проблемы со зрением, а другая изучает сайт в неблагоприятных условиях (например, на телефоне под светящим солнцем) — не затрудняйте им жизнь.
- Проверка коэффициента контраста
- Почему контраст так важен?
Стилизация различных состояний
Кнопка уже выглядит неплохо, но кое-чего не хватает. Это интерактивный элемент, имеющий несколько состояний. Мы должны стилизовать и их.
У браузеров есть собственные дефолтные стили для состояний :focus (фокус на кнопке) и :active (нажатие), но часть из них мы уже сбросили. Не забудем также про состояние :hover (наведение курсора).
- Для нажатой кнопки создадим олдскульный эффект «утопления» с небольшим изменением насыщенности.
- При наведении курсора поменяем местами цвета фона и текста и добавим рамку.
- Для обозначения фокусировки используем такой же стиль.
Обратите внимание: стили фокуса очень важны. Многие пользователи по разным причинам пользуются клавиатурой для навигации по странице. Только стилизованный :focus помогает им понять, где они находятся в данный момент.
Только после того как мы позаботились о собственном оформлении фокуса можно убрать у кнопки дефолтные браузерные стили ( outline ).
Разбираемся с «липким» фокусом
Осталось решить еще одну небольшую проблему.
В ряде браузеров когда вы кликаете на ссылку или кнопку, она получает два псевдокласса: :active и :focus .
:active убирается сразу после того, как вы перестали нажимать на кнопку мышки или трекпад. Но :focus зачастую остается до тех пор, пока вы не кликнете на какой-нибудь другой элемент страницы.
Это поведение можно пофиксить с помощью нового псевдокласса :focus-visible.

Это свойство еще не принято официально, но идея заключается в том, что состояние :focus-visible устанавливается для элемента только при получении фокуса с клавиатуры (а не при клике).
При необходимости можно использовать JS-полифилл.
Давайте разделим состояния :hover и :focus в нашем компоненте:
.btn:hover < color: #9050AA; border-color: currentColor; background-color: white; >.btn:focus
Теперь подключим полифилл focus-visible.js. Он добавит элементу body класс js-focus-visible . Используем его, чтобы удалить тень с элементов, у которых нет класса focus-visible (то есть тех элементов, на которых сфокусировались не с клавиатуры):
.js-focus-visible .btn:focus:not(.focus-visible)
Кажется, было бы проще установить стили только для .focus-visible элементов, однако, так мы лишимся фоллбэка на тот случай, если скрипт не сработает.
maxua.com.ua Автоматизация интернет магазинов
Каждый браузер устанавливает свои значения стилей по умолчанию для различных HTML-элементов, нам их и надо сбросить, чтобы сайты отображались одинаково во всех браузерах.
Самый распространенный вариант сброса стилей это такой код:
* padding: 0; margin: 0>
Звездочка – универсальный селектор, который перебирает все теги по порядку. И иногда использует намного больше ресурсов компьютера, поэтому опытные верстальщики используют явное описание сброса для каждого HTML тега. Выглядит профессиональный CSS reset чаще всего так.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td
margin: 0; /* нулевая граница */
padding: 0; /* нулевые отступы */
border: 0; /* больше всего для картинок в IE6 */
outline: 0; /* точечная граница вокруг ссылок в Firefox */
font-size: 100%;
vertical-align: baseline;
background: transparent;
>
body
line-height: 1;
>
ol, ul
list-style: none; /* маркеры без кружочков */
>
blockquote, q
quotes: none;
>
blockquote:before, blockquote:after,
q:before, q:after
content: '';
content: none;
>
:focus
outline: 0; /* Firefox выделяет рамкой из точек все ссылки при нажатии */
>
ins
text-decoration: none;
>
del
text-decoration: line-through;
>
table
border-collapse: collapse; /* cellspacing="0" */
border-spacing: 0;
>
Я лично сам не пользуюсь множеством тегов при верстке макетов, такие как abbr, acronym, address, big, cite, code, del, dfn, em, ins, kbd, q, s, samp, small, strike, sub, sup, tt, var и другие – поэтому их можно вообще убрать. Получается, что каждый верстальщик вырабатывает CSS reset свой собственный, в котором нет ничего лишнего.