Wednesday, September 27, 2017

A Simpler Slider Toggle

A few years ago I wrote an article about what I called a "slider toggle". Because it was written so long ago, and user-agents change pretty frequently, I wanted to revisit it to see if I could make it easier. In the original post, I gave two different orientations - one horizontal and the other vertical - but both using a single "round button" style. I won't be doing that in this post. In this post all versions are horizontally oriented; however, there are two styles - one a round button and one a rectangular version (with rounded corners).

Again, in HTML terms, these are stylized checkboxes, and the overall approach has not changed. The primary changes are in the CSS used to generate the different looks. I've also included, in this post, an approach that has the button labels inside the button as part of the background. To make this post as easy to understand as possible, I've grouped the markup, images of rendered code, and a demo together, and placed the CSS at the end. The CSS handles all the different styles - both round button (which is the default style) and rectangular button and with external labels, internal labels, and no labels.

☝ Note that the label tag wraps the entire element. This is to increase the size of the target and make the toggle button behave in keeping with the skeuomorphic design. To compensate for the fragmentation possible on some platforms (with regard to accessibility), the label tags have been given a role of text.

It's also important to note that the code provided uses an HTML checkbox rather than a different element and the checkbox or switch role. The ARIA checkbox and switch roles are widget roles, which will likely be treated differently than native HTML. It is likely an interface using a widget role will be less discoverable than a native element with no ARIA role specified.


External labels

This example uses labels outside the switch and is the pattern used in my original post. As mentioned in the earlier post, because the non-visual interface is a checkbox, the visual-only labels whose meaning is only proximity-based are hidden from accessibility devices.

HTML

<label for="push-mode" role="text">   Push Notifications   <span class="switch-label" aria-hidden="true">Off</span>   <span class="switch">     <input id="push-mode" type="checkbox" value="on">     <span></span>   </span>   <span class="switch-label" aria-hidden="true">On</span> </label> <label for="airplane-mode" role="text">   Airplane Mode   <span class="switch-label" aria-hidden="true">Off</span>   <span class="switch slider">     <input id="airplane-mode" type="checkbox" value="on">     <span></span>   </span>   <span class="switch-label" aria-hidden="true">On</span> </label>


Internal labels

This example uses labels inside the switch. It is not recommended due to the variance in text length.

HTML

<label for="location-mode" role="text">   Location Services   <span class="switch">     <span class="switch-label" aria-hidden="true">on</span>     <input id="location-mode" type="checkbox" value="on">     <span class="switch-label" aria-hidden="true">off</span>     <span></span>   </span> </label> <label for="email-mode" role="text">   Electronic communication   <span class="switch slider">     <span class="switch-label" aria-hidden="true">ON</span>     <input id="email-mode" type="checkbox" value="on">     <span class="switch-label" aria-hidden="true">OFF</span>     <span class="slider"></span>   </span> </label>


Longer text length makes buttons appear less like buttons as can be seen in the 'other alerts' and 'bluetooth' examples.

HTML

<label for="alert-mode" role="text">          Other Alerts   <span class="switch">     <span class="switch-label" aria-hidden="true">apagado</span>     <input id="alert-mode" type="checkbox" value="on">     <span class="switch-label" aria-hidden="true">encendido</span>     <span></span>   </span> </label> <label for="bluetooth-mode" role="text">   Bluetooth   <span class="switch slider">     <span class="switch-label" aria-hidden="true">apagado</span>     <input id="bluetooth-mode" type="checkbox" value="on">     <span class="switch-label" aria-hidden="true">encendido</span>     <span class="slider"></span>   </span> </label>


Unlabeled

This example does not use interior or exterior labels. It is not recommended due to the increase in cognitive load caused by the lack of those labels.

HTML

<label for="busy-mode" role="text">   Busy   <span class="switch">     <input id="busy-mode" type="checkbox" value="on">     <span></span>   </span> </label> <label for="dnd-mode" role="text">   Do Not Disturb   <span class="switch slider">     <input id="dnd-mode" type="checkbox" value="on">     <span></span>   </span> </label>


CSS

The CSS for these items is relatively simple. The rule for the label element is left out as it does not affect the switch.

CSS

.switch-label {   font-size: 0.5em; } .switch:before {   content: '';   display: inline-block; } .switch .switch-label {   display: table-cell;   padding: 0 0.5em;   text-align: center;   vertical-align: middle;   width: 50%; } .swtich .switch-label:after {   content: '';   display: block;   margin-top: 100%; } .switch {   background-color: rgb(255, 255, 255);   border: 1px solid rgb(0, 0, 0);   border-radius: 0.7rem 0.7rem 0.7rem 0.7rem;   box-shadow: 0 0 0.1rem 0.1rem rgb(187, 187, 187) inset;   cursor: pointer;   display: inline-table;   min-height: 1.2em;   min-width: 2.3em;   position: relative; } .switch * {   -webkit-touch-callout: none;   -webkit-user-select: none;   -moz-user-select: none;   -ms-user-select: none;   user-select: none; } .switch input[type="checkbox"] {   position: absolute;   z-index: -1; } .switch > span:last-of-type, .switch.slider > span:last-of-type {   background-image: linear-gradient(to bottom, rgb(255, 255, 255) 0%, rgb(153, 153, 153) 100%);   border: 1px solid rgb(0, 0, 0);   border-radius: 0.7rem 0.7rem 0.7rem 0.7rem;   display: table-cell; /*inline-block*/;   min-height: 90%;   position: absolute;   top: 0;   width: 50%;   z-index: 2; } .switch > input[type="checkbox"]:not(:checked) ~ span:last-of-type {   left: 0; } .switch > input[type="checkbox"]:checked ~ span:last-of-type {   right: 0; } .switch > input[type="checkbox"]:focus ~ span:last-of-type {   border: 1px solid rgba(204, 204, 204, 0.8);   box-shadow: 0 0 5px rgb(102, 102, 102); } .switch.slider {   border-radius: 0.2rem;   box-shadow: 0 0 0.1rem 0.1rem rgb(187, 187, 187) inset; } .switch.slider > span:last-of-type {   background-image: linear-gradient(to bottom, rgb(255, 255, 255) 0%, rgb(153, 153, 153) 100%);   border: 1px solid rgb(0, 0, 0);   border-radius: 0.2rem; } .switch.slider > input[type="checkbox"]:focus ~ span:last-of-type, .switch.slider:hover > span:last-of-type {   border: 1px solid rgba(204, 204, 204, 0.8);   box-shadow: 0 0 5px rgb(102, 102, 102); }


Although this may require a few tweaks, such as changing the colors to match your design, this should be ready for you to test in your page.

Happy coding

No comments:

Post a Comment