Building a button component

by:

Web Development

[ad_1]

In this post I want to share my thoughts on how to build a color-adaptive, responsive, and accessible &LTbutton> element. Try the demo and view the source!

Buttons are interacted with via keyboard and mouse in the light and dark themes.

If you prefer video, here’s a YouTube version of this post:

Overview #

Browser support: chrome true, Not supported × firefox true, Not supported × edge 12, Supported 12 safari true, Not supported × Source

The &LTbutton> element is built for user interaction. Its click event triggers from keyboard, mouse, touch, voice, and more, with smart rules about its timing. It also comes with some default styles in each browser, so you can use them directly without any customization. Use color-scheme to opt into browser-provided light and dark buttons too.

There are also different types of buttons, each shown in the preceding Codepen embed. A &LTbutton> without a type will adapt to being within a &LTform>, changing to the submit type.

&LT!-- buttons -->
button>&LT/button>
button type="submit">&LT/button>
button type="button">&LT/button>
button type="reset">&LT/button>

&LT!-- button state -->
button disabled>&LT/button>

&LT!-- input buttons -->
input type="button" />
input type="file">

In this month’s GUI Challenge, each button will get styles to help visually differentiate their intent. Reset buttons will have warning colors since they’re destructive, and submit buttons will get blue accent text so they appear slightly more promoted than regular buttons.

Preview of the final set of all button types, shown in a form and not in a form, with nice additions for icon buttons and customized buttons.
Preview of the final set of all button types, shown in a form and not in a form, with nice additions for icon buttons and customized buttons

Buttons also have pseudo classes for CSS to use for styling. These classes provide CSS hooks into customizing the feel of the button: :hover for when a mouse is over the button, :active for when a mouse or keyboard is pressing, and :focus or :focus-visible for assisting in assistive technology styling.

button:hover 
button:active
button:focus
button:focus-visible

Preview of the final set of all button types in the dark theme.
Preview of the final set of all button types in the dark theme

Markup #

In addition to the button types provided by the HTML specification, I’ve added a button with an icon and a button with a custom class btn-custom.

button>Default&LT/button>
input type="button" value="&LTinput>"/>
button>
svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true">
path d="..." />
&LT/svg>
Icon
&LT/button>
button type="submit">Submit&LT/button>
button type="button">Type Button&LT/button>
button type="reset">Reset&LT/button>
button disabled>Disabled&LT/button>
button class="btn-custom">Custom&LT/button>
input type="file">

Then, for testing, each button is placed inside of a form. This way I can ensure styles are updated appropriately for the default button, which behaves as a submit button. I also switch the icon strategy, from inline SVG to a masked SVG, to ensure both work equally well.

form>
button>Default&LT/button>
input type="button" value="&LTinput>"/>
button>Icon span data-icon="cloud">&LT/span>&LT/button>
button type="submit">Submit&LT/button>
button type="button">Type Button&LT/button>
button type="reset">Reset&LT/button>
button disabled>Disabled&LT/button>
button class="btn-custom btn-large" type="button">Large Custom&LT/button>
input type="file">
&LT/form>

The matrix of combinations is pretty overwhelming at this point. Between button types, pseudo-classes, and being in or out of a form, there are over 20 combinations of buttons. It’s a good thing CSS can help us articulate each of them clearly!

Accessibility #

Button elements are naturally accessible but there are a few common enhancements.

Hover and focus together #

I like to group :hover and :focus together with the :is() functional pseudo selector. This helps ensure my interfaces always consider keyboard and assistive technology styles.

button:is(:hover, :focus) 

Try a demo!

Interactive focus ring #

I like to animate the focus ring for keyboard and assistive technology users. I accomplish this by animating the outline away from the button by 5px, but only when the button is not active. This creates an effect that makes the focus ring shrink back to the button size when pressed.

:where(button, input):where(:not(:active)):focus-visible 
outline-offset: 5px;

Ensuring passing color contrast #

There are at least four different color combinations across light and dark that need consideration of color contrast: button, submit button, reset button, and disabled button. VisBug is used here to inspect and show all their scores at once:

Hiding icons from folks who can’t see #

When creating an icon button, the icon should provide visual support to the button text. This also means the icon is not valuable to someone with sight loss. Fortunately the browser provides a way to hide items from screen-reader technology so people with sight loss aren’t bothered with decorative button images:

button>
svg aria-hidden="true">...&LT/svg>
Icon Button
&LT/button>

Chrome DevTools showing the accessibility tree for the button. The tree ignores the button image because it has aria-hidden set to true.
Chrome DevTools showing the accessibility tree for the button. The tree ignores the button image because it has aria-hidden set to true

Styles #

In this next section, I first establish a custom property system for managing the adaptive styles of the button. With those custom properties I can begin to select elements and customize their appearance.

An adaptive custom property strategy #

The custom property strategy used in this GUI Challenge is very similar to that used in building a color scheme. For an adaptive light and dark color system, a custom property for each theme is defined and named accordingly. Then a single custom property is used to hold the current value of the theme and is assigned to a CSS property. Later, the single custom property can be updated to a different value, then updating the button style.

button 
--_bg-light: white;
--_bg-dark: black;
--_bg: var(--_bg-light);

background-color: var(--_bg);

@media (prefers-color-scheme: dark)
button
--_bg: var(--_bg-dark);

Leave a Reply

Your email address will not be published. Required fields are marked *