Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Creating a Simple, Accessible On/Off Switch


Published on

Have you ever tried to style checkboxes or radio buttons and ended up pulling your hair out? This presentation will explore a few simple tricks that can be used to style checkboxes and radio buttons. In this case, we will make them look like an on/off switch.

Published in: Education
  • Be the first to comment

Creating a Simple, Accessible On/Off Switch

  1. 1. Creating a simple, accessible on/off switch
  2. 2. Intro
  3. 3. This presentation is based on a simple GitHub Repo and page available here:
  4. 4. Checkbox and radio button switch: Github: checkbox
  5. 5. During this presentation, I’m going to ask you some questions - which you can answer in the chat window.
  6. 6. I'll be giving away three SitePoint Premium annual memberships as prizes to the best/quickest answers.
  7. 7. That gives you unrestricted access to over $20,000 worth of SitePoint books and courses! premium/
  8. 8. I want to start with a couple of accessibility-related questions.
  9. 9. And yes, these are incredibly easy, “prize-winnable” questions.
  10. 10. Question 1: What is the easiest and most effective way of identifying common accessibility problems in your site/ app?
  11. 11. Answer
  12. 12. Unplug the mouse The easiest and most effective way to check your site is using keyboard-only.
  13. 13. A large number of users rely on key-strokes (TAB, ARROW, ENTER, SPACE) or the equivalent of these keystrokes in order to navigate and interact with sites/apps.
  14. 14. If you cannot navigate or interact with your site/app using keystrokes only, then your site is potentially inaccessible to a large number of users.
  15. 15. Question 2: Why is this one of the most evil CSS rules you could ever write? *:focus  {  outline:  none;  }
  16. 16. Answer
  17. 17. Because this rule make it hard, if not impossible, for keyboard-only users to see which element is in focus and therefore very hard to navigate and interact with your site/app.
  18. 18. Time to explore how to style a simple radio button or checkbox!
  19. 19. Custom radios & checkboxes
  20. 20. Web designers and developers have always struggled with how to customise radio buttons and checkboxes.
  21. 21. The main issue is that radio buttons and checkboxes are notoriously hard to style - especially across multiple browsers and devices.
  22. 22. In the past, some developers resorted to JavaScript-based solutions to solve this problem.
  23. 23. In some cases this involved using JavaScript to remove the original radio or checkbox element making the end result inaccessible for a wide range of assistive technologies.
  24. 24. A solution
  25. 25. It is possible to style these elements without having to use JavaScript. And more importantly, we can make the end result accessible.
  26. 26. Let’s take a simple example of an on/off switch that can be applied to either radio or checkbox elements:
  27. 27. unchecked checked
  28. 28. The solution I’m about to demo, has five key accessibility features.
  29. 29. Well… many of these are not really features, they are just default behaviours that should not be overridden.
  30. 30. Feature 1: We will use the appropriate semantic elements - input and label elements. We will explicitly associate these elements using matching “for" and "id" values.
  31. 31. Feature 2: The label content can be used to describe the purpose of each switch for screen readers. This content is hidden off-screen.
  32. 32. Feature 3: We will make the two different states (“on” and “off”) clearly distinguishable using a tick icon for the “on” state. This will aid colour- blind users and some types of cognitive-impaired users.
  33. 33. (Keeping in mind that we should never use “color alone” to signal important information.)
  34. 34. unchecked checked
  35. 35. Feature 4: Because we are using native elements, the default keyboard behaviour will still be available. (Users can select a radio button or checkbox using the SPACE bar).
  36. 36. Feature 5: We will make the focus and hover states clearly visible. The focus state is especially important for keyboard only users.
  37. 37. checked checked hover checked focus
  38. 38. The markup
  39. 39. <div  class="switch">      <input          class="switch__control"          type="radio"          name="example01"          id="example01">      <label  class="switch__label"  for="example01">          <span  class="switch__content">Label  content</span>      </label>   </div> input label
  40. 40. <div  class="switch">      <input          class="switch__control"          type="radio"          name="example01"          id="example01">      <label  class="switch__label"  for="example01">          <span  class="switch__content">Label  content</span>      </label>   </div> radio
  41. 41. <div  class="switch">      <input          class="switch__control"          type="checkbox"          name="example01"          id="example01">      <label  class="switch__label"  for="example01">          <span  class="switch__content">Label  content</span>      </label>   </div> checkbox
  42. 42. <div  class="switch">      <input          class="switch__control"          type="radio"          name="example01"          id="example01">      <label  class="switch__label"  for="example01">          <span  class="switch__content">Label  content</span>      </label>   </div> id for
  43. 43. The class names
  44. 44. We will use BEM-like class names as these allow us to see the relationship between the parent element, descendant elements and modifiers.
  45. 45. /*  parent  module  */   .switch  {  }   /*  parent  modifiers  */   .switch-­‐-­‐xl  {  }   .switch-­‐-­‐lg  {  }   .switch-­‐-­‐md  {  }   .switch-­‐-­‐sm  {  }   .switch-­‐-­‐xs  {  }
  46. 46. /*  parent  module  */   .switch  {  }   /*  descendants  of  parent  module  */   .switch__control  {  }   .switch__label  {  }   .switch__content  {  }
  47. 47. How does it work
  48. 48. We can use the parent container (“switch”) to create the overall dimensions of the switch.
  49. 49. Parent Container “switch”
  50. 50. The radio button or checkbox control (“switch__control”) is then positioned on top of the parent. It will be given the same dimensions as the parent.
  51. 51. Control “switch__control”
  52. 52. The label (“switch__label”) is placed on top of the radio button and also given the same dimensions as the parent. We are hiding the control under the label.
  53. 53. We will then style the background of the label to look like a switch - including adding rounded corners and our background icon.
  54. 54. Label “switch__label”
  55. 55. And finally, the label content (“switch__content”) is hidden off screen so that it is available for screen readers, but does not clutter the visual appearance of the switch.
  56. 56. Adding states
  57. 57. Checkbox and radio button elements can be manually changed by users - from unchecked to checked etc.
  58. 58. These elements can also be given predefined boolean “checked” and “disabled” attributes.
  59. 59. <!-­‐-­‐  no  additional  attributes  -­‐-­‐>   <input  type="checkbox">   <!-­‐-­‐  boolean  checked  attribue  -­‐-­‐>   <input  type="checkbox"  checked>   <!-­‐-­‐  boolean  disabled  attribute  -­‐-­‐>   <input  type="checkbox"  disabled>
  60. 60. However, for this solution, most of the styling is applied to the label element, rather than the input.
  61. 61. Unfortunately, the label element has no checked, unchecked or disabled state of its own.
  62. 62. We can get around this using adjacent sibling selectors, which target any label element that is adjacent to (comes directly after) the input.
  63. 63. /*  unchecked  input  */   .switch__control  +  label  {  }   /*  checked  input  */   .switch__control:checked  +  label  {  }   /*  disabled  input  */   .switch__control[disabled]  +  label  {  }
  64. 64. unchecked checked disabled
  65. 65. We also want to style the :focus and :hover states of the switch, which can also be done using adjacent-sibling selectors.
  66. 66. /*  unchecked  input  */   .switch__control:hover  +  label  {  }   .switch__control:focus  +  label  {  }   /*  checked  input  */   .switch__control:checked:hover  +  label  {  }   .switch__control:checked:focus  +  label  {  }
  67. 67. unchecked hover unchecked focus unchecked checked checked hover checked focus disabled
  68. 68. SASS variables
  69. 69. Time for our final “prize-winnable” question (and yes, this one is also super-easy to answer)…
  70. 70. Question 3: Why would we want to be able to control all of the dimensions of our switch using one master SASS variable?
  71. 71. Answer
  72. 72. Because this makes it easier to maintain and to scale as needed.
  73. 73. We can define this one master variable by dividing our switch into scalable units.
  74. 74. 12x 6x 4x 1x
  75. 75. So, we have four different variables for the dimensions: - switch width - switch height - toggle width/height - gutter (space) around the toggle
  76. 76. $switch-­‐width:      3em;   $switch-­‐height:    ($switch-­‐width  /  2);          /*  1.5em  */   $toggle-­‐width:      ($switch-­‐width  /  3);            /*  1em  */   $toggle-­‐gutter:    ($switch-­‐width  /  12);        /*  .25em  */
  77. 77. Now it becomes easy to create a range of size variations, just by resetting the font-size.
  78. 78. $switch-­‐xl:    1.6em;   $switch-­‐lg:    1.4em;   $switch-­‐md:    1.2em;   $switch-­‐sm:    1em;   $switch-­‐xs:    .8em;
  79. 79. We can also set some quick variables for each of the background-colors used in different states.
  80. 80. $color-­‐toggle:                      #fff;   $color-­‐unchecked-­‐static:  #aaa;   $color-­‐unchecked-­‐hover:    #777;   $color-­‐checked-­‐static:      #00a000;   $color-­‐checked-­‐hover:        #006e00;   $color-­‐disabled:                  #ddd;
  81. 81. Transitions
  82. 82. I’m generally not a fan of transitions or animations unless they are being used to help “tell the story” of a UI component - help users understand what is happening.
  83. 83. Transitions should not draw attention to themselves. Ideally they should be simple and subtle.
  84. 84. For the checkbox, we could do a very simple transition to animate the switch from unchecked to checked - to help users understand what has happened.
  85. 85. We can do this by transitioning the “left” property as it changes from unchecked to checked.
  86. 86. .switch__label:after  {   left:  $toggle-­‐gutter;   transition:  left  .04s;   }   .switch__control:checked  +  label:after  {      left:  $switch-­‐height  +  $toggle-­‐gutter;   }
  87. 87. We can also softly animate the background-color to avoid a jarring change.
  88. 88. .switch__label  {   background:  $color-­‐unchecked-­‐static;   transition:  background  .2s;   }   .switch__control:hover  +  label,   .switch__control:focus  +  label  {      background:  $color-­‐unchecked-­‐hover;   }  
  89. 89. Demos
  90. 90. Checkbox and radio button switch: Github: checkbox
  91. 91. A simple, accessible language switcher module: switcher/ Github: switcher
  92. 92. Upvote - downvote module: Github: downvote
  93. 93. Russ Weakley Max Design Site: Twitter: Slideshare: Linkedin: