Стилизуем кнопки правильно
Если вы создаёте сайт или веб-приложение, там наверняка есть кнопки. А может быть ссылки, выглядящие как кнопки? В любом случае важно правильно их сделать.
Этап 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 или телеграм-канал.
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 свой собственный, в котором нет ничего лишнего.
Стилизуем кнопки правильно
Кнопки есть практически в любом приложении. В их роли могут выступать самые разные элементы — собственно кнопки, ссылки и даже простые спаны. В любом случае важно правильно их оформить. В этом руководстве мы займемся созданием 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 элементов, однако, так мы лишимся фоллбэка на тот случай, если скрипт не сработает.
Нормальный сброс. Normalize
Расскажите про ресеты и нормалайзы, что лучше использовать? — просят наши зрители Андрей, Сергей и Юрий. Знаете, это как отвёртка и молоток — что лучше? Все хороши. Давайте копнём глубже — к самой сути проблемы, которую они по-разному решают.
HTML хорош тем, что вы набросали тегов и всё — они сразу выглядят. И во всех браузерах всё примерно одинаково: чёрным Таймсом по белому body, да с синими ссылками. Эх, красота! Но в том и дело, что почти: точные стили для всех элементов хоть и рекомендованы сегодня в HTML5, но в каждом браузере свои.
В HTML 4 было всего 78 строк стилей по умолчанию, вроде head < display: none >или text-decoration: underline для ссылок. В WebKit, Chrome и Firefox сегодня около 1000 строк стилей, в которые смело можно снаряжать археологическую экспедицию. Но мы не будем, у нас и так дел хватает.
/* html.css */ HTML 4: 78; Chrome: 1123; Firefox: 907;
Разработчикам долго не мешало это примерное соответствие стилей, к тому же браузеры старались их изредка улучшать и унифицировать. Проблема была в другом: все эти отступы, рамки, подчёркивания всегда не по дизайну и приходится их снова и снова отменять для каждого элемента. Но потом кто-то придумал ластик, первый сброс стилей.
Звёздочка выбирает все элементы, а дальше начинается: margin: 0 , padding: 0 , border: 0 , Джофри, Серсея, Фрей и все остальные свойства, которые мешают вам жить. Способ довольно варварский: не только потому, что выбирает элементы, которым ничего не нужно сбрасывать, но и потому, что некоторые стили лучше не трогать, иначе всё развалится — например, элементы форм.
* < margin: 0; padding: 0; border: 0; joffrey: kill; cersei: kill; frey: kill; >/* ORLY? */ div , span
Следующей попыткой сделать из HTML стерильный набор кубиков, стал CSS Reset из Yahoo UI, который сбрасывал стили только там, где это было нужно. Ещё большую популярность получил Reset CSS Эрика Мейера, сделанный по мотивам Yahoo UI. Эти ресеты не только сбрасывали отступы, но и приводили к единому значению размер и семейство шрифта, выравнивание для текста и другие свойства.
Между ресетами Yahoo и Мейера были различия: Эрик, например, разумно не трогал элементы форм. Было много других решений, но все они решали единую задачу — сделать из сложных стилей по умолчанию простой констуктор, чтобы вы сразу могли писать свои стили, не сбрасывая встроенные.
Эти ресеты никогда не были чистыми сбросами браузерных стилей: нет-нет, да назначались цвета, выравнивание, начиналась борьба за кроссбраузерность. В итоге все проекты несли печать предпочтений конкретных авторов. Самым нейтральным из ресетов до сих пор остаётся Reset CSS Мейера, но даже он убрал вредный: focus < outline: 0 >— и правильно сделал.
/* YUI Reset */ html < color: #000; background: #FFF; >select < *font-size:100%; >/* Не забыть вернуть обводку */ :focus < outline: 0; >/* Забыл */
Многих ресеты раздражали: для внутренних блоков с содержимым приходилось восстанавливать стили не только для списков, но и базовых текстовых элементов вроде strong , em , code и других. У Yahoo даже был CSS Base, который назначал правильные базовые стили. После ресета, который отменял неправильные. Почему бы и нет.
Николас Галлахер и Джонатан Нил зашли с другой стороны: вместо того, чтобы сбрасывать примерно одинаковые браузерные умолчания, они подробно изучили все различия и проблемы — и сделали Normalize.css. Он делает везде одинаково и решает много проблем по пути.
С Normalize вам снова приходится убирать отступы со списков. Многих это провоцирует использовать элементы попроще, но будьте внимательны — это чревато диватозом. Зато Normalize берёт на себя сложности оформления элементов форм, поведение мобильных браузеров и много мелких багов.
Видите? Совсем другую задачу решает проект. Я на днях видел сайт, на котором после Normalize.css подключают Reset CSS, чтобы оставить нормализацию, но при этом получить нейтральный конструктор. Это конечно глупости, которые приводят к распуханию глобальных стилей. Уж лучше собрать свой гибрид — кода там всего ничего.
@import "normalize.css"; @import "reset.css"; @import "yui-reset.css"; @import "yui-base.css"; @import "h5bp.css";
Благо Normalize. css дотошно документирован: у каждого свойства стоит объяснение зачем оно нужно. В сомнительных местах, которые не нормализуют, а назначают более подходящие (по мнению авторов) умолчания — стоят пометки. Это помогает не просто слепо копировать его из проекта в проект, а использовать только нужные части.
Представьте, что вы в рамках проекта делаете модуль, который потом будет использоваться на другом сайте. У вас есть Normalize, а у них? Или наоборот: на ваш проект приходит сторонний модуль — а там нет Normalize и всё подогнано под браузерные баги, ну или особенности. Или даже есть Normalize, но другой версии. Так себе модульность получается.
А вот если бы вы сразу пошли в Normalize и скопировали нужные кусочки для каждой сложной ситуации — модуль бы вышел хороший, независимый. Normalize — это ещё и самая полная энциклопедия кроссбраузерных сложностей Да, это провоцирует лёгкое дублирование, но дарит гибкость — притом, что сжатие повторяющихся фрагментов — это хлеб с маслом для gzip.
Reset CSS не обновлялся с 2011 года, хотя до сих пор отлично работает. Но его эпоха уже прошла — на смену спешит новое свойство all со значением unset . Оно сбрасывает браузерные умолчания, где это нужно — почитайте на MDN. Normalize. css сейчас в моде и хорошо решает проблемы кроссбраузерности, но попробуйте использовать его как справочник. Ну так Reset или Normalize? Танцуйте от задачи.
/* Welcome to the */ .future
- Default style sheet for HTML 4
- Reset CSS
- Normalize.css
- CSS: all
«Доктайп» — журнал о фронтенде. Читайте, слушайте и учитесь с нами.
