UI Challenge: Switch
Switch is an input element that allows users to turn things on and off.
In this article
Specifications
A switch is a handy little input element in user interfaces that lets the users turns things on or off with a simple click. You’ve probably seen them before—they look like little toggles that you can slide from one side to the other. One side usually means “on” and the other means “off”, often shown with different colors to make it easy to understand.
How is a switch different from a checkbox? Well, a checkbox can have three states: checked, unchecked, or partially checked. A switch is simpler—it’s just on or off.
Here are some essential specifications of the Switch element that we will create:
- User Interaction: User should be able to click the switch to change its state, or even press the spacebar on the keyboard if the element is focused.
- Visual Feedback: The switch should provide clear visual feedback of its state. This typically involves a color change or a movement animation.
- Accessibility: The state should be readable by users with screen readers. Additionally, to aid understanding for users with cognitive disabilities, we should display text equivalents for the states (e.g., “on” and “off”).
- Form Integration: The switch should integrate with HTML form elements so that its state can be submitted in form submissions.
- Right-to-Left (RTL) Support: Support for devices with right-to-left writing directions, such as Arabic.
Also, it’s important to note that we will approach this with a progressive enhancement mindset, meaning we will achieve as much as possible without relying on JavaScript.
Basic Idea
The core idea is to utilize a checkbox element (i.e., <input type="checkbox" />
) as the primary control. We will apply opacity: 0
to this checkbox element, making it visually hidden while preserving its functionality. For the visual representation, we will replace it with another element that resembles a switch. This switch typically consists of a slider element and a bullet element.
Step 1: Basic Markup and Styling
This is the fundamental HTML structure we’re using. The <input type="checkbox">
element allows us to maintain the default behaviors of a checkbox, including keyboard navigation and seamless form interactions, without the need for custom JavaScript. Also, by assigning role="switch"
to the checkbox element, we ensure that assistive technologies like screen readers will accurately interpret its state as either “on” or “off”.
Next, we’ll utilize CSS custom properties to declare dimension and spacing values for later reference in other parts of our code.
Here is the result of our basic markup and styling:
Step 2: Visual Feedback
To provide visual cues indicating the “on” and “off” state, we’ll modify the appearance of our toggle switch. Specifically, we’ll alter the background color of the .slider
element and reposition the .bullet
element. To select these elements, we’ll employ the ~ (i.e. subsequent-sibling combinator) selector. This will allow us to target the .slider
and .bullet
elements that directly follow the checked input
element via :checked
.
Alter the background color
Reposition the .bullet
Use translateX
with the value of width - lebar bullet - (2 * gap)
.
Here is the result of the code we’ve implemented. To enhance clarity, we’ve increased the transparency of the input
element.
Step 3: Text Label
Users with cognitive disabilities may struggle to visually distinguish between the “on” and “off” states of a switch. To provide additional context, we’ll add text labels to the switch. However, to avoid redundancy and potential confusion for screen reader users, we’ll hide these labels from assistive technologies by using the aria-hidden="true"
attribute.
Depending on whether the input is checked or not, we’ll either hide or show one of the two text labels using the display property. This is controlled by the :checked
pseudo-selector.
Here is the result of our improvement:
Step 4: Finalization
We’ve finished building the fundamental parts. Next, we’ll move on to the finalization process, which involves the following steps.
Make the input
element fully transparent
Add animation
To make the user experience more engaging, we’ve included animations for the background color of the .slider
and the position of the .bullet
. These animations will provide visual cues to the user. To accommodate users who prefer reduced motion, we’ve added a media query to disable these animations when the prefers-reduced-motion
preference is set on the device.
Add focus indicator
A focus indicator is visually used to inform the user that an element has received focus, especially when triggered by keyboard interactions. We’ll add an outline to the .root
element when the input
element receives focus, using the :has
and :focus-visible
pseudo-selectors. We also need to remove the default outline from the input
element.
Supports right-to-left (RTL)
To ensure our implementation works for languages that are read from right to left, such as Arabic, we’ll need to add support for right-to-left writing direction. This is done by adding the dir="rtl"
attribute to a particular element, in this case the wrapper. And for our slider, this means reversing the direction of the .bullet
element.
Summary
By building our custom switch on top of the HTML <input type="checkbox" />
element, we can take advantage of all the default behaviors and interactions that come with it. This means our switch will work seamlessly with keyboard input and can be easily integrated into forms. Best of all, we get this functionality without having to write any extra JavaScript.