<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lindsey Kopacz</title>
    <description>The latest articles on DEV Community by Lindsey Kopacz (@lkopacz).</description>
    <link>https://dev.to/lkopacz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F105612%2F5720111f-ef6e-49a4-ac37-fc41a4ef051a.jpeg</url>
      <title>DEV Community: Lindsey Kopacz</title>
      <link>https://dev.to/lkopacz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lkopacz"/>
    <language>en</language>
    <item>
      <title>Creating an Accessible Range Slider with CSS</title>
      <dc:creator>Lindsey Kopacz</dc:creator>
      <pubDate>Mon, 04 May 2020 14:15:22 +0000</pubDate>
      <link>https://dev.to/lkopacz/creating-an-accessible-range-slider-with-css-4jkm</link>
      <guid>https://dev.to/lkopacz/creating-an-accessible-range-slider-with-css-4jkm</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally Posted on &lt;a href="https://a11ywithlindsey.com/blog/creating-accessible-range-slider-css" rel="noopener noreferrer"&gt;www.a11ywithlindsey.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I’ve always loved exploring how to make semantic, accessible elements aesthetically pleasing. And yes, it is possible. Challenging myself to do this has improved my CSS skills.&lt;/p&gt;

&lt;p&gt;Today we are going to talk about &lt;code&gt;input[type="range"]&lt;/code&gt;. These inputs where you select a value from a slider that has a thumb on it. You start with HTML that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"wrapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"range"&lt;/span&gt; &lt;span class="na"&gt;min=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; &lt;span class="na"&gt;max=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Selecting a purpose for an input range slider has many possibilities. You could use it for volume decibel. You could use it for an audio player. You could use it in a survey when rating from 1-10. Many times, when people make these features custom, they don't think to use the semantic features. They make a bunch of divs, and don't think about the keyboard or screen reader accessibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  Considerations
&lt;/h2&gt;

&lt;p&gt;Today I am going to be playing around with CSS to show you some of the possibilities. A lot of what I do in this post is a form of exploration. I learned a lot about &lt;code&gt;linear-gradient&lt;/code&gt; from research for this post, and we’ll be going over how I perceived it.&lt;/p&gt;

&lt;p&gt;When I go through these steps, I am considering the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Browser support&lt;/strong&gt; - I don't talk about browser support often. But according to the &lt;a href=""&gt;POUR&lt;/a&gt; principles, your site and application must be &lt;strong&gt;robust&lt;/strong&gt;. In the post, we’ll be going over many pseudo-elements for robust browser support.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Providing a fallback&lt;/strong&gt; - linear-gradient isn't always supported. It looks neat, but we have to ensure we have a clear way of presenting the range even if it's not possible&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't use JavaScript to hack&lt;/strong&gt; - just because you can doesn't mean you should.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Starting out
&lt;/h2&gt;

&lt;p&gt;When we first create that HTML, the appearance is pretty unimpressive.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5v7rcf5e9ul97sw45904.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5v7rcf5e9ul97sw45904.png" alt="An input range slider unstyled."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first thing we want to do is start with a clean slate in our CSS. We are going to add a &lt;code&gt;position: relative;&lt;/code&gt; on our &lt;code&gt;wrapper&lt;/code&gt; class. Then we add an &lt;code&gt;appearance: none;&lt;/code&gt; to our range input. If you check out the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/appearance" rel="noopener noreferrer"&gt;Mozilla docs&lt;/a&gt;, prepending &lt;code&gt;-webkit-&lt;/code&gt; should cover us for Firefox, Chrome, and edge.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.wrapper&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'range'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-appearance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvjgkehon1aejk6zzxyxu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvjgkehon1aejk6zzxyxu.png" alt="The slider with no track, only the thumb."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are a few things that I am going to “normalize” before I start going into the pseudo-elements. I am adding a width and a transparent background. For this particular item, I am going to add a &lt;code&gt;max-width&lt;/code&gt; as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'range'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-appearance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;7rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Browser Specific Pseudo Elements
&lt;/h2&gt;

&lt;p&gt;You'd think that you could just add a bunch of properties like height, background color, and margin, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'range'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;-moz-appearance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-appearance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;7rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.9rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#464646&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, if you use something like BrowserStack, you'll see something like this in IE11.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvh787dlwo54ln8l6eavk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvh787dlwo54ln8l6eavk.png" alt="An input range that has a blue fill for the lower track on the left side of the thumb and white fill for the upper track on the right side of the thumb. There is a dark grey background behind the slider."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Depending on what your analytics say for your audience's browser usage, this may be moot. And take that knowledge and apply it how you please. But I believe in robust browser support, so I’m going to cover the following pseudo-elements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;::-webkit-slider-runnable-track&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;::-moz-range-track&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;::-ms-track&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note: if you want to use these pseudo-elements, you have to create the selectors separately. That’s because if a browser isn’t supported, it’ll ignore the entire block.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'range'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;::-webkit-slider-runnable-track&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.9rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#464646&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'range'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;::-moz-range-track&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.9rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#464646&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'range'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;::-ms-track&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.9rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#464646&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'range'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;::-ms-fill-lower&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Chrome:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjrhbyvpbqjlf3f4vd0xo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjrhbyvpbqjlf3f4vd0xo.png" alt="Unstyled, round, light grey thumb, with a dark grey rectangular track."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Firefox:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fi8ql6ls32uf1w06ownmk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fi8ql6ls32uf1w06ownmk.png" alt="Unstyled, round, light grey thumb, with a dark grey rectangular track."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Edge:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3nx9g2064o2a6uiktndg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3nx9g2064o2a6uiktndg.png" alt="Unstyled, square, black thumb, with a dark grey rectangular track."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In IE11:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0i5rigoplky11f8thwie.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0i5rigoplky11f8thwie.png" alt="Unstyled, square, black thumb, with a dark grey rectangular track."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The main difference between the properties inside the blocks is the &lt;code&gt;::-ms-track&lt;/code&gt; pseudo-element needs a &lt;code&gt;color: transparent&lt;/code&gt;. We also need to have a &lt;code&gt;::-ms-fill-lower&lt;/code&gt; otherwise it looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcufesnlerbtu3nwh81zm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcufesnlerbtu3nwh81zm.png" alt="In IE11, unstyled, square, black thumb, with a rectangular track. The lower left track is a light blue and the upper right track is dark grey."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we add all these in, we have a starting out point for our volume slider:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/littlekope0903/embed/KKpMvXM?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Now we get to play around with the part I explored the most - linear gradient.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using linear-gradient
&lt;/h2&gt;

&lt;p&gt;Linear gradient confused me for the longest time. Because I focus on accessibility more than CSS, I never learned all the fun CSS functions. I want a volume bar that shows a triangle going from the lowest step to the highest step while giving a screen reader user the ability to control volume decibel.&lt;/p&gt;

&lt;p&gt;Our goal would be to have something that looks similar to this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6ln7ng3f3xuxf8u82rr8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6ln7ng3f3xuxf8u82rr8.png" alt="A dark grey right triangle, the right angle being the bottom right. There is a tall yet narrow rounded corner thumb."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;linear-gradient&lt;/code&gt; is a CSS function that transforms a background from one or many colors into another. This function takes on many arguments and can be very simple or very complex.&lt;/p&gt;

&lt;p&gt;From the most basic standpoint, here is what to consider when you're creating a linear gradient:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The angles and the direction of the gradient&lt;/li&gt;
&lt;li&gt;What colors you want in the gradient.&lt;/li&gt;
&lt;li&gt;What percent points you want the "fade" to start and stop. More formally, we call these color stops.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have a few examples that I played with that I show in the following CodePens.&lt;/p&gt;

&lt;p&gt;First a rainbow:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/littlekope0903/embed/povBzqX?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;A few of my observations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If there's no direction or angle specified, it assumes a horizontal (0deg) angle and top to bottom direction.&lt;/li&gt;
&lt;li&gt;If you don’t specify where the colors stop, the gradient assumes even distribution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now a French Flag:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/littlekope0903/embed/LYEvPay?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;My first observation: I associate linear gradients as fades. But if you want a straight line, you have to put the “stop” to be at equal values.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.flag--fr&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c"&gt;/* The gradient is going toward the right */&lt;/span&gt;
    &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="nb"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c"&gt;/* It starts at blue and stops in full opacity at 33% */&lt;/span&gt;
    &lt;span class="no"&gt;blue&lt;/span&gt; &lt;span class="m"&gt;33%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c"&gt;/* White starts in full opacity at 33% */&lt;/span&gt;
    &lt;span class="no"&gt;white&lt;/span&gt; &lt;span class="m"&gt;33%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c"&gt;/* White ends in full opacity at 66% */&lt;/span&gt;
    &lt;span class="no"&gt;white&lt;/span&gt; &lt;span class="m"&gt;66%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c"&gt;/* Red starts in full opacity at 66%
    and will continue till the background is over */&lt;/span&gt;
    &lt;span class="no"&gt;red&lt;/span&gt; &lt;span class="m"&gt;66%&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What if we want to start playing with fades and make it more blurry?&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/littlekope0903/embed/yLyrBQm?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;There is a gap between the stops at full opacity, and in between that gap, there is a fade. Fun stuff!&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.flag--fr&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="nb"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c"&gt;/* Blue stops at 27%, starts to
    fade into the next color */&lt;/span&gt;
    &lt;span class="no"&gt;blue&lt;/span&gt; &lt;span class="m"&gt;27%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c"&gt;/* White starts at 33% */&lt;/span&gt;
    &lt;span class="no"&gt;white&lt;/span&gt; &lt;span class="m"&gt;33%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c"&gt;/* White stops at 66%, starts to
    fade into next color */&lt;/span&gt;
    &lt;span class="no"&gt;white&lt;/span&gt; &lt;span class="m"&gt;66%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c"&gt;/* Red starts at 73% */&lt;/span&gt;
    &lt;span class="no"&gt;red&lt;/span&gt; &lt;span class="m"&gt;73%&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Febbzjh9xs9z1h08gaq4t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Febbzjh9xs9z1h08gaq4t.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm still a complete newb to this stuff, so I bet I am missing many details. But this is my "explain like I'm five" version of this.&lt;/p&gt;

&lt;p&gt;So, this feels like a tangent, but I promise it's not. We are going to use what we learned to create a volume range. We want to visually indicate that the volume is getting higher when we increase the range value. So we are going to take the code we were using at the end of the Starting Out section, and add a linear-gradient to it. Remember, these lines won't be blurry. We'll need to make sure that the percentage of the gradient matches.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;range&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;::-webkit-slider-runnable-track&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.9rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#464646&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="nb"&gt;bottom&lt;/span&gt; &lt;span class="nb"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;transparent&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="m"&gt;#464646&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;range&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;::-moz-range-track&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.9rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#464646&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="nb"&gt;bottom&lt;/span&gt; &lt;span class="nb"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;transparent&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="m"&gt;#464646&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;range&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;::-ms-track&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.9rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#464646&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="nb"&gt;bottom&lt;/span&gt; &lt;span class="nb"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;transparent&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="m"&gt;#464646&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, this looks like a right triangle, with the 90degrees mark being at the bottom right-hand corner.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdu8gdb3x2vux1de3x50j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdu8gdb3x2vux1de3x50j.png" alt="A dark grey right triangle, the right angle being the bottom right. The thumb is the original round thumb."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My SCSS linter will yell at me about having 2 background properties. But I like having the background as a solid color as a fallback. If the browser doesn’t support linear-gradient, we have a browser fallback.&lt;/p&gt;

&lt;h2&gt;
  
  
  Designing the thumb
&lt;/h2&gt;

&lt;p&gt;Now, with my goal, I want the thumb to be narrow and taller. CSS wise, this is relatively simple. Here’s the list of the pseudo-elements to make sure the thumb works across browsers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;::-webkit-slider-thumb&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;::-moz-range-thumb&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;::-ms-thumb&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Again, we have to separate these all out into their separate selectors, the same as the track.&lt;/p&gt;

&lt;p&gt;We want to set the &lt;code&gt;-webkit-appearance: none;&lt;/code&gt; and set height, width, border, and background. For Chrome, we add a negative &lt;code&gt;margin-top&lt;/code&gt; to balance out the positioning. The rest have no &lt;code&gt;margin-top&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'range'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;::-webkit-slider-thumb&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-appearance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'range'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;::-moz-range-thumb&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-appearance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'range'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;::-ms-thumb&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-appearance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.75rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we will see the track is tall and white with a black border.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ff85n7vizo9xh0koq08wf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ff85n7vizo9xh0koq08wf.png" alt="A dark grey right triangle, the right angle being the bottom right. There is a tall yet narrow rectangular thumb."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can just round out the edges and add a pointer cursor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'range'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;::-webkit-slider-thumb&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-appearance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'range'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;::-moz-range-thumb&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-appearance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'range'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;::-ms-thumb&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-appearance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.75rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The source that helped me out a lot with this section: &lt;a href="https://css-tricks.com/styling-cross-browser-compatible-range-inputs-css/#article-header-id-1" rel="noopener noreferrer"&gt;CSS Tricks&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding custom focus states
&lt;/h2&gt;

&lt;p&gt;I want to remove the focus styles (gasp!) from the entire input, and put it on the thumb itself. I couldn't figure out how to get rid of it on Firefox, so if you know, tweet at me and let me know!&lt;/p&gt;

&lt;p&gt;I am going to remove the outline on the entire input, and instead all box shadows to the input range on focus:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'range'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;:focus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;outline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'range'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;:focus::-webkit-slider-thumb&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt; &lt;span class="m"&gt;7px&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt; &lt;span class="m"&gt;#0065c4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'range'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;:focus::-moz-range-thumb&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt; &lt;span class="m"&gt;7px&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt; &lt;span class="m"&gt;#0065c4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'range'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;:focus::-ms-thumb&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt; &lt;span class="m"&gt;7px&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt; &lt;span class="m"&gt;#0065c4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/littlekope0903/embed/PowVaJd?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  When it gets hairy
&lt;/h2&gt;

&lt;p&gt;If you want the area between the thumb and the start of the range to be a different color, it can begin to get complicated. This differentiation indicates progress, not to be confused with the progress element.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6fr9h1h9ky6klm56hnl0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6fr9h1h9ky6klm56hnl0.png" alt="An audio bar slider with a round white thumb. The left of the thumb is navy blue indicating progess. The right of the thumb is pale blue, indicating non played audio."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unfortunately, using pseudo-elements, we only have support for Edge, IE, and Firefox. There is the pseudo-element &lt;code&gt;::-ms-fill-lower&lt;/code&gt; and &lt;code&gt;::-moz-range-progress&lt;/code&gt;, but none for Chrome. I’ve played with doing this in JavaScript, but it sounds like a performance nightmare and too much math.&lt;/p&gt;

&lt;p&gt;You can check out the CodePen where I use these pseudo-elements.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/littlekope0903/embed/rNabEbm?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Thanks for reading and learning with me! I hope I've helped you explore and also realize that aesthetic and accessibility are not mutually exclusive. You just have to take some time and think it through.&lt;/p&gt;

&lt;p&gt;Stay in touch! If you liked this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let me know on &lt;a href="https://twitter.com/LittleKope" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and share this article with your friends! Also, feel free to tweet me any follow up questions or thoughts.&lt;/li&gt;
&lt;li&gt;Support me on &lt;a href="https://www.patreon.com/a11ywithlindsey" rel="noopener noreferrer"&gt;Patreon&lt;/a&gt;! If you like my work, consider making a $1 monthly pledge. You’ll be able to vote on future blog posts if you make a \$5 pledge or higher! I also do a monthly Ask Me Anything Session for all Patrons!&lt;/li&gt;
&lt;li&gt;Take my &lt;a href="https://a11y-with-lindsey.ck.page/b4e437f629" rel="noopener noreferrer"&gt;10 days of a11y&lt;/a&gt; free email course.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pages.convertkit.com/4218bd5fb5/68dc4e412a" rel="noopener noreferrer"&gt;Be the first to learn about my posts&lt;/a&gt; for more accessibility funsies!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cheers! Have a great week!&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>css</category>
      <category>html</category>
    </item>
    <item>
      <title>How Accessibility Taught me to be Better at JavaScript - Part Two</title>
      <dc:creator>Lindsey Kopacz</dc:creator>
      <pubDate>Tue, 21 Jan 2020 18:26:00 +0000</pubDate>
      <link>https://dev.to/lkopacz/how-accessibility-taught-me-to-be-better-at-javascript-part-two-20af</link>
      <guid>https://dev.to/lkopacz/how-accessibility-taught-me-to-be-better-at-javascript-part-two-20af</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally Posted on &lt;a href="https://www.a11ywithlindsey.com/blog/how-accessibility-taught-better-javascript-part-two" rel="noopener noreferrer"&gt;www.a11ywithlindsey.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Content Warning: There are gifs in this post.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hey friends! Today's writing is going to be a follow up to &lt;a href="https://www.a11ywithlindsey.com/blog/how-accessibility-taught-better-javascript-part-one" rel="noopener noreferrer"&gt;How Accessibility Taught Me to be Better At JavaScript&lt;/a&gt;. If you have read my content, one of my favorite topics is about JavaScript and Accessibility. I speak about how JavaScript is &lt;strong&gt;actually&lt;/strong&gt; necessary to make interactive elements accessible.&lt;/p&gt;

&lt;p&gt;In my previous article, I talked about how I created a popup language menu with accessibility in mind. Making something functional and accessible was my first taste of vanilla JavaScript. The code certainly needed improvements, which we went over in the post. However, making the menu accessible started to help me understand JavaScript better.&lt;/p&gt;

&lt;p&gt;Today we are going over how I took some cringy “accordion” markup and made it accessible. Remember, an essential requirement was that I was not allowed to alter the content markup in any way. This page was a WordPress post, meaning I couldn’t go in and edit the post to be the markup I wanted it to be.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting out
&lt;/h2&gt;

&lt;p&gt;So, this right here was the starting markup.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/littlekope0903/embed/zYxRvbm?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I like clean HTML, and the inability to alter the markup got under my skin. This markup is a mess. First, it started with an unordered list, which isn’t the worst, but not ideal. Then inside the list item, it has a span for the title of the panel, an h3, another unordered list element, then a singular list item (meaning it’s not even a list?).&lt;/p&gt;

&lt;p&gt;I detest this markup so much.&lt;/p&gt;

&lt;p&gt;Now that I finished that soapbox, let's talk about a few goals here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hide the panels when we load the page&lt;/li&gt;
&lt;li&gt;Accordion panels open and close on click.&lt;/li&gt;
&lt;li&gt;Accordion panels open and close using the space bar or the enter key.&lt;/li&gt;
&lt;li&gt;Make that span &lt;strong&gt;focusable&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I added a little bit of SCSS to clean up the markup. I also added normalize.css in my CodePen settings.&lt;/p&gt;

&lt;p&gt;Now let's get on to how I approached this problem 4 years ago.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I approached the problem
&lt;/h2&gt;

&lt;p&gt;As a disclaimer, this is what Lindsey 4 years ago did. There's only one thing I &lt;strong&gt;wouldn't&lt;/strong&gt; do; however, even so, I would add more to this code, which I do in the next section.&lt;/p&gt;

&lt;p&gt;First, let's grab some variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accordion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;accordion&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, let's make a conditional statement. If that accordion exists, let's grab some other variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accordion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.accordion__header&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;panels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.accordion__panel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I added the conditional statement because we loop through that nodeList. I don’t want to be adding event listeners on &lt;code&gt;null&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now let's add the event listener&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accordion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.accordion__header&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toggleAccordion&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;panels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.accordion__panel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, let's add that function where the &lt;code&gt;.accordion__header&lt;/code&gt; represents &lt;code&gt;this&lt;/code&gt; and the &lt;code&gt;.nextElementSibling&lt;/code&gt; is the &lt;code&gt;.accordion__panel&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;toggleAccordion&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nextElementSibling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visually-hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we go to the element inspector and click on the accordion item, we notice the class toggle.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fy9aa3wdvwqhgo7bzfea6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fy9aa3wdvwqhgo7bzfea6.gif" alt="Clicking on 'Question 1' and seeing the accordion__panel class has a visually-hidden class being toggled."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then let's add the &lt;code&gt;visually-hidden&lt;/code&gt; class in the SCSS (source: &lt;a href="https://a11yproject.com/posts/how-to-hide-content/" rel="noopener noreferrer"&gt;The A11y Project&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nc"&gt;.visually-hidden&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="cm"&gt;/* IE6, IE7 */&lt;/span&gt;
  &lt;span class="nl"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;white-space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* added line */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's add the &lt;code&gt;visually-hidden&lt;/code&gt; class to the panels, so it visually toggles.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accordion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.accordion__header&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toggleAccordion&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;panels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.accordion__panel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;panels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;panel&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visually-hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you’re not thinking about accessibility, you may only add a click event and call it a day. Because these are not buttons, we have to add keypress events. We need to replicate the functionality of a button. This reason is why using semantic HTML is the best way to help accessibility.&lt;/p&gt;

&lt;p&gt;First, we have to add a tabindex of 0 to every header.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accordion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.accordion__header&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tabIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toggleAccordion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;panels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.accordion__panel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;panels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;panel&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visually-hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we do that, we can see the focus styles whenever we press the &lt;code&gt;tab&lt;/code&gt; key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9kg8ijualemvjeziw91k.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9kg8ijualemvjeziw91k.gif" alt="Tabbing through the accordion buttons seeing the clear focus styling from the default browser settings."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we press the enter or space key, nothing happens. That's because this isn't a &lt;code&gt;button&lt;/code&gt; element with built-in &lt;a href="https://www.a11ywithlindsey.com/blog/3-simple-tips-improve-keyboard-accessibility" rel="noopener noreferrer"&gt;keyboard events&lt;/a&gt; on click. That's why I preach from time to time about using semantic HTML.&lt;/p&gt;

&lt;p&gt;We have to add a &lt;code&gt;keypress&lt;/code&gt; event on the header elements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tabIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toggleAccordion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keypress&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toggleAccordion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This “works” but not quite how we want it. Because we haven't separated which key we want to toggle the class on, it wouldn't matter if we hit the &lt;code&gt;k&lt;/code&gt; key or the Space bar.&lt;/p&gt;

&lt;p&gt;So first, let's pass the event into the &lt;code&gt;toggleAccordion&lt;/code&gt; function and &lt;code&gt;console.log()&lt;/code&gt; that&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;toggleAccordion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nextElementSibling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visually-hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quick interruption here. Even though I prefer buttons for this, learning how to do it the wrong way taught me a LOT about JavaScript. I learned about event handlers and the event object. As someone who was a newb to JavaScript, I learned a great deal from exploring, even if this wasn't the best way to write the code.&lt;/p&gt;

&lt;p&gt;Back to talking about events. When we open this up in the console, we see a bunch of properties on that event.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fys2pmo6wakaktsuc3o8a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fys2pmo6wakaktsuc3o8a.png" alt="JavaScript Console in the Developer Tools showing the event properties for KeyPress. We see 2 properties that stick out to us. 'key' which has the value 'j' and 'code' which has the value of 'KeyJ.'"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I see a few things I can use, particularly the &lt;code&gt;code&lt;/code&gt; or &lt;code&gt;key&lt;/code&gt;. I'm going to use the &lt;code&gt;key&lt;/code&gt; property because it's a bit more verbose when I press the space bar.&lt;/p&gt;

&lt;p&gt;So I can do this, right?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;toggleAccordion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Enter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Space&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nextElementSibling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visually-hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well, no. Because this doesn't account for the &lt;code&gt;click&lt;/code&gt; event. Click events don't have the &lt;code&gt;code&lt;/code&gt; property. What types of properties do they have that we can use to make this work for this click event? Let's add the &lt;code&gt;console.log(e)&lt;/code&gt; back into our function and see what we have available to us.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Faw7exlugo34p1el5u500.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Faw7exlugo34p1el5u500.png" alt="JavaScript Console in the Developer Tools showing the event properties for Click. We see the 'type' property has the value of 'click.'"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So now, I check if the &lt;code&gt;type&lt;/code&gt; is click or &lt;code&gt;code&lt;/code&gt; is a space or enter.&lt;/p&gt;

&lt;p&gt;To make this a bit easier to read, I am going to separate the &lt;code&gt;code&lt;/code&gt; into a ternary operator that returns true or false. I didn't do that when I was initially doing this, but I wanted to add a little bit of readability into my conditional.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;toggleAccordion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pressButtonKeyCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Enter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Space&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;pressButtonKeyCode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nextElementSibling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visually-hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now we can click AND open with a space bar and enter key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fp1a4fv1972vpcgz1ek77.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fp1a4fv1972vpcgz1ek77.gif" alt="Clicking on the button the corresponding accordion section is opening and closing. Then we tab to it and open and close it with our keyboard."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are a ton of things I would improve upon, which we'll go over next. But if you want to take a look at the code, take a look at the CodePen below:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/littlekope0903/embed/gObvPwg?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would change now
&lt;/h2&gt;

&lt;p&gt;While this &lt;strong&gt;technically&lt;/strong&gt; works, it's not the most ideal. I had no idea what progressive enhancement was when I was learning JavaScript. I also had no idea what ARIA was.&lt;/p&gt;

&lt;p&gt;So let's start walking through it. If you read part 1, you’ll know that I am a big fan of having a &lt;code&gt;no-js&lt;/code&gt; class as a way to detect if JavaScript has loaded or not.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"accordion"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"accordion no-js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- Children elements --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the first thing we do when our JavaScript loaded is removing that class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accordion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;accordion&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;accordion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll add some default styling if the &lt;code&gt;no-js&lt;/code&gt; class is present, meaning that JavaScript wouldn't have loaded:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nc"&gt;.accordion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;.no-js&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;.accordion__header&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;.accordion__item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;border-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;:first-child&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;border-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;:last-child&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;.accordion__panel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;border-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've removed the button that isn't technically a button and had everything open by default.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fa7ec3gu12odz7jx9eufb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fa7ec3gu12odz7jx9eufb.png" alt="The rendered HTML in the browser with the no-js class. There are no more buttons and just the header and the text body, neither of which are hidden"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, back into the JavaScript. On the headers, we want to set the &lt;code&gt;aria-expanded&lt;/code&gt; attribute to false and give it a role of button.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tabIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;role&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aria-expanded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toggleAccordion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keypress&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toggleAccordion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While we are setting roles, I am going to set the panels' role to &lt;code&gt;region&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accordion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// header code&lt;/span&gt;
  &lt;span class="nx"&gt;panels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;panel&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;role&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;region&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I'll toggle aria-expanded and remove the toggling of the class in the function. As a note, even though we set the attribute to be a boolean, &lt;code&gt;getAttribute()&lt;/code&gt; returns a string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;toggleAccordion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pressButtonKeyCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Enter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Space&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ariaExpanded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aria-expanded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;pressButtonKeyCode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ariaExpanded&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;false&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aria-expanded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aria-expanded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We don’t need to visually hide the content because we have the button that controls the information. It's not a good screen reader user experience to read the information they didn't want. I love using &lt;code&gt;aria-expanded&lt;/code&gt; in CSS to toggle between &lt;code&gt;display: none&lt;/code&gt; and &lt;code&gt;display: block&lt;/code&gt; for the panel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nc"&gt;.accordion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nt"&gt;__header&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// more scss&lt;/span&gt;
    &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;aria-expanded&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'true'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;.accordion__panel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nt"&gt;__panel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nt"&gt;h3&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm going to be adding a few ARIA attribute to help associate the header and the panel together.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions" rel="noopener noreferrer"&gt;aria-controls&lt;/a&gt; - This can be confusing for some people. I highly recommend reading &lt;a href="https://tink.uk/using-the-aria-controls-attribute/" rel="noopener noreferrer"&gt;Léonie's post&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-labelledby_attribute" rel="noopener noreferrer"&gt;aria-labelledby&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I based this on the &lt;a href="https://www.w3.org/TR/wai-aria-practices-1.1/examples/accordion/accordion.html" rel="noopener noreferrer"&gt;WAI-ARIA authoring practices&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First, the headers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tabIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;role&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;// This will match the aria-labelledby on the panel&lt;/span&gt;
  &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`accordion-header-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aria-expanded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;// This will match the id on the panel&lt;/span&gt;
  &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aria-controls&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`accordion-section-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toggleAccordion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keypress&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toggleAccordion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we'll take those and make sure they match up accurately with the panels&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;panels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;panel&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// This will match the aria-controls on the header&lt;/span&gt;
  &lt;span class="nx"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`accordion-section-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;role&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;region&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;// This will match the id on the header&lt;/span&gt;
  &lt;span class="nx"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aria-labelledby&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`accordion-header-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to play around with the code, fork the CodePen and check it out.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/littlekope0903/embed/oNgExXZ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Was this the most ideal markup ever? No. Did this teach me a lot about JavaScript? Yes. Did this teach me the value of using buttons where I have keyboard events built-in? Yes.&lt;/p&gt;

&lt;p&gt;Stay in touch! If you liked this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let me know on &lt;a href="https://twitter.com/LittleKope" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and share this article with your friends! Also, feel free to tweet me any follow up questions or thoughts.&lt;/li&gt;
&lt;li&gt;Support me on &lt;a href="https://www.patreon.com/a11ywithlindsey" rel="noopener noreferrer"&gt;patreon&lt;/a&gt;! If you like my work, consider making a $1 monthly pledge. You’ll be able to vote on future blog posts if you make a \$5 pledge or higher! I also do a monthly Ask Me Anything Session for all Patrons!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://a11y-with-lindsey.ck.page/b4e437f629" rel="noopener noreferrer"&gt;Take the 10 days of a11y Challenge&lt;/a&gt; for more accessibility funsies!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cheers! Have a great week!&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>10 Ways to Help Accessibility at Conferences as a Speaker</title>
      <dc:creator>Lindsey Kopacz</dc:creator>
      <pubDate>Mon, 02 Dec 2019 13:07:52 +0000</pubDate>
      <link>https://dev.to/lkopacz/10-ways-to-help-accessibility-at-conferences-as-a-speaker-5dfp</link>
      <guid>https://dev.to/lkopacz/10-ways-to-help-accessibility-at-conferences-as-a-speaker-5dfp</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally Posted on &lt;a href="https://a11ywithlindsey.com/blog/accessibility-conferences" rel="noopener noreferrer"&gt;www.a11ywithlindsey.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hey friends! Wedding planning is starting to heat up with five months left to go. I was pretty ambitious about my writing schedule when I started my second year of blogging. I figured I had so much more free time on my hands versus what I had six months ago. But I didn’t account for the timeliness of my wedding and my other goals. Whoops. This blog is a work in progress, just like me.&lt;/p&gt;

&lt;p&gt;Anyways, about a month ago, I presented at a11yTO conference. It was the first time that I had spoken in a while. It reminded me of how much I’ve learned about accessibility beyond the web. Speaking at an accessibility conference forced me to think about my speaker tendencies. For example, I tend to forget words when I’m nervous. I wanted to make sure I wasn’t unintentionally excluding people due to my nerves. So I practiced my presentation several times. I thought critically about everything that I said that could exclude others. I even made a few mistakes that I will be fixing in the future.&lt;/p&gt;

&lt;p&gt;Here are my 10 tips for what I’ve learned from this past month.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing yourself with your pronouns
&lt;/h2&gt;

&lt;p&gt;I foresee a future where pronouns are standard. I’ve been adding my pronouns to as many places as I can. I added it to my email signature and my Twitter handle. It wasn’t until I spoke last that I thought, “why don’t I add it to my speaker slides?”&lt;/p&gt;

&lt;p&gt;However, it’s not enough to write your pronouns onto your slides. Introducing yourself with your pronouns is vital. Here’s the format I try to take on:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Hi! I am Lindsey Kopacz. My pronouns are she/her. Today we will be talking about [insert presentation name]."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Simple and Inclusive!&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating readable shortened links
&lt;/h2&gt;

&lt;p&gt;Whenever I link out to &lt;strong&gt;anything&lt;/strong&gt;, I ensure that I use bit.ly to create a shortened version. However, it’s not ideal to have "bit.ly/37oSXR". Did you know that if you have a free account with bit.ly, you can customize the link name?&lt;/p&gt;

&lt;p&gt;Here's how to get started:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to the &lt;a href="https://bitly.com/" rel="noopener noreferrer"&gt;bit.ly&lt;/a&gt; website and sign up for free.&lt;/li&gt;
&lt;li&gt;Once you're signed in and set up, go to your dashboard&lt;/li&gt;
&lt;li&gt;In the upper right-hand corner, click on “Create”&lt;/li&gt;
&lt;li&gt;In the Paste URL field, put your link.&lt;/li&gt;
&lt;li&gt;After you created your link, go to the “Customize Back-Half” field. After "bit.ly," type in your custom URL! (Note you cannot do custom domains unless you pay)&lt;/li&gt;
&lt;li&gt;Press save and copy!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Before:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fxh0vjuplk5ehm2n7oysa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fxh0vjuplk5ehm2n7oysa.png" alt="The bit.ly interface that shows the Customize Back-Half field with the randomly generated URL."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and After:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fkccuh2imodnhbdpjqw92.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fkccuh2imodnhbdpjqw92.png" alt="The bit.ly interface that shows the Customize Back-Half field with the URL typed 'testing-out-bitly.'"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And voilà! There you have it!&lt;/p&gt;

&lt;p&gt;When you include the visual text for this link, don't include the &lt;code&gt;http://&lt;/code&gt;. It doesn’t look sightly, and when your users go without it, it won’t impact your link!&lt;/p&gt;

&lt;p&gt;Including the link is not enough. Physically read it. Don’t say, “here’s the link if you want to check it out.” Instead, say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"If it's easier for you to follow along on your computer, the link is bit dot L Y slash testing dash out dash B I T L Y."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I’ll talk more about the phonetics a little later. But it’s essential actually to say your link. It helps those who are not able to see your slides.&lt;/p&gt;

&lt;h2&gt;
  
  
  Include your slide link at the beginning
&lt;/h2&gt;

&lt;p&gt;Now you have customized links! So your first slide after your introduction is your link to your slides. If someone prefers to use their assistive tech to go through your slides, they can.&lt;/p&gt;

&lt;p&gt;Also, for those who have trouble keeping up, your audience can take a look at the slide if they missed something. For example, I have ADHD and sometimes need to re-read certain things for the information to seep in.&lt;/p&gt;

&lt;p&gt;As a bonus, sometimes it’s helpful to include your link on all slides (in an unobtrusive way, of course). If you do this, you don't need to read it out on every slide, only on that first one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Spell out abbreviations, especially for links
&lt;/h2&gt;

&lt;p&gt;We don’t want to make any assumptions that people know how to spell abbreviations that we use. We also don't want to assume how we pronounce something that isn’t a common word is how someone else may interpret it.&lt;/p&gt;

&lt;p&gt;A lot of my bit.ly’s have the word “a11y” in them, and I have made the mistake of pronouncing it “ally” during a presentation. Even at an accessibility conference, how would the audience know that I am not saying “ally?” Instead, what I should be saying is “A eleven Y.”&lt;/p&gt;

&lt;p&gt;To take it a step further for necessary information (like links), I can ensure I spell out everything. So let's rewrite how I would announce the link in the section:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"If it's easier for you to follow along on your computer, here's the link spelled out: B I T dot L Y slash T E S T I N G dash O U T dash B I T L Y."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also, as a note, make sure you enunciate and speak slowly while you do this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Having proper contrast on your slides (and code samples!)
&lt;/h2&gt;

&lt;p&gt;Have you ever been watching a presentation, and you cannot see what the slides say? You have to think about contrast even more than you would for a web site. When you consider glare and fluorescent lighting, your slides could be washed out.&lt;/p&gt;

&lt;p&gt;Sometimes “pretty” slides aren’t the best contrast. I would much prefer that people were able to read my content. Something I’ve started doing is taking my blog theme and using those colors for my slides. That way, it’s very “on brand” and also high contrast.&lt;/p&gt;

&lt;p&gt;I will say, the biggest offender I've seen is when people go over code samples. Have you checked your VSCode theme for contrast? What about your CodeSandbox theme?&lt;/p&gt;

&lt;p&gt;So many code themes are notoriously lousy contrast. For example, I use the &lt;a href="https://marketplace.visualstudio.com/items?itemName=bceskavich.theme-dracula-at-night" rel="noopener noreferrer"&gt;Dracula At Night&lt;/a&gt; VSCode theme. While most of the colors have excellent contrast, comments only past for large text. Usually, if you use a VSCode theme, they have a Github repo where they tell you all the colors. If it’s not in the README, it’s usually in the code repo somewhere. I found mine in this &lt;a href="https://github.com/bceskavich/dracula-at-night/blob/master/src/themes/DraculaAtNight.ts" rel="noopener noreferrer"&gt;TypeScript file&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So the orange, green, and blue texts below have accessible contrast for my code theme (Note: I used WebAim's &lt;a href="https://webaim.org/resources/contrastchecker/" rel="noopener noreferrer"&gt;Contrast Checker&lt;/a&gt; to check the contrast):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F82dvmhvpm3btkvtrtw18.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F82dvmhvpm3btkvtrtw18.png" alt="Color Contrast Checker from webaim testing out the orange foreground color hex #ffb86c and the background color #0E1419. The color contrast is passing with a contrast of 10.88:1."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fol73m3scne3m6wwhsrgy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fol73m3scne3m6wwhsrgy.png" alt="Color Contrast Checker from webaim testing out the green foreground color hex #50FA7B and the background color #0E1419. The color contrast is passing with a contrast of 13.5:1."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Flwb8opmeif5o5g3fte6m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Flwb8opmeif5o5g3fte6m.png" alt="Color Contrast Checker from webaim testing out the cyan foreground color hex #8BE9FD and the background color #0E1419. The color contrast is passing with a contrast of 13.39:1."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But the comments, which I find essential to communicating to an audience what I am doing, is not:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F35rd15j5ejnjhfu787nn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F35rd15j5ejnjhfu787nn.png" alt="Color Contrast Checker from webaim testing out the comment foreground color hex #6272A4 and the background color #0E1419. The color contrast is failing all but large text with a contrast of 3.93:1."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The comments &lt;strong&gt;technically&lt;/strong&gt; pass for large text. But how would that look on a screen where there’s glare?&lt;/p&gt;

&lt;p&gt;If you're not using VSCode and using &lt;a href="https://codesandbox.io/" rel="noopener noreferrer"&gt;CodeSandbox&lt;/a&gt;, test out the theme. Write some comments and some code and use the wave tool or Google Dev Tools to check out the contrast. I always use the High Contrast theme for CodeSandbox.&lt;/p&gt;

&lt;h2&gt;
  
  
  Articulate alt text
&lt;/h2&gt;

&lt;p&gt;I am a big fan of being descriptive and creative in your alt text. One of my first blog posts was about &lt;a href="https://www.a11ywithlindsey.com/blog/writing-alternative-text-matters" rel="noopener noreferrer"&gt;Writing Alternative Text that Matter&lt;/a&gt;. A lot of times, we will use images as visual aids in our presentations. They’re fun and help you with storytelling. But you are excluding your visually disabled audience when you present the image without comment.&lt;/p&gt;

&lt;p&gt;So, before you present your gif or meme without comment, articulate it. Why do you have it in your presentation? Are you posting a gif that shows your annoyance when a client says something? Describe what the gif is doing and say it's a metaphor for how you feel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoid using vague words
&lt;/h2&gt;

&lt;p&gt;I tend to use vague words, instead of articulating what I mean. I'll point to items on the screen and say, "here we do this" or "this means." I've been trying to improve my word usage in my writing as well.&lt;/p&gt;

&lt;p&gt;I challenge myself to ask myself: “what is here?” Or “What is this?” The only time I use "this" now is when I am referencing JavaScript &lt;code&gt;this&lt;/code&gt;. But even then, I will be sure to clarify to my audience about its usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Content Warnings before Gifs
&lt;/h2&gt;

&lt;p&gt;In my blog post about &lt;a href="https://www.a11ywithlindsey.com//blog/reducing-motion-improve-accessibility" rel="noopener noreferrer"&gt;Reducing Motion&lt;/a&gt;, you learn that too much animation can be problematic. Certain animations from gifs cause dizziness and vertigo for those with vestibular disorders.&lt;/p&gt;

&lt;p&gt;There are a few gifs that I frequently see on Twitter that bother me for this reason. Give a content warning before you post a slide that has a gif.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not using too much slide animation
&lt;/h2&gt;

&lt;p&gt;Most slide animation is unnecessary. People are coming to your talk because they want to hear you speak. They aren't coming because they want to see fancy slide animations.&lt;/p&gt;

&lt;p&gt;If you want to reduce motion, I would go with fade animation versus sliding animation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ensure the conference is accessible
&lt;/h2&gt;

&lt;p&gt;We don’t have optimal control over the conference itself. But as speakers, we have a unique ability to influence. I mean, without speakers, conference organizers wouldn’t have a conference, right? Using your influence is especially important if the conference is &lt;strong&gt;for profit&lt;/strong&gt;. I don’t speak as often as I used to. But now, when I do, I feel that I can be particular. Tatiana Mac’s &lt;a href="https://gist.github.com/tatianamac/493ca668ee7f7c07a5b282f6d9132552#conference-logistics" rel="noopener noreferrer"&gt;Speaker Rider&lt;/a&gt;, particularly the conference logistics section, has inspired me.&lt;/p&gt;

&lt;p&gt;If the conference says they cannot afford it, I wonder:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do they provide an open bar at their festivities?&lt;/li&gt;
&lt;li&gt;Do they have unnecessary swag?&lt;/li&gt;
&lt;li&gt;Do they have random giveaways?&lt;/li&gt;
&lt;li&gt;What's the price of their ticket? Is it a free conference?&lt;/li&gt;
&lt;li&gt;Are there free ways to make the event more accessible?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are some inclusive conference examples that I've seen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Onsite post-conference events or Accessible transportation to them&lt;/li&gt;
&lt;li&gt;Transcriptionist or Sign Language Interpreter (or both)&lt;/li&gt;
&lt;li&gt;Ramps everywhere&lt;/li&gt;
&lt;li&gt;Alternatives to Speaker Podiums&lt;/li&gt;
&lt;li&gt;Elevators&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I’ve said this before, and I’ll repeat it. Accessibility isn’t about coding (even though this blog talks mostly about coding). Accessibility is about &lt;strong&gt;people&lt;/strong&gt;. Accessibility is about including and protecting people in minoritized groups. So I hope these tips help you! Let me know what tips you have!&lt;/p&gt;

&lt;p&gt;Stay in touch! If you liked this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let me know on &lt;a href="https://twitter.com/LittleKope" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and share this article with your friends! Also, feel free to tweet me any follow up questions or thoughts.&lt;/li&gt;
&lt;li&gt;Support me on &lt;a href="https://www.patreon.com/a11ywithlindsey" rel="noopener noreferrer"&gt;patreon&lt;/a&gt;! If you like my work, consider making a $1 monthly pledge. You’ll be able to vote on future blog posts if you make a \$5 pledge or higher! I also do a monthly Ask Me Anything Session for all Patrons!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pages.convertkit.com/4218bd5fb5/68dc4e412a" rel="noopener noreferrer"&gt;Be the first to learn about my posts&lt;/a&gt; for more accessibility funsies!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cheers! Have a great week and a great holiday if you're in America!&lt;/p&gt;

</description>
      <category>speaking</category>
      <category>conferences</category>
      <category>a11y</category>
    </item>
    <item>
      <title>Accessibility in d3 Donut Charts</title>
      <dc:creator>Lindsey Kopacz</dc:creator>
      <pubDate>Mon, 11 Nov 2019 15:51:18 +0000</pubDate>
      <link>https://dev.to/lkopacz/accessibility-in-d3-donut-charts-2bgh</link>
      <guid>https://dev.to/lkopacz/accessibility-in-d3-donut-charts-2bgh</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally Posted on &lt;a href="https://a11ywithlindsey.com/blog/accessibility-d3-donut-charts"&gt;www.a11ywithlindsey.com&lt;/a&gt;. If you'd like to see video examples of how screen readers interpret these, they are at the source!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hey friends! I got back from Toronto last week after speaking at a11yTO, one of the only conferences where I wanted to speak! I spoke about accessibility and JavaScript. This talk was loosely based on my &lt;a href="https://a11ywithlindsey.com/blog/a11y-js-seemingly-unconventional-romance"&gt;a11y and JS - A Seemingly Unconventional Romance post&lt;/a&gt;. So I'm pretty motivated to do a JavaScript-heavy blog post.&lt;/p&gt;

&lt;p&gt;One of my favorite posts that I've written was my &lt;a href="https://a11ywithlindsey.com/blog/accessibility-d3-bar-charts"&gt;accessible bar chart post&lt;/a&gt;. It's been about.... 6 months since I wrote that. So much for a series, ey? Today I am going to be going through how to make an accessible donut chart with d3. I'm not going to go through all the bells and whistles and interactions. It's going to be a donut chart with accessible data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting out
&lt;/h2&gt;

&lt;p&gt;As a disclaimer, because I am most familiar with d3, this is how I am building out my visualization. D3 renders SVG, so if it helps you, you can explore the final result and see how the SVG renders.&lt;/p&gt;

&lt;p&gt;I am still learning about d3, and am not exactly an expert at teaching it. I won't be going over d3 lingo in this blog post, so I recommend reading up a little bit on d3 if it's confusing to you. If it's available to you, I recommend checking out Shirley Wu's courses on &lt;a href="https://frontendmasters.com/teachers/shirley-wu/"&gt;Frontend Masters&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First things first, we have to get a dataset formatted. Most donut charts I see are on finance apps, so I am going to use a sample spending of a small business owner that I made up. I have no idea how much businesses spend on things, but the numbers are irrelevant here. The data structure is the most important! I am going to create an array of objects with 2 properties: label and spending.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Office Supplies&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;spending&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;460&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Transportation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;spending&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Business Services&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;spending&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Restaurant&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;spending&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Entertainment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;spending&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;220&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Travel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;spending&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Other&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;spending&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;125.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For my HTML, I have a &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; tag with an id of &lt;code&gt;donut-chart&lt;/code&gt; and some starting d3 code. I'm not going to go through d3 step by step here because this isn't a "how to d3" it's a "how to make visualizations accessible" post.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/littlekope0903/embed/oNvRQpP?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;What I've done here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Created a pie chart using &lt;code&gt;d3.arc()&lt;/code&gt; to generate the d attribute for the &lt;code&gt;&amp;lt;path&amp;gt;&lt;/code&gt; and &lt;code&gt;d3.pie()&lt;/code&gt; to format the data properly.&lt;/li&gt;
&lt;li&gt;Created a tooltip that when you hover over the arc, it highlights the corresponding data.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Why is this not accessible?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It ignores users who navigate with their keyboard.&lt;/li&gt;
&lt;li&gt;It ignores users who navigate with a screenreader.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Option 1: Make the tooltips accessible
&lt;/h2&gt;

&lt;p&gt;This option is my least preferred option. However, it’s a great lesson about how to test for accessibility, so I do like going through the exercise.&lt;/p&gt;

&lt;p&gt;To make tooltips accessible, we have to do a few things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a &lt;code&gt;tabindex="0"&lt;/code&gt; to all the arc paths so that we can tab to it.&lt;/li&gt;
&lt;li&gt;Add an &lt;code&gt;aria-describedby&lt;/code&gt; to each selected path with a unique value&lt;/li&gt;
&lt;li&gt;Add an &lt;code&gt;id&lt;/code&gt; to the tooltip that matched the &lt;code&gt;aria-describedby&lt;/code&gt; value. Because each &lt;code&gt;id&lt;/code&gt; must be unique, we have to create multiple tooltips.&lt;/li&gt;
&lt;li&gt;Make sure that we add not only mouse events, but focus and blur events.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;First, let's take care of the &lt;code&gt;tabindex&lt;/code&gt;. The below code makes the paths &lt;strong&gt;focusable&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;arcGroup
&lt;/span&gt;  .selectAll('.arc')
  .data(pie(data))
  .enter()
  .append('g')
  .attr('class', 'arc-group')
  .append('path')
  .attr('class', 'arc')
&lt;span class="gi"&gt;+ .attr('tabindex', 0)
&lt;/span&gt;  .attr('d', arc)
  .attr('fill', (d, i) =&amp;gt; colors[i])
  .on('mousemove', () =&amp;gt; {
    const { clientX, clientY } = d3.event
    d3.select('.tooltip').attr('transform', `translate(${clientX} ${clientY})`)
  })
  .on('mouseenter', d =&amp;gt; {
    d3.select('.tooltip')
      .append('text')
      .text(`${d.data.label} - $${d.data.spending}`)
  })
  .on('mouseleave', () =&amp;gt; d3.select('.tooltip text').remove())
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now we can reach the arcs with our keyboard.&lt;/p&gt;

&lt;p&gt;I'm going to add one small tweak and add a &lt;code&gt;stroke&lt;/code&gt; color around the arc when we focus on it. I'm going to remove the outline on this with CSS (gasp!) and add a stroke color on focus instead.&lt;/p&gt;

&lt;p&gt;In the JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;arcGroup
&lt;/span&gt;  .selectAll('.arc')
  .data(pie(data))
  .enter()
  .append('g')
  .attr('class', 'arc-group')
  .append('path')
  .attr('class', 'arc')
  .attr('tabindex', 0)
  .attr('d', arc)
  .attr('fill', (d, i) =&amp;gt; colors[i])
  .on('mousemove', () =&amp;gt; {
    const { clientX, clientY } = d3.event
    d3.select('.tooltip').attr('transform', `translate(${clientX} ${clientY})`)
  })
  .on('mouseenter', d =&amp;gt; {
    d3.select('.tooltip')
      .append('text')
      .text(`${d.data.label} - $${d.data.spending}`)
  })
&lt;span class="gi"&gt;+ .on('focus', function(d) {
+   d3.select(this)
+     .attr('stroke', 'black')
+     .attr('stroke-width', 2)
+ })
&lt;/span&gt;  .on('mouseleave', () =&amp;gt; d3.select('.tooltip text').remove())
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and in the CSS&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.arc&lt;/span&gt;&lt;span class="nd"&gt;:focus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;outline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, we have to add an &lt;code&gt;aria-describedby&lt;/code&gt; attribute to the focusable arcs. And remember, that means we need a matching id on the tooltip itself. After we do this, if a screen reader user focuses on an arc, the screen reader reads the content in those tooltips.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Each&lt;/strong&gt; arc and &lt;strong&gt;each&lt;/strong&gt; tooltip must have a unique identifier. That way, it won't confuse the assistive technology. To do that, I am taking not only the datum's but also the &lt;strong&gt;indexes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, let's add the &lt;code&gt;aria-describedby&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;arcGroup
&lt;/span&gt;  .selectAll('.arc')
  .data(pie(data))
  .enter()
  .append('g')
  .attr('class', 'arc-group')
  .append('path')
  .attr('class', 'arc')
  .attr('tabindex', 0)
  .attr('d', arc)
  .attr('fill', (d, i) =&amp;gt; colors[i])
&lt;span class="gi"&gt;+ .attr('aria-describedby', (d, i) =&amp;gt; `tooltip-${i}`)
&lt;/span&gt;  .on('mousemove', () =&amp;gt; {
    const { clientX, clientY } = d3.event
    d3.select('.tooltip').attr('transform', `translate(${clientX} ${clientY})`)
  })
  .on('mouseenter', d =&amp;gt; {
    d3.select('.tooltip')
      .append('text')
      .text(`${d.data.label} - $${d.data.spending}`)
  })
  .on('focus', function(d) {
    d3.select(this)
      .attr('stroke', 'black')
      .attr('stroke-width', 2)
  })
  .on('mouseleave', () =&amp;gt; d3.select('.tooltip text').remove())
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let’s add a tooltip per each piece of data and add an &lt;code&gt;id&lt;/code&gt; that matches the &lt;code&gt;aria-describedby&lt;/code&gt; value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;const tooltipGroup = svg.append('g').attr('class', 'tooltip')
&lt;/span&gt;
tooltipGroup
  .selectAll('.tooltip-item')
  .data(data)
  .enter()
  .append('g')
&lt;span class="gi"&gt;+ .attr('id', (d, i) =&amp;gt; `tooltip-${i}`)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now the last thing we have to do is add &lt;code&gt;focus&lt;/code&gt; and &lt;code&gt;blur&lt;/code&gt; events and correct the &lt;code&gt;d3.select()&lt;/code&gt; items on all the events.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;arcGroup
&lt;/span&gt;  .selectAll('.arc')
  .data(pie(data))
  .enter()
  .append('g')
  .attr('class', 'arc-group')
  .append('path')
  .attr('class', 'arc')
  .attr('tabindex', 0)
  .attr('d', arc)
  .attr('fill', (d, i) =&amp;gt; colors[i])
  .attr('aria-describedby', (d, i) =&amp;gt; `tooltip-${i}`)
  .on('mousemove', (d, i) =&amp;gt; {
    const { clientX, clientY } = d3.event
&lt;span class="gd"&gt;-   d3.select('.tooltip')
&lt;/span&gt;&lt;span class="gi"&gt;+   d3.select(`#tooltip-${i}`)
&lt;/span&gt;      .attr('transform', `translate(${clientX} ${clientY})`)
  })
  .on('mouseenter', (d, i) =&amp;gt; {
&lt;span class="gd"&gt;-   d3.select('.tooltip')
&lt;/span&gt;&lt;span class="gi"&gt;+   d3.select(`#tooltip-${i}`)
&lt;/span&gt;      .append('text')
      .text(`${d.data.label} - $${d.data.spending}`)
  })
  .on('focus', function(d, i) {
    d3.select(this)
      .attr('stroke', 'black')
      .attr('stroke-width', 2)

+   const { top, right, bottom, left } = d3.event
&lt;span class="gi"&gt;+     .target.getBoundingClientRect()
+
+   d3.select(`#tooltip-${i}`)
+     .append('text')
+     .text(`${d.data.label} - $${d.data.spending}`)
+     .attr('transform',
+       `translate(${(left + right) / 2} ${(top + bottom) / 2})`
+     )
&lt;/span&gt;  })
&lt;span class="gd"&gt;- .on('mouseleave', () =&amp;gt; d3.select('.tooltip text').remove())
&lt;/span&gt;&lt;span class="gi"&gt;+ .on('mouseleave', (d, i) =&amp;gt; d3.select(`#tooltip-${i} text`).remove())
+ .on('blur', function(d, i) {
+   d3.select(this).attr('stroke', null)
+   d3.select(`#tooltip-${i} text`).remove()
+ })
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's go over a bit of what we've done here.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We've altered the d3 selections to be more specific to &lt;code&gt;id&lt;/code&gt;s and not classes.&lt;/li&gt;
&lt;li&gt;We've positioned the tooltip on focus dependent on the approximate "middle" position. I've averaged the vertical and horizontal positions using &lt;code&gt;.getBoundingClientRect()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;I've removed the stroke when we blur off the event.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/littlekope0903/embed/VwwepoW?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Potential problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Depending on how large our dataset is, this means we have to have one tooltip rendered per datum. Numerous unique tooltips could become a performance issue in the long run.&lt;/li&gt;
&lt;li&gt;This technique is VERY JavaScript-heavy, and I worry about performance.&lt;/li&gt;
&lt;li&gt;When we use a screen reader, it announces all the labels with the word "Image" at the end. This has to do with the &lt;code&gt;role&lt;/code&gt; of the &lt;code&gt;path&lt;/code&gt; element.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are ways we could tweak this.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Keep the &lt;code&gt;id&lt;/code&gt; as one on the tooltip itself&lt;/li&gt;
&lt;li&gt;On &lt;code&gt;mouseenter&lt;/code&gt; update the &lt;code&gt;aria-describedby&lt;/code&gt; of the target to match that &lt;code&gt;id&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Remove the &lt;code&gt;aria-describedby&lt;/code&gt; on &lt;code&gt;mouseleave&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Change the contents on &lt;code&gt;focus&lt;/code&gt; and &lt;code&gt;mouseenter&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you want, you can fork my CodePen above and play around with this. Test it on slower connections. Test it with a screen reader. But I am going to move onto my preferred version, and that's creating a legend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 2: Creating a separate legend
&lt;/h2&gt;

&lt;p&gt;I prefer this option. The reason for this is it simplifies these problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;gives users a visual representation&lt;/li&gt;
&lt;li&gt;fewer performance risks&lt;/li&gt;
&lt;li&gt;people using screen readers and keyboards can access the information&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So let's take our original code and start adding a legend to it. You may have noticed that I have 2 variables in my code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;571&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;chartWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;189&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The reason for this is we have the &lt;code&gt;chartWidth&lt;/code&gt;, which is the width for the donut chart. But then we have the &lt;code&gt;width&lt;/code&gt; which is the width of the SVG itself. That way, we have room for the legend itself.&lt;/p&gt;

&lt;p&gt;First, let's get the legend built.&lt;/p&gt;

&lt;p&gt;The first thing I do is to create a group for the legend and position it with the &lt;code&gt;transform&lt;/code&gt; attribute. Positioning it this way makes it easier to position the children items.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;legendGroup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;svg&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;g&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;transform&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`translate(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;chartWidth&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 0)`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;class&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;legend-group&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above code positions the &lt;code&gt;g&lt;/code&gt; element beside the donut chart. Next, we create legend item groups and translate them based on their position&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;legendItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;legendGroup&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;g&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;g&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;transform&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`translate(20 &lt;/span&gt;&lt;span class="p"&gt;${(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Using the index of the array, we establish the vertical positioning of each item using multiplication (yay math!).&lt;/p&gt;

&lt;p&gt;Next, I am going to append a small square that color matches the corresponding arc. Because you know, legends usually have a key. This won't be for accessibility purposes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;legendItems&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;y&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;width&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;height&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fill&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Adding shapes doesn't do much for accessibility, so let's get some text in there.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;legendItems&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; - $&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;spending&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So we are good, right? Well, not quite. We need to test this visualization manually. Sure this is good for a visually abled user and a keyboard user. But does it work on a screen reader?&lt;/p&gt;

&lt;p&gt;I'm turning on VoiceOver and using it in Safari (you should always test in Safari since both are Native to macOS).&lt;/p&gt;

&lt;p&gt;I learned through manual testing is that every single &lt;code&gt;path&lt;/code&gt; element (the arcs) had a role of Image. And it announces on a screenreader. As a result, I'm going to put a &lt;code&gt;role="presentation"&lt;/code&gt; on each path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;arcGroup
&lt;/span&gt;  .selectAll('.arc')
  .data(pie(data))
  .enter()
  .append('g')
  .attr('class', 'arc-group')
  .append('path')
&lt;span class="gi"&gt;+ .attr('role', 'presentation')
&lt;/span&gt;  .attr('class', 'arc')
  .attr('d', arc)
  .attr('fill', (d, i) =&amp;gt; colors[i])
  .on('mousemove', () =&amp;gt; {
    const { clientX, clientY } = d3.event
    d3.select('.tooltip').attr('transform', `translate(${clientX} ${clientY})`)
  })
  .on('mouseenter', d =&amp;gt; {
    d3.select('.tooltip')
      .append('text')
      .text(`${d.data.label} - $${d.data.spending}`)
  })
  .on('mouseleave', () =&amp;gt; d3.select('.tooltip text').remove())
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Adding a presentation role tells the screen reader, "this is for presentation and screen readers can ignore."&lt;/p&gt;

&lt;p&gt;Now, all it reads are the groups of the text of the legend. We could do more to make it better, like add a Legend title and reduce the duplication (the reading of the groups is really repetitive). But hopefully, you have learned how to start thinking about accessible data visualizations.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/littlekope0903/embed/mddXJGm?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As I conclude this post, I want to emphasize something I often say: &lt;strong&gt;Manual testing is your friend&lt;/strong&gt;. What I did is not necessarily the &lt;strong&gt;right&lt;/strong&gt; answer. This is a &lt;strong&gt;potential&lt;/strong&gt; answer. The critical takeaway is that I always test what I am doing with a screen reader, a keyboard, and a mouse. I think about what options we are providing for our disabled users before I start building it, so it’s easy to adapt.&lt;/p&gt;

&lt;p&gt;Stay in touch! If you liked this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let me know on &lt;a href="https://twitter.com/LittleKope"&gt;Twitter&lt;/a&gt; and share this article with your friends! Also, feel free to tweet me any follow up questions or thoughts.&lt;/li&gt;
&lt;li&gt;Support me on &lt;a href="https://www.patreon.com/a11ywithlindsey"&gt;patreon&lt;/a&gt;! If you like my work, consider making a $1 monthly pledge. You’ll be able to vote on future blog posts if you make a \$5 pledge or higher! I also do a monthly Ask Me Anything Session for all Patrons!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pages.convertkit.com/4218bd5fb5/68dc4e412a"&gt;Be the first to learn about my posts&lt;/a&gt; for more accessibility funsies!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cheers! Have a great week!&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>javascript</category>
      <category>dataviz</category>
    </item>
    <item>
      <title>How Accessibility Taught me to be Better at JavaScript - Part One</title>
      <dc:creator>Lindsey Kopacz</dc:creator>
      <pubDate>Tue, 22 Oct 2019 14:14:05 +0000</pubDate>
      <link>https://dev.to/lkopacz/how-accessibility-taught-me-to-be-better-at-javascript-part-one-1l8p</link>
      <guid>https://dev.to/lkopacz/how-accessibility-taught-me-to-be-better-at-javascript-part-one-1l8p</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally Posted on &lt;a href="https://www.a11ywithlindsey.com/blog/how-accessibility-taught-better-javascript-part-one"&gt;www.a11ywithlindsey.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hey friends! Hope you’ve had a great week! This tweet I wrote a while back inspired me to write this blog post:&lt;/p&gt;

&lt;blockquote class="twitter-tweet"&gt;
&lt;p&gt;Fun fact about me: I started learning about JavaScript BECAUSE of accessibility, not in spite of it.&lt;/p&gt;— Lindsey Kopacz 🐞 (@LittleKope) &lt;a href="https://twitter.com/LittleKope/status/1148576284332699651?ref_src=twsrc%5Etfw"&gt;July 9, 2019&lt;/a&gt;
&lt;/blockquote&gt;

&lt;p&gt;One of the responses was “this would be a good blog post.” So here I am.&lt;/p&gt;

&lt;p&gt;In this post I’m going to go over:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Background on my first project as the sole front end developer&lt;/li&gt;
&lt;li&gt;The requirements of that project that led me to get better at JavaScript&lt;/li&gt;
&lt;li&gt;Creating a popup menu that allowed me to start playing with JavaScript&lt;/li&gt;
&lt;li&gt;The accessibility issues I faced that I solved using JavaScript&lt;/li&gt;
&lt;li&gt;Learning about progressive enhancement&lt;/li&gt;
&lt;li&gt;How I would improve things now&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;About 3-4 years ago, while I’d been in tech for a couple of years, I finally knew that I wanted to be a &lt;strong&gt;front end developer&lt;/strong&gt;. I talked to my boss about owning the front end development on a project. My boss loved finding fitting projects for developer strengths and their desired growth. The project she assigned to me wasn’t particularly sexy. However, it was perfect for my learning. It was &lt;strong&gt;not&lt;/strong&gt; a redesign.&lt;/p&gt;

&lt;p&gt;Different, right? You rarely hear about build projects that aren’t redesign. The job: migrate their content to WordPress. The client disliked their previous CMS’s user experience but wanted to keep their design the same. This project allowed me to improve their CSS, accessibility, and performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  The requirements
&lt;/h2&gt;

&lt;p&gt;There was one primary requirement that had me in a panic. I was &lt;strong&gt;not&lt;/strong&gt; allowed to use jQuery. At the time, I thought it was a silly requirement and couldn't fathom why we weren't allowed to use jQuery. JavaScript frameworks, like Angular and React, were still new to the market. Drupal and WordPress still heavily relied on jQuery.&lt;/p&gt;

&lt;p&gt;The other main requirement was that I was not allowed to alter the content markup in any way. We’ll talk more about this in another post, but this ended up being a bit of a blessing for progressive enhancement!&lt;/p&gt;

&lt;p&gt;I'm not going to talk &lt;strong&gt;too&lt;/strong&gt; much about WordPress or CSS in this post. However, I am going to quickly go over some of the tasks that I remember doing to get things set up with accessibility in mind. At the time, I understood accessibility from a UI developer perspective, but not about the intersection of JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting in JavaScript
&lt;/h2&gt;

&lt;p&gt;We had a base theme at our agency, and I used that to get started. The theme was a blank slate with CSS and some JavaScript for accessible navigation. The first time I had to encounter JavaScript was when I created a language dropdown menu.&lt;/p&gt;

&lt;p&gt;This website had many language sites, over 20. This menu’s purpose was to switch the language. We kept the existing functionality, which was a menu of links to each languages' homepage. Ideally, I would want to have the language switcher to get the page the user was on. However, remember, we were not changing any of the functionality; it was a migration project.&lt;/p&gt;

&lt;p&gt;Starting with the JavaScript, I created a button with an unordered list. Then we are going to use &lt;code&gt;addEventListener&lt;/code&gt; to toggle a &lt;code&gt;visually-hidden&lt;/code&gt; class. To read more about visually hidden, check out the &lt;a href="https://a11yproject.com/posts/how-to-hide-content/"&gt;A11y Project's post&lt;/a&gt; about it.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/littlekope0903/embed/KKPVjPb/?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Simple enough, right?&lt;/p&gt;

&lt;p&gt;Wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessibility Issues
&lt;/h2&gt;

&lt;p&gt;When we do it this way, we can focus on links that are not visible. Take a look at this gif, and particularly the bottom left corner where you see the links. Do you notice when we focus on the button, we see a blue outline? When we start tabbing again, &lt;strong&gt;all the links&lt;/strong&gt; we hid are focusable. We cannot see &lt;strong&gt;where&lt;/strong&gt; it the focus of the link is&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OpE7IrhR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/nwsuicnd17z25a3qp7sa.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OpE7IrhR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/nwsuicnd17z25a3qp7sa.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What I did in the past was &lt;strong&gt;way more&lt;/strong&gt; overkill than I needed. I set all the tabindexes of the links inside that menu to be &lt;code&gt;-1&lt;/code&gt; upon page load. In that event listener, I also checked to see if the class existed and based the tabindex toggle off that. There is a silver lining of me going over the top with my code. I learned a lot about the properties of HTML elements in JavaScript. Which was valuable to me strengthening my skills in JavaScript. All while learning about focus management, which is important for accessibility.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/littlekope0903/embed/KKPzZXM/?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--INXIiETt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/09p6h5udbcbtwa3hi790.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--INXIiETt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/09p6h5udbcbtwa3hi790.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ah much better, at least functionally.&lt;/p&gt;

&lt;p&gt;When I first started, I thought that &lt;code&gt;display: none&lt;/code&gt; was always bad for accessibility. But it's not. If something isn't open, &lt;strong&gt;nobody&lt;/strong&gt; should be able to access it, not even screen reader users. So I'm going to change it up a bit.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I wish I had done:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;remove the &lt;code&gt;visually-hidden&lt;/code&gt; class&lt;/li&gt;
&lt;li&gt;set &lt;code&gt;.lang-menu&lt;/code&gt; to &lt;code&gt;display: none&lt;/code&gt; and when I append the &lt;code&gt;.open&lt;/code&gt; class, change styling to &lt;code&gt;display: block&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Change the toggle classList to toggle the class &lt;code&gt;open&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/littlekope0903/embed/wvwGpzV/?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Doing the above steps won't solve the problem entirely, though. Let's talk about progressive enhancements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Progressive Enhancements that I wish I had done
&lt;/h2&gt;

&lt;p&gt;Unfortunately, neither of these strategies account for progressive enhancement. If JavaScript doesn’t load or loads slowly, we want people to still able to access the navigation menu. Let’s say JS doesn’t load, what happens to our users for this implementation?&lt;/p&gt;

&lt;p&gt;If JavaScript doesn't load and the &lt;code&gt;ul&lt;/code&gt; element has &lt;code&gt;display: none&lt;/code&gt;, nobody can &lt;strong&gt;ever&lt;/strong&gt; see the language menu. That's because there's no way to toggle the menu open without the event listeners.&lt;/p&gt;

&lt;p&gt;There are a few things I would do for progressive enhancement.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a &lt;code&gt;no-js&lt;/code&gt; class&lt;/li&gt;
&lt;li&gt;Remove that class as soon as JavaScript loads.&lt;/li&gt;
&lt;li&gt;Change up the open/close to focus more on the "close" and load a class in upon JavaScript loading.&lt;/li&gt;
&lt;li&gt;Create some default styling with &lt;code&gt;no-js&lt;/code&gt;, so it doesn't look unsightly (I'm not going to do that here)&lt;/li&gt;
&lt;li&gt;Hide the button visually and from assistive technology, if &lt;code&gt;no-js&lt;/code&gt; is present.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/littlekope0903/embed/YzKGEWy/?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding context with ARIA
&lt;/h2&gt;

&lt;p&gt;If you've read my &lt;a href="https://www.a11ywithlindsey.com/blog/beginning-demystify-aria"&gt;Demystifying ARIA blog post&lt;/a&gt; you know that I add ARIA only at the end when I need more context. I didn't know anything about ARIA when I first started working as a web developer, so I never added that to the code.&lt;/p&gt;

&lt;p&gt;Here are the ARIA attributes that I am going to add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;aria-expanded&lt;/code&gt; to indicate to a user whether the menu is open or closed. The value toggles between true and false on the event listener.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;aria-haspopup&lt;/code&gt; to indicate that the element has a popup context menu or sub-level menu.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/littlekope0903/embed/BaBQVQg/?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;To test on macOS:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;open up Safari and turn on a screen reader using cmd + F5.&lt;/li&gt;
&lt;li&gt;Use VoiceOver Commands to select the button. It should read “Open, Collapsed, Popup button.”&lt;/li&gt;
&lt;li&gt;Press enter. The screen reader should read “Open, Expanded, Popup Button.”&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;See the video below go to the &lt;a href="https://www.a11ywithlindsey.com/blog/how-accessibility-taught-better-javascript-part-one"&gt;original post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These aria attributes give direction to a screen reader user about &lt;strong&gt;how&lt;/strong&gt; to interact with the button. It would be even better if I had a more verbose button label with more context telling you what you're opening up, too!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;It's really fun seeing how my code has evolved as an accessibility focused web developer. I am going to make a second post about the other main accessibility issue I came up with for this project. This post was starting to get REALLY lengthy! I needed JavaScript to solve these issues. I also needed JavaScript to learn about Progressive Enhancement.&lt;/p&gt;

&lt;p&gt;Stay in touch! If you liked this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let me know on &lt;a href="https://twitter.com/LittleKope"&gt;Twitter&lt;/a&gt; and share this article with your friends! Also, feel free to tweet me any follow up questions or thoughts.&lt;/li&gt;
&lt;li&gt;Support me on &lt;a href="https://www.patreon.com/a11ywithlindsey"&gt;patreon&lt;/a&gt;! If you like my work, consider making a $1 monthly pledge. You’ll be able to vote on future blog posts if you make a \$5 pledge or higher! I also do a monthly Ask Me Anything Session for all Patrons!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pages.convertkit.com/4218bd5fb5/68dc4e412a"&gt;Be the first to learn about my posts&lt;/a&gt; for more accessibility funsies!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cheers! Have a great week!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>a11y</category>
    </item>
    <item>
      <title>Reducing Motion to Improve Accessibility</title>
      <dc:creator>Lindsey Kopacz</dc:creator>
      <pubDate>Tue, 20 Aug 2019 10:53:15 +0000</pubDate>
      <link>https://dev.to/lkopacz/reducing-motion-to-improve-accessibility-1c0i</link>
      <guid>https://dev.to/lkopacz/reducing-motion-to-improve-accessibility-1c0i</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://www.a11ywithlindsey.com/blog/reducing-motion-improve-accessibility" rel="noopener noreferrer"&gt;a11ywithlindsey.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hey friends! In this post, I am going to walk you through a newer media query (to me): &lt;code&gt;prefers-reduced-motion&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Quick confession: I know CSS fundamentals, but I am pretty behind on all the new stuff that has been coming out. Because my focus is usually on accessibility, I am focusing far more on HTML and JavaScript. When I focus on CSS, it's ensuring proper color contrast or custom focus states. Sometimes I use CSS to make &lt;a href="https://www.a11ywithlindsey.com/blog/create-custom-keyboard-accesible-checkboxes" rel="noopener noreferrer"&gt;checkboxes keyboard accessible&lt;/a&gt;. I always associated media queries with responsive design. I never thought of media queries as an accessibility enhancement.&lt;/p&gt;

&lt;p&gt;In this post, we are updating my blog by:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Adding the &lt;code&gt;prefers-reduced-motion&lt;/code&gt; query&lt;/li&gt;
&lt;li&gt;Adding a user-controlled setting for reducing motion.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Understanding &lt;code&gt;prefers-reduced-motion&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Animations, zooming, and panning can be problematic for people who have vestibular disorders. These disorders can cause motion sickness and vertigo. These are uncomfortable feelings that you don't want to deal with ever, let alone on a website. From what I understand, the &lt;a href="https://a11yproject.com/posts/understanding-vestibular-disorders/" rel="noopener noreferrer"&gt;vestibular system&lt;/a&gt; is in your inner ear and helps to control balance.&lt;/p&gt;

&lt;p&gt;According to &lt;a href="https://vestibular.org/understanding-vestibular-disorder" rel="noopener noreferrer"&gt;vestibular.org&lt;/a&gt;, up to 35% of adults aged 40 years or older in the United States have experienced some form of vestibular dysfunction. So this is not a small problem.&lt;/p&gt;

&lt;p&gt;My major takeaways from the web accessibility perspective:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Be careful with your animations.&lt;/li&gt;
&lt;li&gt;Be careful with your gifs.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;prefers-reduced-motion&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Allow a user to control reduce motion.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  How you do it
&lt;/h3&gt;

&lt;p&gt;Implementing the query is pretty simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-reduced-motion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* Reduced Motion Code */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a few places I have some animations for my links.&lt;/p&gt;

&lt;p&gt;First, there are my links where I have a border-bottom that moves down when you hover over it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/MY7TMjVSbUUITM2Brh/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/MY7TMjVSbUUITM2Brh/giphy.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then there is my call to action link that scales 1.1x larger when we hover over it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/XdIJqlqTIXZG3SyS3V/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/XdIJqlqTIXZG3SyS3V/giphy.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was talking to &lt;a href="https://twitter.com/andybelldesign/" rel="noopener noreferrer"&gt;Andy Bell&lt;/a&gt;, and he gave me &lt;a href="https://github.com/andybelldesign/stalfos/blob/feature/v2/src/utilities/_reset.scss#L71" rel="noopener noreferrer"&gt;some suggestions&lt;/a&gt; on implementation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-reduced-motion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;animation-play-state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;paused&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;scroll-behavior&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After implementing the changes, we have the hover effects, but none of the transitions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/W30RUUrYrc94jOvaau/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/W30RUUrYrc94jOvaau/giphy.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/fszlV41WjnJrjIpoVx/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/fszlV41WjnJrjIpoVx/giphy.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This strategy technically works well. However, I want to remove the hover effect altogether and keep the link as an underline. I may also play with the scale.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-reduced-motion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;animation-play-state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;paused&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;scroll-behavior&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;padding-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;underline&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that change, now all my links are just a simple underline.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzzypb4pbrjq137egweqc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzzypb4pbrjq137egweqc.png" alt="Screenshot of underlined text."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Without the transition animation, the call to action links are a bit jarring going from &lt;code&gt;scale(1)&lt;/code&gt; to &lt;code&gt;scale(1.1)&lt;/code&gt; on hover. So I changed it to &lt;code&gt;scale(1.05)&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-reduced-motion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;animation-play-state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;paused&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;scroll-behavior&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;padding-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;underline&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.blog__more-link&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.blog__more-link&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1.05&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.hero__cta&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.hero__cta&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1.05&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://i.giphy.com/media/jtjBSsS5KPvtCCNqYn/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/jtjBSsS5KPvtCCNqYn/giphy.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How to test on a mac
&lt;/h3&gt;

&lt;p&gt;This setting is primarily available on macOS.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to System Preferences&lt;/li&gt;
&lt;li&gt;Go to Accessibility&lt;/li&gt;
&lt;li&gt;Go to Display&lt;/li&gt;
&lt;li&gt;Check "Reduce Motion"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Easy Peasy! As soon as this post is published, you should be able to test this on my blog!&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a user controlled option to reduce motion
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://andy-bell.design/wrote/create-a-user-controlled-dark-or-light-mode/" rel="noopener noreferrer"&gt;Andy Bell's dark mode post&lt;/a&gt; inspired me to add the user-controlled option. We want to have the user's preferences take priority. We also want to account for people who don't have these settings available to them.&lt;/p&gt;

&lt;p&gt;Here's how we are going to do this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a checkbox with the label "reduce motion."&lt;/li&gt;
&lt;li&gt;Add a &lt;code&gt;checked&lt;/code&gt; state and a method to toggle that state in my Gatsby App.&lt;/li&gt;
&lt;li&gt;Use that state to control a &lt;code&gt;data-user-reduced-motion&lt;/code&gt; attribute.&lt;/li&gt;
&lt;li&gt;Apply the CSS using the above attribute.&lt;/li&gt;
&lt;li&gt;Store that in &lt;code&gt;localStorage&lt;/code&gt;, so we preserve the user settings.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Creating a &lt;code&gt;&amp;lt;ReduceToggle /&amp;gt;&lt;/code&gt; Component
&lt;/h3&gt;

&lt;p&gt;This component is an HTML checkbox with a label. As a disclaimer, I am using a &lt;code&gt;class&lt;/code&gt; component and not hooks. I still like writing classes sometimes, and it was easier for my thought process. Keep an eye out for a hook version!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReduceToggle&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"toggle"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"reduce-motion"&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"reduce-motion"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Reduce Motion&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ReduceToggle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only thing I've done here is to create a checkbox input with an &lt;a href="https://www.a11ywithlindsey.com/blog/introduction-accessible-labeling" rel="noopener noreferrer"&gt;associated form label&lt;/a&gt;. Something you may have noticed is that instead of for, React uses &lt;code&gt;htmlFor&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After that, I place it in my &lt;code&gt;&amp;lt;Header /&amp;gt;&lt;/code&gt; component above the menu. I'll worry about styling finesse later; I know it'll break my layout, and that's ok. We are only worried about functionality right now.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding in the states
&lt;/h3&gt;

&lt;p&gt;We want to go ahead and add a &lt;code&gt;checked&lt;/code&gt; state to our constructor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReduceToggle&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"toggle"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"reduce-motion"&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"reduce-motion"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Reduce Motion&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ReduceToggle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we are going to add that state to the checkbox itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReduceToggle&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;checked&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"toggle"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
          &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"reduce-motion"&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt;
          &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;checked&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"reduce-motion"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Reduce Motion&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ReduceToggle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we want to add a &lt;code&gt;toggleChecked&lt;/code&gt; method for the &lt;code&gt;onChange&lt;/code&gt; event.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReduceToggle&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;toggleChecked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;checked&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;checked&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"toggle"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
          &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"reduce-motion"&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt;
          &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;checked&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toggleChecked&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"reduce-motion"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Reduce Motion&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ReduceToggle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I always like to double-check that the state is working using &lt;a href="https://github.com/facebook/react-devtools" rel="noopener noreferrer"&gt;React Developer Tools&lt;/a&gt;. To do this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I inspect the element&lt;/li&gt;
&lt;li&gt;Go to the React Tab&lt;/li&gt;
&lt;li&gt;Find the &lt;code&gt;ReduceToggle&lt;/code&gt; component&lt;/li&gt;
&lt;li&gt;Ensure the state is working correctly!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/d83SPyGS9K9Pm6GQhw/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/d83SPyGS9K9Pm6GQhw/giphy.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we know the state is working. Let's toggle the &lt;code&gt;data-user-reduced-motion&lt;/code&gt; attribute value on the &lt;code&gt;documentElement&lt;/code&gt;. I'm going to add that in the &lt;code&gt;componentDidUpdate&lt;/code&gt; lifecycle method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReduceToggle&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;componentDidUpdate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;checked&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-user-reduced-motion&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-user-reduced-motion&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;toggleChecked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;checked&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;checked&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"toggle"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
          &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"reduce-motion"&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt;
          &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;checked&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toggleChecked&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"reduce-motion"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Reduce Motion&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ReduceToggle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://i.giphy.com/media/gIrdrOgahVAwaRsOW0/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/gIrdrOgahVAwaRsOW0/giphy.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding CSS to the &lt;code&gt;data-user-reduced-motion&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Word of warning. It's tempting to jump into the CSS and copy and paste all the things. I recommend doing this one step at a time. I made the mistake of trying to do it all at once and spent a lot more time debugging than I wanted to. So first let's go back to the goals of what we want.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We want user preference to rule over system preferences. We'll add the system preferences as a &lt;strong&gt;progressive enhancement&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Gatsby is a Static Site Generator, so if JavaScript doesn't load, most of my static site should load. However, if JavaScript doesn't load, we want to fallback on system preferences when the &lt;code&gt;data-user-reduced-motion&lt;/code&gt; attribute doesn't exist. So we are going to add a little bit to the query that we did in the first section about the media query itself. So we are using the &lt;code&gt;:not()&lt;/code&gt; CSS pseudo-class to do that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-reduced-motion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="py"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;not&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;data-user-reduced-motion&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;animation-play-state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;paused&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;scroll-behavior&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="py"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;not&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;data-user-reduced-motion&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;padding-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;underline&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.blog__more-link&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="py"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;not&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;data-user-reduced-motion&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;blog__more-link&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.blog__more-link&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="py"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;not&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;data-user-reduced-motion&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;blog__more-link&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;hover&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1.05&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.hero__cta&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="py"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;not&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;data-user-reduced-motion&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hero__cta&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.hero__cta&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="py"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;not&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;data-user-reduced-motion&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hero__cta&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;hover&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1.05&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we add the CSS &lt;strong&gt;outside&lt;/strong&gt; the query for if the &lt;code&gt;data-user-reduced-motion="true"&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-user-reduced-motion&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'true'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;animation-play-state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;paused&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;scroll-behavior&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;:root&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-user-reduced-motion&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'true'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;padding-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;underline&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;:root&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-user-reduced-motion&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'true'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nc"&gt;.blog__more-link&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12px&lt;/span&gt; &lt;span class="m"&gt;14px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;:root&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-user-reduced-motion&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'true'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nc"&gt;.blog__more-link&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1.05&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;:root&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-user-reduced-motion&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'true'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nc"&gt;.hero__cta__link&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12px&lt;/span&gt; &lt;span class="m"&gt;14px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;:root&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-user-reduced-motion&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'true'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nc"&gt;.hero__cta__link&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1.05&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To test, I did the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Turned off any reduce motion settings on macOS&lt;/li&gt;
&lt;li&gt;With the Reduce Toggle unchecked, ensure that all animations are still there.&lt;/li&gt;
&lt;li&gt;Check the Reduce Toggle Checkbox and see that all the CSS changes to reduce motion are working.&lt;/li&gt;
&lt;li&gt;In the element inspector, go to the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; document and find the &lt;code&gt;data-user-reduced-motion&lt;/code&gt;. Remove that attribute. Here we are simulating that that attribute never loaded.&lt;/li&gt;
&lt;li&gt;Go to the system preferences and check Reduce Motion. We should have the CSS changes for reduced motion!&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Adding &lt;code&gt;localStorage&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Now that we have that working, we want to start playing with &lt;code&gt;localStorage&lt;/code&gt;. We want to preserve the user's preferences for the future. Choosing your settings every time you visit isn't the best user experience. If you don’t know what &lt;code&gt;localStorage&lt;/code&gt; is, I would recommend pausing here and glancing over the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage" rel="noopener noreferrer"&gt;docs&lt;/a&gt;. If you like video examples, take a look at &lt;a href="https://www.youtube.com/watch?v=YL1F4dCUlLc" rel="noopener noreferrer"&gt;Wes Bos’s JS30 tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The first thing we are going to do is set the &lt;code&gt;localStorage&lt;/code&gt; on the &lt;code&gt;componentDidMount&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReduceToggle&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;componentDidMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;reduceMotionOn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reduceMotionOn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reduceMotionOn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// if we haven't been to the site before&lt;/span&gt;
    &lt;span class="c1"&gt;// this will return null&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// All other code stuff&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"toggle"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"reduce-motion"&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"reduce-motion"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Reduce Motion&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ReduceToggle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now what we want to do is create a default localStorage state for the user if the &lt;code&gt;reduceMotionOn&lt;/code&gt; is null. I'm going to set that to &lt;code&gt;false&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReduceToggle&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;componentDidMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;reduceMotionOn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reduceMotionOn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Just a way to get around localStorage being&lt;/span&gt;
    &lt;span class="c1"&gt;// stored as a string and not a bool&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;reduceMotionOn&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;reduceMotionOn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reduceMotionOn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reduceMotionOn&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reduceMotionOn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// All other code stuff&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"toggle"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"reduce-motion"&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"reduce-motion"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Reduce Motion&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ReduceToggle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last thing I am going to do upon mounting the component is set the state in the app. I want to ensure that my app's is the same as the &lt;code&gt;localStorage&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReduceToggle&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;componentDidMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;reduceMotionOn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reduceMotionOn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;reduceMotionOn&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;reduceMotionOn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reduceMotionOn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reduceMotionOn&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reduceMotionOn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;reduceMotionOn&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// All other code stuff&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"toggle"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"reduce-motion"&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"reduce-motion"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Reduce Motion&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ReduceToggle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go to Application &amp;gt; Local Storage in Chrome Dev Tools (Storage &amp;gt; Local Storage in Firefox). Then, clear the &lt;code&gt;reduceMotionOn&lt;/code&gt; storage. Upon refresh, you should see that the &lt;code&gt;reduceMotionOn&lt;/code&gt; is false. If you go to React Dev Tools and go to the &lt;code&gt;&amp;lt;ReduceToggle /&amp;gt;&lt;/code&gt; component, you’ll find that the checked state matches the reduceMotionOn localStorage item.&lt;/p&gt;

&lt;p&gt;That's not all! We have to toggle the localStorage in the &lt;code&gt;toggleChecked&lt;/code&gt; method in the React component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReduceToggle&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// All other code stuff&lt;/span&gt;

  &lt;span class="nx"&gt;toggleChecked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reduceMotionOn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;checked&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"toggle"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"reduce-motion"&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"reduce-motion"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Reduce Motion&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ReduceToggle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if I check Reduce motion and leave the site, my user-controlled preferences are preserved!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Thanks for joining me while I added a progressively enhanced accessibility feature to my blog! I hope you learned something along the way. Shout out to Andy for inspiring me to write this post!&lt;/p&gt;

&lt;p&gt;These are the key takeaways from this post, regardless of the framework that you use:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Be careful with what you animate and provide options for those who have vestibular disorders.&lt;/li&gt;
&lt;li&gt;User-controlled &amp;gt; System Preferences&lt;/li&gt;
&lt;li&gt;Have system preferences for progressive enhancements&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;localStorage&lt;/code&gt; to your benefit so that the user settings are preserved!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you'd like to play around with this, I've made a CodeSandbox for you!&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/laughing-sutherland-76xj6"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Stay in touch! If you liked this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let me know on &lt;a href="https://twitter.com/LittleKope" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and share this article with your friends! Also, feel free to tweet me any follow up questions or thoughts.&lt;/li&gt;
&lt;li&gt;Support me on &lt;a href="https://www.patreon.com/a11ywithlindsey" rel="noopener noreferrer"&gt;patreon&lt;/a&gt;! If you like my work, consider making a $1 monthly pledge. You’ll be able to vote on future blog posts if you make a \$5 pledge or higher! I also do a monthly Ask Me Anything Session for all Patrons!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pages.convertkit.com/4218bd5fb5/68dc4e412a" rel="noopener noreferrer"&gt;Be the first to learn about my posts&lt;/a&gt; for more accessibility funsies!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cheers! Have a great week!&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>css</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Create custom keyboard accessible radio buttons</title>
      <dc:creator>Lindsey Kopacz</dc:creator>
      <pubDate>Mon, 05 Aug 2019 19:40:10 +0000</pubDate>
      <link>https://dev.to/lkopacz/create-custom-keyboard-accessible-radio-buttons-22eh</link>
      <guid>https://dev.to/lkopacz/create-custom-keyboard-accessible-radio-buttons-22eh</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://www.a11ywithlindsey.com/blog/create-custom-keyboard-accessible-radio-buttons" rel="noopener noreferrer"&gt;a11ywithlindsey.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hey friends! Today we'll be creating custom keyboard accessible radio buttons! This blog post is a follow-up post from &lt;a href="https://www.a11ywithlindsey.com/blog/create-custom-keyboard-accesible-checkboxes" rel="noopener noreferrer"&gt;my accessible checkboxes post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We'll go over:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The markup&lt;/li&gt;
&lt;li&gt;Creating a pseudo-element on the label in CSS&lt;/li&gt;
&lt;li&gt;Add "selected" styling in CSS&lt;/li&gt;
&lt;li&gt;Add focus styling&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Starting out
&lt;/h2&gt;

&lt;p&gt;I decided to create a simple group of radio buttons asking what your favorite animal is&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;fieldset&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;legend&amp;gt;&lt;/span&gt;What is your favorite Wild Animal?&lt;span class="nt"&gt;&amp;lt;/legend&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"radio-wrapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"animal"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"elephant"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"elephant"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Elephant&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"radio-wrapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"animal"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"monkey"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"monkey"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Monkey&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"radio-wrapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"animal"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"cheetah"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"cheetah"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Cheetah&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"radio-wrapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"animal"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"giraffe"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"giraffe"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Giraffe&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/fieldset&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;fieldset&lt;/code&gt; groups all the radio buttons together logically. The radios inputs are all options to the question in the &lt;code&gt;legend&lt;/code&gt;. Also, remember to associate those form labels with the radio buttons!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fuuwpu368vuu876tdhulq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fuuwpu368vuu876tdhulq.png" alt="A Fieldset with the question 'What is your favorite Wild Animal?' with four options: Elephant, Monkey, Cheetah, Giraffe."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm going to add some straightforward CSS to clean it up a bit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="sx"&gt;url('https://fonts.googleapis.com/css?family=Roboto&amp;amp;display=swap')&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Roboto'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;fieldset&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I didn’t do anything much here; I added a font and took away the border from the &lt;code&gt;fieldset&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fz8nqescfb1mkwase27n6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fz8nqescfb1mkwase27n6.png" alt="The fieldset with a sans serif font and no outline on the fieldset"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's get to the fun part! Styling these radio buttons!&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a pseudo-element on the label
&lt;/h2&gt;

&lt;p&gt;First thing I am going to do is add a &lt;code&gt;::before&lt;/code&gt; pseudo-element on the &lt;code&gt;label&lt;/code&gt; element. I'm going to start with something basic first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nv"&gt;$muted-red&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#db3846&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'radio'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* This will be adjusted */&lt;/span&gt;

    &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-22px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* This will be adjusted */&lt;/span&gt;
      &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$muted-red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The radio buttons won't look like anything much right now. We only want to see the radio buttons to ensure we are replicating the HTML functionality.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Faov9cx78mznxtddkhr4x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Faov9cx78mznxtddkhr4x.png" alt="Radio buttons with a red box between the label and the button."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm going to add a teensy amount of margin on the &lt;code&gt;.radio-wrapper&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;$muted-red: #db3846;
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gi"&gt;+ .radio-wrapper {
+ margin: 0.5rem 0;
+ }
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;input[type='radio'] {
&lt;/span&gt;  + label {
    position: relative;
    cursor: pointer;
    margin-left: 20px; /* This will be adjusted */
&lt;span class="err"&gt;
&lt;/span&gt;    &amp;amp;::before {
      content: '';
      position: absolute;
      left: -24px; /* This will be adjusted */
      width: 18px;
      height: 18px;
      background: $muted-red;
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fdixzy83mlspcdju5kdy6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fdixzy83mlspcdju5kdy6.png" alt="Radio buttons with a red box between the label and the button, with extra space below each field."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's remove that background color and round out the edges.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;input[type='radio'] {
&lt;/span&gt;  + label {
    position: relative;
    cursor: pointer;
    margin-left: 20px; /* This will be adjusted */
&lt;span class="err"&gt;
&lt;/span&gt;    &amp;amp;::before {
      content: '';
      position: absolute;
      left: -24px; /* This will be adjusted */
&lt;span class="gi"&gt;+     border-radius: 50%;
+     border: 1px solid #6f686a;
&lt;/span&gt;      width: 18px;
      height: 18px;
&lt;span class="gi"&gt;+     background: transparent;
&lt;/span&gt;    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a note, I am going to leave the standard radio buttons for debugging purposes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fn3b1i0r48fmtm5gp8ni4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fn3b1i0r48fmtm5gp8ni4.png" alt="Radio buttons with a large circle between the labels."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Add &lt;code&gt;:checked&lt;/code&gt; styling in CSS
&lt;/h2&gt;

&lt;p&gt;If you've read my post on &lt;a href="https://www.a11ywithlindsey.com/blog/create-custom-keyboard-accesible-checkboxes" rel="noopener noreferrer"&gt;keyboard accessible checkboxes&lt;/a&gt; you know about the &lt;code&gt;:checked&lt;/code&gt; pseudo-class. First, we need to put add an &lt;code&gt;::after&lt;/code&gt; pseudo-element on the label.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;input[type='radio'] {
&lt;/span&gt;  + label {
    position: relative;
    cursor: pointer;
    margin-left: 20px; /* This will be adjusted */
&lt;span class="err"&gt;
&lt;/span&gt;    &amp;amp;::before {
      content: '';
      position: absolute;
      left: -24px; /* This will be adjusted */
      border-radius: 50%;
      border: 1px solid #6f686a;
      width: 18px;
      height: 18px;
      background: transparent;
    }
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gi"&gt;+   &amp;amp;::after {
+     content: '';
+     position: absolute;
+     left: -20px;
+     top: 4px;
+     border-radius: 50%;
+     width: 12px;
+     height: 12px;
+     background: $muted-red;
+   }
&lt;/span&gt;  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, this is what that looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fqmmubk8irp7jw2upgoz6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fqmmubk8irp7jw2upgoz6.png" alt="Radio buttons with an outlined red circle between the labels."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we have the styling in place. Let's only add the &lt;code&gt;background&lt;/code&gt; of the &lt;code&gt;::after&lt;/code&gt; pseudo-element when the radio input is &lt;code&gt;:checked&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;input[type='radio'] {
&lt;/span&gt;  + label {
    &amp;amp;::after {
      content: '';
      position: absolute;
      left: -20px;
      top: 4px;
      border-radius: 50%;
      width: 12px;
      height: 12px;
    }
  }
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gi"&gt;+ &amp;amp;:checked {
+   + label::after {
+     background: $muted-red;
+   }
+ }
&lt;/span&gt;}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now if I select a radio button, it'll have a background color!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9877l0h9wgsp1lgzbrt5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9877l0h9wgsp1lgzbrt5.png" alt="A selected radio button with an outlined red circle, indicating it is selected."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you notice, though, there is no focus styling. Let's focus on that next (see what I did there)&lt;/p&gt;

&lt;h2&gt;
  
  
  Add focus styling
&lt;/h2&gt;

&lt;p&gt;If I were to hide the radio button, you would have no idea if I focused on it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F3kumy7cckffepf4m7uer.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F3kumy7cckffepf4m7uer.png" alt="A focused radio button with an outlined circle."&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'radio'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;:focus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;+ &lt;/span&gt;&lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt; &lt;span class="nv"&gt;$muted-red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I decided to add a similar muted red for the focus styling.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1uzppohknmlmykut8adz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1uzppohknmlmykut8adz.png" alt="A focused radio button with an outlined red circle."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To finish up, I will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;remove the &lt;code&gt;opacity&lt;/code&gt; from the radio button itself (the input)&lt;/li&gt;
&lt;li&gt;remove the &lt;code&gt;margin-left&lt;/code&gt; from the label!
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'radio'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And Voilà!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/RgzwLbAOB4W4aSUkog/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/RgzwLbAOB4W4aSUkog/giphy.gif" alt="Gif going through custom radio buttons."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;When we make custom radio buttons, we have to make sure we account for the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creating proper HTML structure with associated form labels!&lt;/li&gt;
&lt;li&gt;Using pseudo-elements to create the custom-styled element&lt;/li&gt;
&lt;li&gt;Accounting for the &lt;code&gt;:checked&lt;/code&gt; pseudo-class&lt;/li&gt;
&lt;li&gt;Ensuring you can focus on the new radio button&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;opacity: 0&lt;/code&gt; to hide the radio button&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you want to play around with it, here is the finished CodePen!&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/littlekope0903/embed/jjgRPL/?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Stay in touch! If you liked this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let me know on &lt;a href="https://twitter.com/LittleKope" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and share this article with your friends! Also, feel free to tweet me any follow up questions or thoughts.&lt;/li&gt;
&lt;li&gt;Support me on &lt;a href="https://www.patreon.com/a11ywithlindsey" rel="noopener noreferrer"&gt;patreon&lt;/a&gt;! If you like my work, consider making a $1 monthly pledge. You’ll be able to vote on future blog posts if you make a \$5 pledge or higher! I also do a monthly Ask Me Anything Session for all Patrons!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pages.convertkit.com/4218bd5fb5/68dc4e412a" rel="noopener noreferrer"&gt;Be the first to learn about my posts&lt;/a&gt; for more accessibility funsies!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cheers! Have a great week!&lt;/p&gt;

</description>
      <category>html</category>
      <category>css</category>
      <category>a11y</category>
    </item>
    <item>
      <title>A11y Lessons I Learned when Starting a Podcast</title>
      <dc:creator>Lindsey Kopacz</dc:creator>
      <pubDate>Tue, 23 Jul 2019 14:35:20 +0000</pubDate>
      <link>https://dev.to/lkopacz/a11y-lessons-i-learned-when-starting-a-podcast-3l82</link>
      <guid>https://dev.to/lkopacz/a11y-lessons-i-learned-when-starting-a-podcast-3l82</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://www.a11ywithlindsey.com/blog/a11y-lessons-learned-starting-podcast" rel="noopener noreferrer"&gt;a11ywithlindsey.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you haven’t noticed, I haven’t been around! It’s been a month since I posted, and there’s been a good reason for that. Kelly Vaughn, Ali Spittel, Emma Wedekind, and I started &lt;a href="https://ladybug.dev/" rel="noopener noreferrer"&gt;the LadyBug Podcast&lt;/a&gt;. This podcast came to fruition with much labor. As a result, I’ve been figuring out how to balance this blog with that side project! Don’t worry, though, this isn’t going away. My blog is my passion project!&lt;/p&gt;

&lt;p&gt;Now that you know where I’ve been, I’ve learned a lot about podcasting and how it intersects with accessibility. I knew some of these things at a high level, but in this post, we’re going to get a little bit more in-depth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Transcripts are a MUST
&lt;/h2&gt;

&lt;p&gt;When we started planning this podcast, it was no doubt we wanted to have transcripts. Transcripts can be time and financially expensive, and many people see them as a “nice to have.” However, I’m here to tell you that they are a must-have.&lt;/p&gt;

&lt;p&gt;Transcripts have a ton of benefits:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Deaf and hard of hearing folks can access your excellent content.&lt;/li&gt;
&lt;li&gt;Some people prefer reading than listening. I cannot tell you how many abled folks have told me they appreciated having transcripts.&lt;/li&gt;
&lt;li&gt;It helps those whose first language may not be English.&lt;/li&gt;
&lt;li&gt;If people are reading your transcripts, this means they are spending a ton of time on your site. Session duration improves SEO.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Being a content creator means that you try to make your content available to as many people as possible. You don't want to alienate a potential audience member because you decided to ignore their needs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We went through a few attempts to get transcripts. I wanted to share the options we tried and the pros and cons of each option.&lt;/p&gt;

&lt;h3&gt;
  
  
  Having someone do it for you
&lt;/h3&gt;

&lt;p&gt;Hiring someone was the first thing we tried because it was the only option we knew. We didn’t have time to go through our entire audio and write it out. So we decided to hire someone who did that for us. We used Fiverr, which I had never tried before. Hiring someone has pros and cons, however.&lt;/p&gt;

&lt;p&gt;Pros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Paying a real person and supporting someone else.&lt;/li&gt;
&lt;li&gt;Catches errors in real-time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expensive&lt;/li&gt;
&lt;li&gt;Because they are a human, it takes a few days to get them back, which isn’t ideal for a quick turn around.&lt;/li&gt;
&lt;li&gt;Language differences.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Using Artificial Intelligence
&lt;/h3&gt;

&lt;p&gt;The other option is to use AI software to parse through your audio and provide a transcript for you. We tried &lt;a href="https://app.trint.com" rel="noopener noreferrer"&gt;Trint&lt;/a&gt; and &lt;a href="https://otter.ai" rel="noopener noreferrer"&gt;Otter AI&lt;/a&gt;, which are both great tools. AI also has some pros and cons.&lt;/p&gt;

&lt;p&gt;Pros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get your transcript back in minutes or hours. Otter AI took about 10 minutes.&lt;/li&gt;
&lt;li&gt;Cheaper&lt;/li&gt;
&lt;li&gt;Gets better as they learn your speakers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Especially at first, you have to edit it. We didn't want to have random words in there, so we took some time to listen to the tool as it read the transcript to us.&lt;/li&gt;
&lt;li&gt;I feel a little guilty when I use Machine Learning to replace a job that a person could do.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What we ended up doing
&lt;/h3&gt;

&lt;p&gt;Because of the quick turn around we needed, we ended up going with AI. We got a deal with OtterAI and ended up using that one. Do what works best for you in the end, all options are great ones!&lt;/p&gt;

&lt;h2&gt;
  
  
  A11y Considerations for Custom Podcast Players
&lt;/h2&gt;

&lt;p&gt;As you may or may not know, we used &lt;a href="http://gatsbyjs.org" rel="noopener noreferrer"&gt;GatsbyJS&lt;/a&gt; to build out the LadyBug Podcast site. I took responsibility for making an accessible podcast player. I learned so much about how to use React to create all the audioElement events. Shout out to &lt;a href="https://syntax.fm/" rel="noopener noreferrer"&gt;Syntax.fm&lt;/a&gt; for having a player that I could explore. The first thing I did was add a &lt;code&gt;ref&lt;/code&gt; to an &lt;code&gt;&amp;lt;audio&amp;gt;&lt;/code&gt; element.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Player&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;show&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;audio&lt;/span&gt;
        &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;audio&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;audio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;show&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;audio&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I go into the code and add a &lt;code&gt;console.log&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Player&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;show&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;audio&lt;/span&gt;
        &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;audio&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;audio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;show&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;audio&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives me the ability to access all the methods of the audio. I can use them on my custom player in the form of buttons, radio buttons, and a slider.&lt;/p&gt;

&lt;p&gt;In the podcast player, I used the following methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/currentTime" rel="noopener noreferrer"&gt;HTMLMediaElement.currentTime&lt;/a&gt; - This tells you current time in the audio, in seconds.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/playbackRate" rel="noopener noreferrer"&gt;HTMLMediaElement.playbackRate&lt;/a&gt; - This tells you the speed at which you are playing. We can set this property when we press a button to increase the speed!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/volume" rel="noopener noreferrer"&gt;HTMLMediaElement.volume&lt;/a&gt; - This tells you the current volume level.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/play" rel="noopener noreferrer"&gt;HTMLMediaElement.play()&lt;/a&gt; - This plays the audio.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/pause" rel="noopener noreferrer"&gt;HTMLMediaElement.pause()&lt;/a&gt; - This pauses the audio.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/duration" rel="noopener noreferrer"&gt;HTMLMediaElement.duration&lt;/a&gt; - This tells you the total length of the audio, in seconds.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you add the &lt;code&gt;ref&lt;/code&gt; to the audio, you can use &lt;code&gt;this.audio&lt;/code&gt; to control anything with the audio. You can append the method or property name to &lt;code&gt;this.audio&lt;/code&gt;. It’s neat! You can use that as well to control React state 🤯! I won’t be going too much into all the states in this blog post. I recommend you check out &lt;a href="https://github.com/ladybug-podcast/ladybugpodcast/blob/master/src/components/player.js" rel="noopener noreferrer"&gt;our source code&lt;/a&gt; as well as the &lt;a href="https://github.com/wesbos/Syntax/blob/master/components/Player.js" rel="noopener noreferrer"&gt;Syntax.fm source code&lt;/a&gt; if you want to learn more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Button Labelling
&lt;/h3&gt;

&lt;p&gt;Button labels are the most critical part of the player being accessible. Remember, we are “hacking” the audio player. We must ensure screen reader, keyboard, and mouse users can access the player. The latter is what abled folks center on, so if you’re doing this, I want to make sure you account for all experiences.&lt;/p&gt;

&lt;p&gt;I used the &lt;code&gt;react-icons/fa&lt;/code&gt; package to get the icons for our player. We used &lt;code&gt;FaPlay&lt;/code&gt;, &lt;code&gt;FaPause&lt;/code&gt;, &lt;code&gt;FaUndo&lt;/code&gt;, and &lt;code&gt;FaRedo&lt;/code&gt; for the play, pause, rewind 15 seconds, and fast-forward 15 seconds buttons. These icons are SVG icons, but I wanted to make sure there was text in the markup. To do this, we ensured the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We used the semantic &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; instead of a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; to support keyboard events. Read my &lt;a href="https://www.a11ywithlindsey.com/blog/3-simple-tips-improve-keyboard-accessibility" rel="noopener noreferrer"&gt;3 Simple Tips to Improve Keyboard Accessibility&lt;/a&gt; post for more information.&lt;/li&gt;
&lt;li&gt;We ensured not to use icon fonts, which was already taken care of us through the &lt;code&gt;react-icons&lt;/code&gt; library.&lt;/li&gt;
&lt;li&gt;We ensured there was &lt;strong&gt;actual text&lt;/strong&gt; inside the buttons, which SVG doesn't do for us. We can visually hide that text using CSS, but it still must be there.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"player__icon"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;svg&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!--paths and things--&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sr-only"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;play&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating a slider
&lt;/h3&gt;

&lt;p&gt;I was searching around for an accessible player that shows the slider. I found the &lt;a href="https://ableplayer.github.io/ableplayer/demos/" rel="noopener noreferrer"&gt;Able Player&lt;/a&gt; and started observing how they did things. Making this accessible was one of the hardest things I’ve done, and it’s still rather buggy. The code ended up being many divs with aria labels and lots of event handling. The side project conundrum is that done is better than perfect. Looking back, I wish I had made it a slider using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/range" rel="noopener noreferrer"&gt;the range input&lt;/a&gt;. Lessons learned - stay tuned for a future blog post when I update that slider!&lt;/p&gt;

&lt;p&gt;For now, I'll go through my thought process of what I wanted to do with the slider. Below is the source code........&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
  &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"player__progress"&lt;/span&gt;
  &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrub&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;progress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"player__progress-loaded"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
    &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"player__progress-played"&lt;/span&gt;
    &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${(&lt;/span&gt;&lt;span class="nx"&gt;currentTime&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.015&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%`&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
    &lt;span class="na"&gt;orientation&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"horizontal"&lt;/span&gt;
    &lt;span class="na"&gt;onKeyDown&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;moveSlider&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;tabIndex&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
    &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"player__slider"&lt;/span&gt;
    &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"slider"&lt;/span&gt;
    &lt;span class="na"&gt;aria-label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"audio timeline"&lt;/span&gt;
    &lt;span class="na"&gt;aria-valuemin&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
    &lt;span class="na"&gt;aria-valuemax&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;aria-valuetext&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;renderValueText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;aria-valuenow&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;renderValueNow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${(&lt;/span&gt;&lt;span class="nx"&gt;currentTime&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%`&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have 3 children divs of the player: &lt;code&gt;.player__progress-loaded&lt;/code&gt;, &lt;code&gt;.player__progress-played&lt;/code&gt;, and &lt;code&gt;.player__slider&lt;/code&gt;. Let's look at what these correspond to:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.a11ywithlindsey.com%2Fstatic%2Fannotated-player-screenshot-3eb0883f8dcab597e51001e7657e8597-846dd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.a11ywithlindsey.com%2Fstatic%2Fannotated-player-screenshot-3eb0883f8dcab597e51001e7657e8597-846dd.png" alt="Custom audio player: played portion is the color red and slider is a white circle."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.player__progress-loaded&lt;/code&gt; corresponds to the width of the entire slider. This div has no semantic value to a screen reader user.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.player__progress-played&lt;/code&gt; is the visual representation of the total amount played.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.player__slider&lt;/code&gt; is the most important element for accessibility. It tells the screen reader user what time it currently is, and allows us to move it with our keyboard.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now let's take a look at some of the events and style here.&lt;/p&gt;

&lt;p&gt;For the &lt;code&gt;onClick&lt;/code&gt; event, we want to ensure that we change the &lt;code&gt;currentTime&lt;/code&gt; in the audio to be wherever we clicked. If you can, look at &lt;a href="https://github.com/ladybug-podcast/ladybugpodcast/blob/master/src/components/player.js#L125" rel="noopener noreferrer"&gt;the code&lt;/a&gt; yourself, fork it, and console log all the things to see what’s happening. If you click anywhere on the &lt;code&gt;.player__progress&lt;/code&gt; div, you’ll change the &lt;code&gt;currentTime&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For the &lt;code&gt;.player__progress-played&lt;/code&gt; div, we have the styling. The component's width is the percentage of the way through the episode.&lt;/p&gt;

&lt;p&gt;Now for the slider itself and then a couple of &lt;a href="https://github.com/ladybug-podcast/ladybugpodcast/blob/master/src/utils/util.js" rel="noopener noreferrer"&gt;helper functions&lt;/a&gt;, one of which I adapted from Syntax's site.&lt;/p&gt;

&lt;p&gt;Holy batman that's a lot of ARIA attributes! Let's dissect this for a second:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;role="slider"&lt;/code&gt; - This tells the screen reader user that un-semantic div has some meaning!&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;aria-valuetext&lt;/code&gt; - This is the human-readable version of the value of the slider. For example, in the screenshot above - it was "5 minutes, 51 seconds"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;aria-valuenow&lt;/code&gt; - defines the current value for a range widget (which the slider is)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;aria-valuemin&lt;/code&gt; - a required attribute that defines the minimum value for a range widget&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;aria-valuemax&lt;/code&gt; - a required attribute that defines the maximum value for a range widget&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Below is how VoiceOver on macOS reads the slider:&lt;/p&gt;

&lt;p&gt;"5 minutes, 51 seconds, audio timeline, slider". So the &lt;code&gt;aria-valuetext&lt;/code&gt;, the &lt;code&gt;aria-label&lt;/code&gt; and then the &lt;code&gt;role&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;this.moveSlider&lt;/code&gt;, if you press a Left or Right arrow and respectively rewinds or fast-forwards 5 seconds. Take a look at &lt;a href="https://github.com/ladybug-podcast/ladybugpodcast/blob/e0cfce0159d1f516812465fbeafaaf5ecd47ef5a/src/components/player.js#L137" rel="noopener noreferrer"&gt;the source code&lt;/a&gt; to see how we did that.&lt;/p&gt;

&lt;h3&gt;
  
  
  How I want to redo the slider
&lt;/h3&gt;

&lt;p&gt;As stated before, this was a little buggy. A few things that are buggy:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Browser support (I got a comment from a listener, but haven't checked it out yet)&lt;/li&gt;
&lt;li&gt;I couldn’t figure out dragging the slider with your mouse.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, for whatever reason, I assumed (don't assume folks, it's dangerous) that you could not custom style a range input.&lt;/p&gt;

&lt;p&gt;I was wrong. You totally can.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Starting a podcast has been a very positive experience all around. I’m sure we’ll talk about the more general lessons we learned starting a podcast on the Ladybug podcast!&lt;/p&gt;

&lt;p&gt;Two key takeaways from this post:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Always have transcripts. It's worth the time and financial cost to include others. It is not an edge case.&lt;/li&gt;
&lt;li&gt;Hack the audio player with caution and ensure that you over-test.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you're interested in the LadyBug Podcast, be sure to &lt;a href="https://link.chtbl.com/ladybugpodcast" rel="noopener noreferrer"&gt;subscribe&lt;/a&gt; to have them downloaded!&lt;/p&gt;

&lt;p&gt;Stay in touch! If you liked this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let me know on &lt;a href="https://twitter.com/LittleKope" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and share this article with your friends! Also, feel free to tweet me any follow up questions or thoughts.&lt;/li&gt;
&lt;li&gt;Support me on &lt;a href="https://www.patreon.com/a11ywithlindsey" rel="noopener noreferrer"&gt;patreon&lt;/a&gt;! If you like my work, consider making a $1 monthly pledge. You’ll be able to vote on future blog posts if you make a \$5 pledge or higher! I also do a monthly Ask Me Anything Session for all Patrons!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pages.convertkit.com/4218bd5fb5/68dc4e412a" rel="noopener noreferrer"&gt;Be the first to learn about my posts&lt;/a&gt; for more accessibility funsies!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cheers! Have a great week!&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>podcast</category>
      <category>showdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>An Introduction to Accessible Labeling</title>
      <dc:creator>Lindsey Kopacz</dc:creator>
      <pubDate>Mon, 24 Jun 2019 14:33:16 +0000</pubDate>
      <link>https://dev.to/lkopacz/an-introduction-to-accessible-labeling-18lo</link>
      <guid>https://dev.to/lkopacz/an-introduction-to-accessible-labeling-18lo</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://www.a11ywithlindsey.com/blog/introduction-accessible-labeling"&gt;a11ywithlindsey.com&lt;/a&gt;. If you'd like to see video examples of how screen readers interpret these, they are at the source!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Last week, I got a decent amount of folks who found the &lt;a href="https://www.a11ywithlindsey.com/blog/introduction-aria-states"&gt;aria states blog post&lt;/a&gt; helpful. This week I wanted to continue with that and go over something that took me a long time to understand: labeling. How do you label things? What needs labeling? What is the difference between all the ways to label things?&lt;/p&gt;

&lt;p&gt;After this post, you should have a firmer understanding of all things labels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Form Labels
&lt;/h2&gt;

&lt;p&gt;Lack of form labels is one of the most common places I see accessibility errors. Most people do something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"search"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Search"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I’m going to repeat it for those in the back:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Placeholder attributes are &lt;strong&gt;not&lt;/strong&gt; enough to label a field for a screen reader.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To properly label this, we need to ensure that there is a &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; that exists and is also &lt;strong&gt;associated&lt;/strong&gt; with the input. The way to associate it is to give the &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; element an &lt;code&gt;id&lt;/code&gt; and to match that value to a &lt;code&gt;for&lt;/code&gt; attribute on the label.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"search"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Search&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"search"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Search"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"search"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Take note that the string in the &lt;code&gt;for&lt;/code&gt; attribute matches the &lt;code&gt;id&lt;/code&gt; in the input. Matching these strings is how you associate them!&lt;/p&gt;

&lt;p&gt;If a designer gives you a mock and there is absolutely no way to tell them to add a label to the design, you’re in luck. You can add a &lt;code&gt;visually-hidden&lt;/code&gt; or &lt;code&gt;sr-only&lt;/code&gt; (screen reader only) class. I always use this CSS from &lt;a href="https://a11yproject.com/posts/how-to-hide-content/"&gt;the a11y project&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.visually-hidden&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c"&gt;/* IE6, IE7 */&lt;/span&gt;
  &lt;span class="nl"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above code would turn into this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"visually-hidden"&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"search"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Search&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"search"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Search"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"search"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Pretty simple, this applies to &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; elements as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nesting inputs in labels
&lt;/h3&gt;

&lt;p&gt;I’ve also seen people nest their inputs. Nested inputs aren’t my preferred method, but if I do something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;
    Search:
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"search"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This HTML is valid and doesn’t produce any errors with the Wave tool. However, it makes it more difficult to visually hide the label, if that’s what you need to do. So choose your method based on your needs!&lt;/p&gt;

&lt;h2&gt;
  
  
  Using &lt;code&gt;aria-label&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;As a disclaimer, this is my least favorite way to label things for screen readers. I prefer to label things with elements that exist in the markup. However, sometimes, it is necessary. A few times that I’ve found it necessary:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I had no control of the markup and had to change up the DOM in JavaScript. It’s way easier to &lt;code&gt;setAttribute()&lt;/code&gt; than it is to create an entire element and append it.&lt;/li&gt;
&lt;li&gt;I was working in an SVG that I couldn’t add &lt;code&gt;&amp;lt;text&amp;gt;&lt;/code&gt; elements to&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The way you use an &lt;code&gt;aria-label&lt;/code&gt; is to put the string in the attribute. For example, I found this on the MDN site:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt;
  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"icon icon-github"&lt;/span&gt;
  &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt;
  &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"24"&lt;/span&gt;
  &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"28"&lt;/span&gt;
  &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 0 24 28"&lt;/span&gt;
  &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"GitHub"&lt;/span&gt;
  &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"img"&lt;/span&gt;
  &lt;span class="na"&gt;focusable=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- all the children --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The aria-label attribute value does not need to match the &lt;code&gt;id&lt;/code&gt; of another element.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;aria-describedby&lt;/code&gt; and &lt;code&gt;aria-labelledby&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;aria-describedby&lt;/code&gt; and &lt;code&gt;aria-labelledby&lt;/code&gt; took awhile to demystify because the two attributes sound like they are the same. So let’s break them down into the literal sense.&lt;/p&gt;

&lt;p&gt;Labels are like titles. They tell you what something is. When do we announce a title or a label: before the element.&lt;/p&gt;

&lt;p&gt;Let’s take the third example from the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-labelledby_attribute"&gt;MDN docs&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"radio_label"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;My radio label&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"radiogroup"&lt;/span&gt; &lt;span class="na"&gt;aria-labelledby=&lt;/span&gt;&lt;span class="s"&gt;"radio_label"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item #1&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item #2&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item #3&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When we use VoiceOver to navigate to the radio group, it reads “My radio label, radio group?” The radio label got announced &lt;strong&gt;before&lt;/strong&gt; it told us about the radio group.&lt;/p&gt;

&lt;p&gt;Let’s take the same markup from above and add an &lt;code&gt;aria-describedby&lt;/code&gt; attribute with a div.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"radio_label"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;My radio label&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt;
  &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"radiogroup"&lt;/span&gt;
  &lt;span class="na"&gt;aria-labelledby=&lt;/span&gt;&lt;span class="s"&gt;"radio_label"&lt;/span&gt;
  &lt;span class="na"&gt;aria-describedby=&lt;/span&gt;&lt;span class="s"&gt;"radio_desc"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item #1&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item #2&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item #3&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"radio_desc"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  A bit more about this radio group. Here are some words.
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The text “A bit more about this radio group. Here are some words” happens after VoiceOver announced after the radio group. It’s a very subtle difference where, in most cases, it won’t matter.&lt;/p&gt;

&lt;p&gt;The strings that we put in these attributes are like the form labels above. We want the &lt;code&gt;aria-describedby&lt;/code&gt; or &lt;code&gt;aria-labelledby&lt;/code&gt; attribute to match the &lt;code&gt;id&lt;/code&gt; of the element that we want the screen reader to read.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope I helped you understand a bit more about the confusing world of labeling for accessibility! Let me know on &lt;a href="https://twitter.com/LittleKope"&gt;Twitter&lt;/a&gt; or comment below what you thought or if you have any other questions.&lt;/p&gt;

&lt;p&gt;Also, I have a &lt;a href="https://www.patreon.com/a11ywithlindsey"&gt;patreon&lt;/a&gt;! If you like my work, consider making a $1 monthly pledge. You’ll be able to vote on future blog posts if you make a \$5 pledge or higher! Cheers! Have a great week!&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>aria</category>
      <category>frontend</category>
    </item>
    <item>
      <title>An Introduction to ARIA States</title>
      <dc:creator>Lindsey Kopacz</dc:creator>
      <pubDate>Mon, 10 Jun 2019 13:40:35 +0000</pubDate>
      <link>https://dev.to/lkopacz/an-introduction-to-aria-states-30nm</link>
      <guid>https://dev.to/lkopacz/an-introduction-to-aria-states-30nm</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://www.a11ywithlindsey.com/blog/introduction-aria-states" rel="noopener noreferrer"&gt;a11ywithlindsey.com&lt;/a&gt;. If you'd like to see video examples of how screen readers interpret these, they are at the source!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hey friends! Today’s blog post comes to you from my &lt;a href="https://www.patreon.com/a11ywithlindsey" rel="noopener noreferrer"&gt;Patreon folks'&lt;/a&gt; poll. It’s a follow up from one of my previous posts about &lt;a href="https://www.a11ywithlindsey.com/blog/beginning-demystify-aria" rel="noopener noreferrer"&gt;Demystifying ARIA&lt;/a&gt;. ARIA can be utterly mysterious and daunting, but it’s handy. One of my favorite ways to use it is to communicate state to screen readers.&lt;/p&gt;

&lt;p&gt;I’m seeing a positive trend in the a11y community. Instead of using classes to style elements, a11y folks are styling by using ARIA attributes in the CSS. This helps enforce accessibility standards and prevent people from cheating accessibility. The attributes I’ll be going over today are &lt;code&gt;aria-expanded&lt;/code&gt;, &lt;code&gt;hidden&lt;/code&gt;, &lt;code&gt;aria-hidden&lt;/code&gt;, and &lt;code&gt;aria-current&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;aria-expanded&lt;/code&gt; attribute
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;aria-expanded&lt;/code&gt; is one of the few aria attributes that does not have an HTML5 equivalent. Please tweet me if I am wrong, but at the time of writing, I believe this to be correct. In the &lt;a href="https://www.a11ywithlindsey.com/blog/javascript-accessibility-accordions" rel="noopener noreferrer"&gt;Accessible Accordion post&lt;/a&gt;, I used &lt;code&gt;aria-expanded&lt;/code&gt; to convey the section’s state.&lt;/p&gt;

&lt;p&gt;Why is this helpful? Let’s take the accordion example that I went through in the blog post that I linked in the previous paragraph:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/littlekope0903/embed/OYqNOd/?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: I changed the code in the above sample to have the CSS tied more to the attributes and less to CSS classes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you go through this on a screen reader, you’ll get something like this: "Section 1, Collapsed, Button." Then when you use the screen reader commands to open it, it will read: "Section 1, Expanded, Button." (If you'd like to see the video sample of this, check out the &lt;a href="https://www.a11ywithlindsey.com/blog/introduction-aria-states" rel="noopener noreferrer"&gt;original blog post&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;Imagine if we took off the &lt;code&gt;aria-expanded&lt;/code&gt; attribute which I did in a &lt;a href="https://codepen.io/littlekope0903/pen/GazpwN/" rel="noopener noreferrer"&gt;separate CodePen&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: I kept most of the original code in here. That way, I could demonstrate the visual opening and closing. Additionally, it shows how it doesn’t work for a screen reader user.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you don't add in the &lt;code&gt;aria-expanded&lt;/code&gt; attribute, when I press the open up the menu, it doesn't stop reading "Section 1, button" tell me if the accordion is open. The interruption is helpful to understand the space. (If you'd like to see the video sample of this, check out the &lt;a href="https://www.a11ywithlindsey.com/blog/introduction-aria-states" rel="noopener noreferrer"&gt;original blog post&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;Do you notice how when I open the button, it doesn’t communicate whether the section is open or closed? This is critical for a screen reader user to know what is going on. Withholding verbal communication of state is confusing for screen reader users.&lt;/p&gt;

&lt;p&gt;Anytime we hide content that expands upon user action, use &lt;code&gt;aria-expanded&lt;/code&gt;. When you use JavaScript to toggle it, it becomes a better user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;hidden&lt;/code&gt; attribute
&lt;/h2&gt;

&lt;p&gt;If you saw my notes above, you may have seen that I changed up the code. Previously, I had the accordion using an &lt;code&gt;aria-hidden&lt;/code&gt; attribute (more on that later). Upon the button click, I would toggle the value to be &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;. The reason for that is because &lt;code&gt;hidden&lt;/code&gt; is the HTML equivalent of &lt;code&gt;display: none&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When I started with accessibility, the motivation to hide content from screen readers baffled me. Why would I want to exclude them from content?? I used to be resistant to &lt;strong&gt;ever&lt;/strong&gt; using &lt;code&gt;hidden&lt;/code&gt;, but the reality is sometimes it’s necessary. With some forms of content, we don’t want to expose content to a user until we interact with it. For example, with modals and accordions, we only want to see what’s inside if they are open.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to use &lt;code&gt;aria-hidden&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;There's one significant difference between &lt;code&gt;aria-hidden&lt;/code&gt; and &lt;code&gt;hidden&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;aria-hidden&lt;/code&gt; only hides elements from screen readers, while &lt;code&gt;hidden&lt;/code&gt; hides from everyone.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I ask myself if there are HTML elements that are primarily for decoration. If so, I might want to use &lt;code&gt;aria-hidden&lt;/code&gt; to hide it from screen readers but not from visually-abled users.&lt;/p&gt;

&lt;p&gt;One of my favorite reason’s to use &lt;code&gt;aria-hidden&lt;/code&gt; is to prevent repetition. This, for example, is the Home button for Twitter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"js-nav js-tooltip js-dynamic-tooltip"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"Icon Icon--home Icon--large"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"Icon Icon--homeFilled Icon--large u-textUserColor"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;aria-hidden=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"u-hiddenVisually a11y-inactive-page-text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"u-hiddenVisually a11y-active-page-text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Home, current page.
  &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"u-hiddenVisually hidden-new-items-text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    New Tweets available.
  &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this instance, the screen reader announces one of the “a11y page texts” based on the context of the page. I want you to take note of this line of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;aria-hidden=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the one that is actually on the screen. We have the dynamic options for the screen reader like “Home,” “Home, current page,” and “Load new Tweets.” We don’t need that context on the Home button if we can see the visual cues.&lt;/p&gt;

&lt;p&gt;With that being said, my rule is if we are toggling states, I use &lt;code&gt;hidden&lt;/code&gt;. If there’s duplicate or unnecessary content, I’ll use &lt;code&gt;aria-hidden&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;aria-current&lt;/code&gt; attribute
&lt;/h2&gt;

&lt;p&gt;Fun fact, this one is totally new to me. I didn’t learn about this until I saw &lt;a href="https://twitter.com/ericwbailey/" rel="noopener noreferrer"&gt;Eric Bailey&lt;/a&gt;’s tweet about the &lt;a href="https://a11yproject.com/" rel="noopener noreferrer"&gt;a11y project&lt;/a&gt; redesign:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1134863254310797312-703" src="https://platform.twitter.com/embed/Tweet.html?id=1134863254310797312"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1134863254310797312-703');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1134863254310797312&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;The best part about the web and accessibility practices is I learn something new every day. After seeing this tweet, I found &lt;a href="https://tink.uk/using-the-aria-current-attribute/" rel="noopener noreferrer"&gt;Léonie’s post on aria-current&lt;/a&gt;. Something they pointed out is that we predominately use CSS to show the “current” element visually. In my Drupal days, most themes had an &lt;code&gt;.is-active&lt;/code&gt; class if you were on a menu item that reflected the current URL.&lt;/p&gt;

&lt;p&gt;As Léonie said, the problem with this approach is CSS is mostly visual. Meaning (with an exception) 0 of the styling is exposed to screen readers. Using aria-current helps ensure that we communicate the context to screen reader users. According to &lt;a href="https://www.w3.org/TR/wai-aria-1.1/#aria-current" rel="noopener noreferrer"&gt;WAI-ARIA 1.1&lt;/a&gt;, there are a few values that &lt;code&gt;aria-current&lt;/code&gt; could take on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;page&lt;/strong&gt; for a link within a set of pagination links, the current page as represented in the navigation, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;step&lt;/strong&gt; for a step-based process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;date&lt;/strong&gt; for a current date.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;time&lt;/strong&gt; for a current time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, this should be only one element in a set of elements can have an &lt;code&gt;aria-current&lt;/code&gt; value. Otherwise, it will confuse the screen reader!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I plan to have more blog posts about ARIA and state in the future. I hope this helped you demystify a few more aria attributes.&lt;/p&gt;

&lt;p&gt;Let me know on &lt;a href="https://twitter.com/LittleKope/" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; what you think! Also, I now have a &lt;a href="https://www.patreon.com/a11ywithlindsey" rel="noopener noreferrer"&gt;patreon&lt;/a&gt;! If you like my work, consider becoming a patron. You’ll be able to vote on future blog posts if you make a \$5 pledge or higher! Cheers! Have a great week!&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>aria</category>
      <category>frontend</category>
    </item>
    <item>
      <title>My Blogging Editing Process</title>
      <dc:creator>Lindsey Kopacz</dc:creator>
      <pubDate>Mon, 03 Jun 2019 17:37:50 +0000</pubDate>
      <link>https://dev.to/lkopacz/my-blogging-editing-process-2a3d</link>
      <guid>https://dev.to/lkopacz/my-blogging-editing-process-2a3d</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://www.a11ywithlindsey.com/blog/blogging-editing-process"&gt;www.a11ywithlindsey.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;span&gt;Hej från sverige!&lt;/span&gt; I’m writing this from Stockholm Airport! I’m on my way to Copenhagen to visit a friend (although when I publish this, I likely will be back in America). I am coming back into my blogging headspace after a bit of a wild week. I spoke about JavaScript and Accessibility for the Spotify Engineering team! Preparing to speak for my first time internationally was rough. However, I cannot even begin to explain how rewarding this experience has been. It’s a talk I’ve wanted to give for a long time, and for a good reason. It was well received, and I had many folks come up to me afterward.&lt;/p&gt;

&lt;p&gt;This post isn’t going to be a talk about speaking. I wanted to give you a glimpse because if you don’t follow me on Twitter, you would have no idea! Onto blogging!&lt;/p&gt;

&lt;p&gt;A few weeks ago, I asked people if they had an interest in my blog editing process. I’m very public about my writing process, and the idea popped into my head.&lt;/p&gt;

&lt;blockquote class="twitter-tweet" data-lang="en"&gt;
&lt;p&gt;Random question: would people be interested to hear about my editing process?&lt;br&gt;&lt;br&gt;I have ADHD and I'm a Type A perfectionist. Editing used to be a challenge, but I've gotten way better and shortened my process a ton! &lt;a href="https://t.co/3HdXdgHMM1"&gt;https://t.co/3HdXdgHMM1&lt;/a&gt;&lt;/p&gt;— Lindsey Kopacz 🐞in Stockholm 🇸🇪 (@LittleKope) &lt;a href="https://twitter.com/LittleKope/status/1124278521378037760?ref_src=twsrc%5Etfw"&gt;May 3, 2019&lt;/a&gt;
&lt;/blockquote&gt;

&lt;p&gt;I had an overwhelming response that said yes. I also asked on my &lt;a href="https://www.patreon.com/join/a11ywithlindsey"&gt;Patreon&lt;/a&gt;. While my last post about &lt;a href="https://www.a11ywithlindsey.com/blog/javascript-accessibility-accordions"&gt;JavaScript and Accordions&lt;/a&gt; won out, this topic was a close second. So here we are!&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting out
&lt;/h2&gt;

&lt;p&gt;First comes writing the thing. Many people have formats like writing outlines and where their points are. I wish I could say I consistently write outlines...but I don’t. I either look to Patreon, Twitter, or a long list of ideas I have written down and pick a topic and get to writing.&lt;/p&gt;

&lt;p&gt;Instead of creating a formal outline, I pull up my Markdown file. In the markdown file, I start creating headings about how I want to group my thoughts. These headings are pseudo outlining, I suppose, but I don’t go through the bullet-pointed list. I tend to add structure during my editing process and let my creative juices flow. I firmly believe that my blog posts are unique because I start this way, then make it more coherent later. That energy is part of who I am, and I also think it helps me relate to people and helps me creatively solve problems.&lt;/p&gt;

&lt;p&gt;If you struggle with feeling all over the place, remember you can always edit it out later. I use tools to help me edit my sloppy writing into cohesive sentences. Some of my best writing comes from going with the flow.&lt;/p&gt;

&lt;p&gt;My only exception is when I write code-heavy posts, which takes a little more planning.&lt;/p&gt;

&lt;h3&gt;
  
  
  If I am writing my code-heavy posts
&lt;/h3&gt;

&lt;p&gt;If I am writing a more technical blog post, writing code samples is the most time-consuming part. I try to note when I want to schedule a blog post because writing coding examples from scratch adds time. I should take my advice - I still think I can write these on a Sunday afternoon. Then it ends up taking 3-4 more days than I thought it would.&lt;/p&gt;

&lt;p&gt;I tend to be more outlined in these posts than usual because these types of posts follow a step by step nature. I like to organize how &lt;strong&gt;I would solve the problem&lt;/strong&gt; first. My blogging organization for code-heavy posts is about the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Come up with a goal of what I want to teach and what type of examples I would want to do.&lt;/li&gt;
&lt;li&gt;Create a few CodePen's showing where I want to be at different stages of the code.&lt;/li&gt;
&lt;li&gt;Through each step of the code, use the markdown code syntax and &lt;code&gt;diff&lt;/code&gt; to show where the code changes.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- some code I am deleted
&lt;/span&gt;&lt;span class="gi"&gt;+ some code I am adding
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://i.giphy.com/media/3oKIPnAiaMCws8nOsE/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3oKIPnAiaMCws8nOsE/giphy.gif" alt="Cat Programming at a computer."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I try not to overanalyze this part because as I said before, it is the most time-consuming part. The more I overanalyze, the longer it takes me to write my code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Editing Process
&lt;/h2&gt;

&lt;p&gt;The editing process has been one of the hardest things for me to learn. I often get distracted, but I also have perfectionist tendencies. The anxiety of leaving an error or typo is challenging to overcome. Logically, I know it is not the end of the world. Editing used to turn into a long process. Every single time I paused or got distracted, I would lose my place and start over.&lt;/p&gt;

&lt;p&gt;I’ve refined my process a bit based on tips I’ve received from friends and what works best from me.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run through Hemingway
&lt;/h3&gt;

&lt;p&gt;When I was researching &lt;a href="https://www.a11ywithlindsey.com/blog/learn-dyslexia-web"&gt;accessibility and dyslexia&lt;/a&gt;, I found the &lt;a href="http://hemingwayapp.com"&gt;Hemingway App&lt;/a&gt;. It quickly became one of my favorite tools. This app lets you know when your sentences are becoming hard to read. It’s a helpful first step for me in narrowing down the creative energy into cohesion. It helps me translate any word vomit into coherent sentences. The app also catches wordiness, useless adverbs, passive voice, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run it through Grammarly
&lt;/h3&gt;

&lt;p&gt;I love the &lt;a href="https://www.grammarly.com/"&gt;Grammarly app&lt;/a&gt;! I pay for the premium version, but the free version is excellent as well! Grammarly helps me catch many typos, words I use too often, and improper punctuation. With the paid version, it even knows to capitalizes CSS and HTML. These corrections are a feature where you can specify that you are writing something technical (this is for the Premium version).&lt;/p&gt;

&lt;h3&gt;
  
  
  Run it through VoiceOver
&lt;/h3&gt;

&lt;p&gt;This is my favorite part of the process. I learned the commands of VoiceOver as I learn about accessibility. VoiceOver is the built-in screen reader for MacOS. I had never thought to have it read to me as a way to edit until one of my Twitter followers suggested it!&lt;/p&gt;

&lt;p&gt;To have VoiceOver start reading it to me, I will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Turn on voiceover by pressing cmd + F5.&lt;/li&gt;
&lt;li&gt;I will double click on the title header and start pressing ctrl + option + The right arrow.&lt;/li&gt;
&lt;li&gt;The screen reader reads it out to me.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Reading something out loud is one of the best ways to learn that something sounds off. However, sometimes, I get so distracted in the process that I’ll start over or get lost. Without using my screen reader, editing takes forever.&lt;/p&gt;

&lt;h3&gt;
  
  
  Walk through my code samples
&lt;/h3&gt;

&lt;p&gt;If I am writing code for that blog post (which many times I am), I want to go through every single step of the post. I will copy and paste the code from a CodePen into an index.html file. I’ll follow my diffs to make sure that I accounted for every single step.&lt;/p&gt;

&lt;p&gt;Going through this step by step ensures:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;My code works if someone else were to go through it&lt;/li&gt;
&lt;li&gt;I didn't forget to show my readers a crucial step&lt;/li&gt;
&lt;li&gt;Catch any assumptions you make.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This last one is important. There were a couple of times where I thought something was working, but it &lt;strong&gt;wasn't&lt;/strong&gt;. Giving my audience code that doesn't work isn't particularly helpful!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I love using tools to help me edit. The anxiety and time that it takes to write and publish a post can be downright daunting. I’ve used this process to cut down the amount of time it takes me to edit, and I hope it helps you as well! Blogging as a developer is very rewarding, and I’m glad I’ve found a process that works for me.&lt;/p&gt;

&lt;p&gt;Let me know on &lt;a href="https://twitter.com/LittleKope/"&gt;Twitter&lt;/a&gt; what you think! Also, I now have a &lt;a href="https://www.patreon.com/a11ywithlindsey"&gt;patreon&lt;/a&gt;! If you like my work, consider becoming a patron. You’ll be able to vote on future blog posts if you make a $5 pledge or higher! Cheers! Have a great week!&lt;/p&gt;

</description>
      <category>blogging</category>
      <category>editing</category>
      <category>discuss</category>
    </item>
    <item>
      <title>7 Ways to make your Tweets more Accessible </title>
      <dc:creator>Lindsey Kopacz</dc:creator>
      <pubDate>Wed, 22 May 2019 08:57:22 +0000</pubDate>
      <link>https://dev.to/lkopacz/7-ways-to-make-your-tweets-more-accessible-4c67</link>
      <guid>https://dev.to/lkopacz/7-ways-to-make-your-tweets-more-accessible-4c67</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://www.a11ywithlindsey.com/blog/7-ways-tweets-more-accessible" rel="noopener noreferrer"&gt;www.a11ywithlindsey.com&lt;/a&gt;. In that post I've included videos with how it sounds to screen readers, but because they aren't hosted on youtube, I cannot link them here. Check them out on the original blog post!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I wrote a tweet thread a while back where I started talking about ways to keep accessibility in mind on the platforms we use such as Twitter. Sometimes we don’t have control over the platforms we use, and the best we can do is ensure our content is accessible. This tweet thread got a decent amount of attention, but unfortunately, it’s easy for things to get lost in the Twitterverse. I decided to write a blog post elaborating a bit more on each of the critical points I made while also ensuring that you could find them more easily.&lt;/p&gt;

&lt;h2&gt;
  
  
  Be careful with your emoji use
&lt;/h2&gt;

&lt;blockquote data-lang="en"&gt;
&lt;p&gt;Thank 👏 you 👏 Kent! (don't do the clap thing either, it's a huge pain in screen readers)&lt;/p&gt;— Marcy Sutton (&lt;a class="mentioned-user" href="https://dev.to/marcysutton"&gt;@marcysutton&lt;/a&gt;) &lt;a href="https://twitter.com/marcysutton/status/1083074150749503488?ref_src=twsrc%5Etfw" rel="noopener noreferrer"&gt;January 9, 2019&lt;/a&gt;
&lt;/blockquote&gt;

&lt;p&gt;Marcy pointed out here how the clapping hands are actually a pain for screenreaders. &lt;/p&gt;

&lt;p&gt;Here’s what it reads if you turn on your screenreader: “Thank clapping hands you clapping hands Kent.” Can you imagine if it was done between every single word on a longer sentence? I see passionate people do this all the time, particularly when they want to say something regarding social issues. I get torn between two worlds because I know how awful it is for screenreaders, but usually, there is a message behind the tweet that I support.&lt;/p&gt;

&lt;p&gt;In general, we should be careful about our emoji use. I created a tweet just for the purposes of this blog post. If we clog an entire tweet with just emojis and no words it sounds like word vomit.&lt;/p&gt;

&lt;p&gt;I love emojis, but let's not abuse them. We should use words more!&lt;/p&gt;

&lt;h2&gt;
  
  
  Don’t use special characters in your handle or your tweets
&lt;/h2&gt;

&lt;p&gt;I’ve already mentioned this tweet in previous posts, but I’ll repeat it:&lt;/p&gt;

&lt;blockquote data-lang="en"&gt;
&lt;p&gt;You 𝘵𝘩𝘪𝘯𝘬 it's 𝒸𝓊𝓉ℯ to 𝘄𝗿𝗶𝘁𝗲 your tweets and usernames 𝖙𝖍𝖎𝖘 𝖜𝖆𝖞. But have you 𝙡𝙞𝙨𝙩𝙚𝙣𝙚𝙙 to what it 𝘴𝘰𝘶𝘯𝘥𝘴 𝘭𝘪𝘬𝘦 with assistive technologies like 𝓥𝓸𝓲𝓬𝓮𝓞𝓿𝓮𝓻? &lt;a href="https://t.co/CywCf1b3Lm" rel="noopener noreferrer"&gt;pic.twitter.com/CywCf1b3Lm&lt;/a&gt;&lt;/p&gt;— Kent C. Dodds (&lt;a class="mentioned-user" href="https://dev.to/kentcdodds"&gt;@kentcdodds&lt;/a&gt;) &lt;a href="https://twitter.com/kentcdodds/status/1083073242330361856?ref_src=twsrc%5Etfw" rel="noopener noreferrer"&gt;January 9, 2019&lt;/a&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you listen to his video, can you hear how much it doesn’t make any sense? It may not be as cute or as fancy, but it's usually a good idea to not try to use fonts that are unsupported on the platform. Twitter doesn't give you the ability to choose a font, so you shouldn't try without testing to ensure it works for everyone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enable Alternative Text on your Tweets
&lt;/h2&gt;

&lt;p&gt;And actually use them! If you’re on your Desktop computer, you can enable them by:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click on your Profile Picture and go to Settings &amp;amp; Privacy&lt;/li&gt;
&lt;li&gt;Go to the Accessibility Section in the left sidebar&lt;/li&gt;
&lt;li&gt;Check “Compose image descriptions”&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Look, I even recorded it for you!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/wJ51taGkDDNftOFMPt/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/wJ51taGkDDNftOFMPt/giphy.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you get this enabled, you should be able to see an “Add Description” on your images. Also, Twitter, why isn't this enabled by default?&lt;/p&gt;

&lt;h2&gt;
  
  
  Test your Profile’s Page Contrast
&lt;/h2&gt;

&lt;p&gt;Have you ever tested the color contrast on your Twitter Profile theme? After checking the default themes on my Twitter profile, I discovered that they have shockingly poor contrast. I use the &lt;a href="https://webaim.org/resources/contrastchecker/" rel="noopener noreferrer"&gt;Webaim Color Contrast Checker&lt;/a&gt; to see what the contrast is. The minimum contrast for Large Text is 3:1 and for small text is 4.5:1. Here are the contrast colors:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Orange Theme&lt;/strong&gt; - The background color is &lt;code&gt;#FE6A1F&lt;/code&gt; on a white foreground color which has a contrast of 2:88:1. (FAIL)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Yellow Theme&lt;/strong&gt; - The background color is &lt;code&gt;#FAB81D&lt;/code&gt; on a white foreground color which has a contrast of 1.76:1. (FAIL)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Light Mint Theme&lt;/strong&gt; - The background color is &lt;code&gt;#7FDBB6&lt;/code&gt; on a white foreground color which has a contrast of 1.65:1. (FAIL)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mint Theme&lt;/strong&gt; - The background color is &lt;code&gt;#19CE86&lt;/code&gt; on white foreground color which has a contrast of 2.06:1. (FAIL)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Periwinkle Theme&lt;/strong&gt; - The background color is &lt;code&gt;#91D1FA&lt;/code&gt; on a white foreground color which has a contrast of 1.65:1. (FAIL)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blue Theme&lt;/strong&gt; - The background color is &lt;code&gt;#1A94E0&lt;/code&gt; on a white foreground color which has a contrast of 3.30:1. (PASS large text only)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gray Theme&lt;/strong&gt; - The background color is &lt;code&gt;#ABB8C1&lt;/code&gt; on a white foreground color which has a contrast of 2.03:1. (FAIL)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dark Pink Theme&lt;/strong&gt; - The background color is &lt;code&gt;#E81C4F&lt;/code&gt; on a white foreground color which has a contrast of 4.46:1. (PASS large text only)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Light Pink Theme&lt;/strong&gt; - The background color is &lt;code&gt;#F58EA7&lt;/code&gt; on a white foreground color which has a contrast of 2.26:1. (FAIL)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Purple Theme&lt;/strong&gt; - The background color is &lt;code&gt;#981CEB&lt;/code&gt; on a white foreground color which has a contrast of 5.67:1. (PASS both large and small text)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So if you count that, out of 10 themes only 1 (!!) has a passing contrast on both large and small text. 2 pass with larger text. The rest fail. This stinks on Twitter's part, but you can also add your own custom HEX Color Code! I just changed mine to have it be one of the colors in my design on my site.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/.%2Fhex-value-twitter.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/.%2Fhex-value-twitter.png" alt="Twitter Theme Selector with a bunch of different rainbow colors to select for your profile."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Communicate with words, not symbols making a picture
&lt;/h2&gt;

&lt;p&gt;“Today’s tea” seems to be pretty popular on Twitter, but I can’t stop thinking about what this sounds like on a screen reader.&lt;/p&gt;

&lt;blockquote data-lang="en"&gt;
&lt;p&gt;Today's tea:&lt;br&gt;                      (&lt;br&gt;            (           )        )&lt;br&gt;_(_____)____(_____(____(_&lt;br&gt; \          Grad students /_&lt;br&gt;   \       should be         /    |&lt;br&gt;     \      paid livable    /___|&lt;br&gt;       \    wages for     /&lt;br&gt;         \   their hard   /&lt;br&gt;           \_   work     _/&lt;/p&gt;— Jay Shelat (@jshelat1) &lt;a href="https://twitter.com/jshelat1/status/1093314977077911558?ref_src=twsrc%5Etfw" rel="noopener noreferrer"&gt;February 7, 2019&lt;/a&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because I couldn't stop thinking about it, I found a tweet and turned on my screen reader. I posted a video &lt;a href="https://www.a11ywithlindsey.com/blog/7-ways-tweets-more-accessible" rel="noopener noreferrer"&gt;on my blog&lt;/a&gt; about what it sounds like.&lt;/p&gt;

&lt;p&gt;So, uh, yeah. Not sure how to fix it aside from not doing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Transcribe Memes and Gifs
&lt;/h2&gt;

&lt;p&gt;As of this writing, there is no way to add alt text to gifs. I usually do this by typing in &lt;code&gt;[gif alt: Descriptive phrase]&lt;/code&gt; in the body whenever I add a gif. Sometimes I see people respond back to me with a gif message and a gif alt back, and that makes my heart sing. You should do the same with Memes, especially once you have enabled Alternative Text on your photos using the tip above. (Source: &lt;a href="https://lifeofablindgirl.com/2018/10/31/6-ways-to-make-your-social-media-posts-accessible-for-people-with-a-visual-impairment/" rel="noopener noreferrer"&gt;Life of a Blind Girl: 6 ways to make your social media posts accessible for people with a visual impairment&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Capitalize the words in your hashtags
&lt;/h2&gt;

&lt;p&gt;This one is new to me, but it makes a lot of sense. Without it, it makes a lot of screen readers mash up the words and sound like a jumbled mess. (Source: &lt;a href="https://lifeofablindgirl.com/2018/10/31/6-ways-to-make-your-social-media-posts-accessible-for-people-with-a-visual-impairment/" rel="noopener noreferrer"&gt;Life of a Blind Girl: 6 ways to make your social media posts accessible for people with a visual impairment&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I want to thank people who write blog posts like the one mentioned for the source of the last two sections. If you haven't already, I would read that article because there are items that I wanted to include, but this post was starting to get too long. Even as an accessibility person, I still have a ton to learn about these platforms. I have also learned a lot from great advocates in tech as well, such as &lt;a href="https://twitter.com/marcysutton" rel="noopener noreferrer"&gt;Marcy Sutton&lt;/a&gt;, &lt;a href="https://twitter.com/redcrew" rel="noopener noreferrer"&gt;Deborah Edwards-Onoro&lt;/a&gt;, and &lt;a href="https://twitter.com/tatianatmac" rel="noopener noreferrer"&gt;Tatiana Mac&lt;/a&gt;! Accessibility isn’t just about coding, it’s about real people who use products that have become everyday use and commonplace.&lt;/p&gt;

&lt;p&gt;Remember to think before you tweet. Who are you potentially excluding from reading your Twitter content? If you have any thoughts on this post, feel free to reach out to me on, you guessed it, &lt;a href="https://twitter.com/LittleKope" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>twitter</category>
      <category>a11y</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
