Button Group
Demo
Animal
Button Group Example
Animal
:root {
--bg-color: #EFEFEF;
--color: #222;
--border-width: max(0.15rem, 1px);
--radius: 0.35rem;
--padding: 0.8rem;
}
button {
padding: 0.5rem 0.7rem;
border: var(--border-width) solid #666;
border-radius: var(--radius);
background-color: var(--bg-color);
cursor: pointer;
}
/* Set the pressed button visual styling.
* 1.4.11 Non-text Content and 1.4.1 Use of Color are
* relvant success criteria.
* Essentially, we need to make sure that the different
* states (pressed versus not pressed) are visually
* perceptible. This state is programmatically perceptible
* by adding the aria-pressed attribute as noted in the HTML.
*/
button[aria-pressed="true"] {
color: var(--bg-color);
background-color: var(--color);
border-color: black;
}
/* We override the default focus indicator by setting our
* own outline.
*/
button:focus-visible {
outline: calc(2 * var(--border-width)) solid var(--color);
outline-offset: var(--border-width);
}
/* We provide a minor visual indication that something
* is interactive by adding a slight box shadow.
*/
button:not(:active):hover {
box-shadow: 0rem 0.1rem 0.25rem -0.1rem black;
}
/* We provide a minor visual indication that something
* is interactive by slightly changing the background color
* on hover.
*/
button[aria-pressed="false"]:hover {
background-color: white;
}
button[aria-pressed="true"]:hover {
background-color: #444;
}
/* Gives the button a "pressed" feel when it is pressed */
button:active {
scale: 0.95;
}
/* Flex with flex-wrap allows the button group to wrap
* if the viewport is small. The 1.4.4 Text Resizing
* 1.4.10 Reflow Success Criteria are relevant here.
*
* Gap provides spacing between each button. Without it the
* focus indicator may overlap with other buttons.
*/
.inner-group {
display: flex;
flex-wrap: wrap;
gap: calc(var(--border-width) * 6);
}
/* This visually styles the heading to look similar
* to a default
// we get all data-btn-group widget/components
let btnGroups = document.querySelectorAll('[data-btn-group]');
// for each data-btn-group, we're going to add event listeners
btnGroups.forEach(group => {
// we get all the buttons in the current button group
let btns = document.querySelectorAll('.inner-group button[aria-pressed]');
btns.forEach(btn => {
btn.addEventListener('click', (e) => {
// remove any other buttons pressed state
btns.forEach(otherBtn => otherBtn.setAttribute('aria-pressed', 'false'));
// set the current button pressed state to true
btn.setAttribute('aria-pressed', 'true');
});
});
});
Why use a button group?
Button groups offer a visually cohesive and organized way to present a set of related actions or options. By grouping buttons together, they provide a clear visual hierarchy that guides users to select from a defined set of choices, making the interface more user-friendly and intuitive. Button groups are especially useful when dealing with tasks like filtering content, navigating between views, or selecting preferences. They promote consistency in design and layout, enhance user engagement by making options readily accessible, and contribute to a more efficient and streamlined user experience. Additionally, button groups can be responsive, adapting to different screen sizes, and they are customizable, allowing designers to tailor their appearance to align with the overall aesthetics of the website or application.
What are some accessibility concerns?
- Keyboard Navigation:
- Ensure that all buttons within the group are keyboard accessible. Users should be able to navigate and select buttons using the Tab key, and the currently focused button should be visually distinguishable.
- Focus Management:
- When a button is selected, manage focus appropriately within the button group. Set focus to the selected button or its associated content, ensuring that users can easily navigate through the group.
- Semantic Markup:
- Use semantic HTML elements (e.g., <button> or <a>) to provide meaning to the buttons within the group. This helps screen readers understand the purpose and action associated with each button.
- Button Labels:
- Ensure that button labels are descriptive and convey the purpose of each button. Avoid vague labels like “click here” and provide clear, concise text that explains the action.
- Color and Contrast:
- Be mindful of color choices and contrast within the button group. Ensure that text and button backgrounds have sufficient contrast for users with low vision or color blindness.
- Active and Disabled States:
- Clearly indicate when a button is active, selected, or disabled, using visual cues and ARIA roles/attributes, to help users understand the state of each button within the group.
- Alternative Content:
- If the button group interacts with dynamic content changes or filters, provide alternative ways for users to access and understand these changes, especially for those who rely on screen readers.
- Color is not used as the only visual means of conveying information, indicating an action, prompting a response, or distinguishing a visual element.
- If a Web page can be navigated sequentially and the navigation sequences affect meaning or operation, focusable components receive focus in an order that preserves meaning and operability.
- Headings and labels describe topic or purpose.
- For all user interface components (including but not limited to: form elements, links and components generated by scripts), the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to user agents, including assistive technologies.