Converting divs into accessible pseudo-buttons
Let’s get this out of the way right now: I don’t think there is a compelling reason to turn an unopinionated HTML element like a div or a span into a button. ’Cause, you know, button already exists.
However, the question was asked, “If you had to do it though, could it be done?”.
This post attempts to take you through the steps of how to, in some ways, convert an unopionated HTML element into a accessible ‘pseudo-button’, and hopefully convinces you to just use a button .
I’ve ruminated on the use of button element before. That was four years ago. My opinion today differs. I don’t care about the speed impact; a button is slower because it does more. What’s more, for the number of buttons you are going to have on almost any page/app it adds up to very little overhead in real terms. I don’t think this is a sensible place to make economies.
The button element gives you things you might not see or appreciate but others might.
button powers
What does a button give you that other elements don’t? Here are a few choice features:
A button can receive focus. For the uninitiated this means someone can move to that element easily with, for example, just a keyboard. It gets a tabIndex whether or not you set it.
It supports an accessKey so you can set a keyboard shortcut to simply activate it.
It supports the disabled attribute, which, when added means the button stops receiving clicks.
It has a type attribute, allowing it to submit the form it lives in, if the type is set to submit . It can also reset a form type="reset" or just do nothing type="button" .
It has a value property, so you can conveniently set a different value than the text should you need it for scripting.
There are a bunch more features. If you’re interested, here are the details of the button element in the HTML 5.2 specification.
Meanwhile, an unopionated element, like a div gives you nothing. Hence the reason it’s demonstrably faster to render than a button.
Making a div more accessible
Hopefully that covers why you wouldn’t want to do this?
Well, as promised at the outset, we are going to see how far we can get anyway!
Say hello to our div :
role=“button”
ARIA (Accessible Rich Internet Applications) attributes provide the means to make a div appear as a button to a screen reader. Here is the intro to the button role page on MDN:
Adding role=“button” will make an element appear as a button control to a screen reader. This role can be used in combination with the aria-pressed attribute to create toggle buttons.
Right, so now our button would look like this:
aria-pressed
In our instance the button is going to be a switch; it can be pressed or not. With ARIA we could also make it the control for something like a menu with aria-expanded but instead we will use aria-pressed . So default it will need that too:
tabindex
We need the buttons to be focusable. That means we need a tabindex. By default we want the button to follow the normal sequence so we can set it to “0”. If you are unfamiliar with tabindex you should know that a negative number means the element is focusable but not in the normal focus sequence/sequential keyboard navigation. You want this if you have a modal that you want focusable but only via script, where you would use focus() when appropriate.
A tabindex of “0” means the element is focusable and happy to follow the normal order. A positive value e.g “1” provides an indication to the browser of how that element should be prioritised in the focus order. If you had elements with tabindex 1,2,3 respectively, your intention would be for the browser to focus them in ascending order. First 1, then 2, then 3. Note, it’s just an indication, not a promise! You should also avoid doing that unless you absolutely know you need to though; it’s liable to create an unpredictable experience for keyboard users. Just go with The Web’s Grain.
Right, with the tabindex attribute in, we are now looking like this:
keyboard event handlers
If you have a button element that has focus, pressing space, or enter will activate the button. When you convert a different element with role="button" you don’t get that functionality for free. You need to add your own keyDown listeners. You can add the listener to individual elements or, thanks to event bubbling, you can listen on a containing element. For example:
disabled (updated – thanks Darek)
The button element has a disabled state built in. When this is present, keyboard actions on the button are ineffective. For a pseudo-button you would need to add this functionality. Stylistically, this could be achieved easily enough. Something like:
However, you would still need to add the correct aria-* attribute, so that assistive technology knows what to do with the element. Without aria-disabled applied to the element it would only be visually ‘disabled’; not functionally.
Styles
There is no way point dancing around this – the button element is not straightforward to style. Browsers have opinions on how a button should look and you need to consider that.
However, switching out a button for a pseudo-button isn’t going to negate that need. Once an element has role="button" it is focusable and as a consequence, browsers indicate this focus in the same manner they would a real button . You will need to consider focus states and styles for when a button is toggled. If you are switching off the default outline for example, make sure you are adding a suitable sustitute.
Example pseudo-buttons
The MDN role="button" documentation gives solid examples that I have amended for this example. Here are a number of divs in a wrapping div. Pressing “Convert to pseudo-buttons” decorates the divs with the necassary attributes and event listeners to give us some of buttons goodnes. You can tab across them and pressing space or enter when one is selected toggles the aria-pressed attribute to indicate the state of the button.
Or you can view the embed here:
Summary
Makming unopionated elements into pseudo-buttons is not a trivial task. A lot of work has to be done, and therefore going forward, managed, to give pseudo-elements just some of the functionality built into the native button element.
There are inherent challenges and arguably shortcomings in dealing with buttons in some situations but appreciate that the friction is likely due to the fact that you are going against the grain of the medium you are working with.
Despite any frustrations, I’d suggest the end result will be far smoother if you choose to work with the grain instead.
If you enjoyed this post and/or it was useful, Say thanks with a coffee.
Learn how to chain and sequence animations with one of the Web Platform’s best kept secrets.
9 comments:
Hi Ben, Looks like nothing is happening when I press all those buttons! Something wrong?
Hi, are you pressing the ‘convert to pseudo-buttons’ button at the bottom first? Once that is done you should be able to press tab inside the wrapper and space to toggle selection of the focused button?
I did, but nothing more.
Hi, thanks for this article
Can you write examples or proof when button real slowly then div.
I think it’s very rare case or not?
Hi Dmitry, tests and explainer already linked at the beginning of the article: https://benfrain.com/we-need-a-better-button-its-too-slow-and-wont-behave/
TL;DR extremely rare!
Hi, your “disabled” section is incomplete. While you have adjusted the styling and prevented click events, the button is still almost fully usable. This means I can focus the button and I can activate the button with Enter/Space.
Additionally, you have to use “aria-disabled” as per WAI-ARIA Authoring Practices. For a button, “disabled” is converted into “aria-disabled”, while this does _not_ work for “disabled” or “data-disabled” within a div.
This is my go-to example on why you really would never want to re-implement a button (which you are also emphasizing in your article).
Hi Darek, I’ll add a little more about disabled in the main copy as you are quite right; it’s an essential factor in making something a button and needs factoring in. No idea why I used data-disabled in the original example! Thanks for the catch.
Thanks for this article. I am curious what your thoughts are on setting up a label element as a “pseudo-button” in order to enable progressive enhancement for CSS-only dialogs, carousels and so on?
The most frustrating thing about this topic, for me, is that right now it seems to me that there is an inevitable trade-off between accessibility and requiring javascript.
There *are* CSS-only methods for a lot of design patterns that traditionally rely on JS, but these are not accessible. These are mostly done with the “checkbox hack”, hence the use of labels.
I am very tempted to try setting up a label system with the pseudo-button functionality you described. I am curious about what your, or other people’s thoughts might be. It seems to be the strongest use-case for a pseudo-button.
Как сделать кнопку в html css? Красивые кнопки для сайта с примерами
Приветствую! В этой статье хочу поговорить про кнопки, на мой взгляд один из важнейших элементов в дизайне сайтов и приложений. Ведь, в большинстве случаев, кнопки нужны для того, чтобы заставить пользователя выполнить какое-либо действие (подписаться на рассылку, добавить товар в корзину, оставить комментарий, заказать обратный звонок и т.д.), которое можно так или иначе монетизировать. Мы же здесь не просто так собрались 😉
Итак из этой статьи вы узнаете:
- Для чего нужны кнопки и какие функции они выполняют
- Какие бывают кнопки и в чем их различия
- Как сделать кнопку в HTML
- Как сделать красивую кнопку в HTML и CSS
Также в конце статьи вас ждет небольшой бонус, который пригодится каждому сайтостроителю.
Но давайте по порядку.
Для чего нужны кнопки на сайте?
Ответ напрашивается сам собой: “Для того, чтобы их нажимали!”. И, действительно, выделяющаяся симпатичная кнопка привлекает гораздо больше внимания чем тусклая и унылая ссылка. С другой стороны, если вся страница заполнена разномастными кнопками, которые, переливаясь и моргая, требуют внимания пользователя, он, скорее всего, не поняв, что от него требуется, не нажмет ни на одну и просто закроет вкладку.
Поэтому использовать кнопки надо “экономно”, в идеале не больше 1-2 в видимой области экрана. При этом пользователю должно быть максимально понятно, что произойдет, если он нажмет на кнопку.
Какие бывают кнопки?
В моем представлении кнопки бываю двух типов, для каждого из них я использую соответствующие HTML-теги:
Кнопки-ссылки нужны для привлечения внимания к ссылке. Побуждают пользователя перейти на какую-либо страницу, например, страницу регистрации. Для них я использую тег <a> .
Кнопки-действия нужны для совершения какого-либо действия на странице (отправка формы, открытие модального окна и т.д.). Для этого можно использовать теги <input> или <button> . Я предпочитаю второй вариант, т.к. он гораздо более гибкий в настройке.
Хотя оба этих типа могут выглядеть одинаково (при помощи CSS), принципиальное их отличие в том, что важнейшим атрибутом тега <a> является href (цель ссылки), без которого этот тег даже не воспринимается браузером как ссылка и курсор при наведении на него не меняется на pointer. Это поведение, конечно, можно изменить при помощи “костылей”
В то же время атрибут href является невалидным для тега <button> , поэтому его не стоит использовать в качестве кнопки-ссылки. Опять же, можно сделать кнопку ссылкой, придумав какие-нибудь “костыли” типа
Но зачем это нужно. Все гораздо проще и понятнее.
Как сделать кнопку в HTML?
Итак, как я уже сказал, кнопки можно добавлять при помощи трех тегов <a> , <button> и <input> . Каждый из этих тегов имеет свои особенности и атрибуты и используется для разных целей.
Сделать кнопку-ссылку при помощи тега <a> , по сути, сводится к описанию его стилей в CSS. О стилях поговорим чуть позже.
Тег <button> используется для создания кнопок, при нажатии на которые должны происходить какие-либо действия, например отправка формы, очистка формы, открытие модального окна, загрузка изображения и т.д.
Основными атрибутами таких кнопок являются:
type: button | submit | reset
Тип кнопки. Это необязательный параметр, и его можно пропустить. Если кнопка находится внутри формы и атрибут type отсутствует, браузер посчитает, что тип кнопки — submit и попытается отправить форму обработчику.
Несмотря на слухи, которые ходят в интернете, о том, что тег <button> должен располагаться только внутри тегов <form> , на самом деле это не так 🙂 Если вдруг по какой-то причине Вам нужно или хочется поместить свою кнопку вне формы, которую она должна отправлять/сбрасывать/еще-что-то-делать, просто используйте атрибут form со значением соответствующим атрибуту id этой формы.
Кроме того, у тега button могут быть следующие атрибуты:
- autofocus — Автоматически устанавливает фокус браузера на кнопке при загрузке страницы
- disabled — Кнопка заблокирована и нажатие на нее не выполняет никаких действий
- formaction (только для типа submit) — адрес обработчика формы, на который отправляются данные из формы
- formenctype (только для типа submit) — Тип отправляемых данных. Может быть application/x-www-form-urlencoded , multipart/form-data , text/plain
- formmethod (только для типа submit) — HTTP-метод, при помощи которого пересылаются данные. Может быть get или post
- formnovalidate (только для типа submit) — Отключает автоматическую валидацию введенных данных
- formtarget (только для типа submit) — Указывает на то, как выводится результат обработки формы. Может быть _blank , _self , _parent , _top или значение атрибута name фрейма
- name — Имя кнопки (можно использовать если, например, в форме есть несколько кнопок, которые ее отправляют, и обработчику нужно знать, какая из них нажата)
- value — Значение кнопки (смысл примерно тот же, что и с name)
Как сделать красивую кнопку в HTML и CSS?
У каждого из нас свое представление о красоте: кто-то считает красивым закат на берегу моря, а кто-то — Ниссан Жук. О вкусах, как говорится, не спорят.
В моем представлении красивая кнопка — это кнопка, которая обладает следующими качествами:
Является интерактивной (т.е. реагирует на взаимодействие с ней пользователем). Отличительной чертой кнопок, является то, что их можно нажимать, следовательно у кнопки должно быть несколько состояний: дефолтное (состояние «покоя»), нажатое и «ховер» (при наведение курсора)
Выделяется на фоне других элементов. Посетители вашего сайта в основном бегло сканируют страницу в поисках нужной им информации. Если вам нужно, чтобы они нажимали на кнопки, сделайте их максимально заметными, контрастными. Главное не перестарайтесь.
Выглядит привычно и современно. Ваши посетители постоянно взаимодействуют с интерфейсами других сайтов и приложений. Поэтому они привыкли, что кнопки выглядят именно так, а не иначе. Если, в попытке привлечь их внимание, вы будете изобретать велосипед, пользователи могут просто не понять, что это кнопка.
Кроме того, тренды в дизайне интерфейсов и технологии их создания постоянно меняются, и за ними нужно успевать.
Если вы хотите узнать как сделать кнопку объемной или с эффектом «стекляшечности», как сделать картинку кнопкой и т.д. — почитайте статьи по дизайну интерфейсов за 2005-2009 гг. 🙂
Еще одним пунктом я бы добавил, расположение кнопки в привычных для посетителей местах (например, кнопки входа/регистрации в правом верхнем углу, или кнопка отправки формы под формой). Но это уже больше относится к дизайну всей страницы.
Итак, давайте для начала сделаем две обычные кнопки, одна из которых должна открывать модальное окно (кнопка-действие — <button> ) с формой для входа, а вторая — вести на страницу регистрации (кнопка-ссылка — <a> ). При этом обе кнопки будут выполнены в одной стилистике.
Для вывода иконок в кнопках, да и, в общем-то, везде я использую замечательный шрифт FontAwesome, а для текста — бесплатный шрифт Roboto, с которым одинаково хорошо смотрятся как кириллические, так и латинские символы.
Теперь добавим интерактивности: при наведении кнопки будут слегка подсвечиваться, а при нажатии затемняться (как бы утапливаться).
Вот и все! Две симпатичные кнопки готовы.
При наличии желания и времени можно их дополнить плавными анимированными переходами. Вот несколько примеров:
А теперь обещанный бонус для тех кто дочитал этот пост до конца.
Красивая анимированная кнопка наверх для сайта
В итоге должно получиться что-то похожее на это 😉
Надеюсь, эта статья была для вас полезна. Буду рад ответить на ваши вопросы в комментариях.
Как сделать кнопку в html из любого элемента на сайте
Многим известно, что для создания простой кнопки на html достаточно использовать тэг button или воспользоваться формой. Но как сделать кнопку абсолютно из любого элемента на сайте. Один из способов представлен в данной статье.
Он заключается в использовании события на jаvascript — onclick. Допустим, у нас имеется блок div с текстом
Дописываем к этому блоку событие onclick, в нем указываем команду для отображения сплывающего сообщения.
<div onclick=”alert(‘Кнопка нажата’)”>Текст</div>
Таким образом обычный текст в теге html на сайте превратился в кнопку. Но такой вариант будет несколько смущать пользователя, так как ему практичеси невозможно догадаться, что текст это кнопка. Поэтому немного оформим ее при помощи css.
<div onclick=”alert(‘Кнопка нажата’)” style=”cursor:pointer;”>Текст</div>
Параметр cursor отвечает за изменение курсора мыши при наведении на объект.
<div onclick=»alert(‘Кнопка нажата’)» style=»cursor:pointer;border-width:1px;border-style:solid;background-color:gray;width:100px;text-align:center;color:#ffffff;»>Текст</div>
Здесь мы добавили небольшую рамку для кнопки и фоновый цвет, получив визуально кнопку. Также мы прописали ширину кнопки и белый цвет текста.
Как было указано ранее, кнопку таким способом можно сделать из любого элемента на html странице.
How to style a div like the button-element?
I’ve noticed that when using the <button></button> element, the browsers will naturally assume that you want to center the inline content, and that the element is clickable. Is it possible to have a div behave in the same way through css? I went through the UA-stylesheet to see if I could figure it out, but nothing made it center it vertically.
The only other way i know to get the same result is with 2 divs. One wrapper with display: table , and a div with display: table-cell and vertical-align: middle .
But that creates an extra div. Is it possible to achieve the same behaviour with just one element?