<?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>Forem: Erik Kroes</title>
    <description>The latest articles on Forem by Erik Kroes (@erikkroes).</description>
    <link>https://forem.com/erikkroes</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%2F150268%2Ff184ca70-b5b8-4918-8551-d73530868241.png</url>
      <title>Forem: Erik Kroes</title>
      <link>https://forem.com/erikkroes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/erikkroes"/>
    <language>en</language>
    <item>
      <title>Accessibility is not binary</title>
      <dc:creator>Erik Kroes</dc:creator>
      <pubDate>Fri, 22 Sep 2023 07:47:47 +0000</pubDate>
      <link>https://forem.com/erikkroes/accessibility-is-not-binary-2ebi</link>
      <guid>https://forem.com/erikkroes/accessibility-is-not-binary-2ebi</guid>
      <description>&lt;p&gt;Often when people talk about accessibility, it appears to be this binary thing. Something either is or isn’t accessible. And that’s true, but it also isn’t.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is it accessible?
&lt;/h2&gt;

&lt;p&gt;I learned a lot about accessibility with this mindset. I’ve always thought of accessibility as a bridge. You can fix 99% of the bridge, but if one section is missing, people still can’t cross. A bridge with holes isn’t a finished bridge. There’s still work to do!&lt;/p&gt;

&lt;p&gt;When you think of accessibility as a subject for business, it’s probably true! Let’s frame it as a user story: As a business I want to comply with WCAG 2.1 AA so I can avoid law suits.&lt;/p&gt;

&lt;p&gt;And that’s the thing right? For a lot of people(/businesses) being accessible means being compliant with WCAG (Web Content Accessibility Guidelines) 2.1 AA. And yes, the question “Is this compliant?” can be answered with a hard yes or no.&lt;/p&gt;

&lt;p&gt;And that’s where audits come in. An audit is when a specialist inspects your website (or app?). Often they follow the methodology WCAG-EM. Their findings go into a big report that states wether you’re accessible (complying with WCAG 2.1 AA) or not, and what you need to fix.&lt;/p&gt;

&lt;p&gt;In a world where goals and targets are decided by those in management, compliance will often be the target. And in such a situation, an audit is very logical.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is it valuable?
&lt;/h2&gt;

&lt;p&gt;But do I believe that is what accessibility is about? It’s the frame I always had but no, accessibility is a spectrum. Even when you’re not fully accessible (WCAG 2.1 AA compliant), you can still be more accessible than other iterations/the competition.&lt;/p&gt;

&lt;p&gt;You might still be excluding people, but that doesn’t mean there are no improvements. I’d still aim for WCAG-compliance. There’s a reason these guidelines end up in regulations all over the world: they’re pretty good. But it also a minimum. It’s the legal requirement in many situations that will avoid getting you sued. It’s not the ideal standard that will ensure everybody will have a great time interacting with your website.&lt;/p&gt;

&lt;p&gt;But don’t forget to be proud when you’re making steps -towards- compliance. When your product is audited, and you’ve fixed previous issues... that’s improvement! You’re including -more- people than before. And that’s valuable! Be proud of what you’ve achieved and what you’ve learned!&lt;/p&gt;

&lt;h2&gt;
  
  
  Concluding
&lt;/h2&gt;

&lt;p&gt;Audits are a great tool for compliance. They’re an external collection of findings. Taking the point of view of somebody building something, it might not be the most valuable feedback. A modern workflow start with components and does not revolve around the delivered pages. So you want your feedback to be shaped like that as well.&lt;/p&gt;

&lt;p&gt;If you’re going for something that’s not just compliance, I would advice looking from the ground up. Make accessibility part of the requirements, incorporate it in your foundations (like design systems and component libraries), focus on it during design, make it part of your handovers, consider it while building and double-check it when delivering.&lt;/p&gt;

&lt;p&gt;Something as foundational as accessibility can be judged with an audit, but just looking at the end-result won’t fix it. Even when you aim for compliance, it’ll be hard to reach from an audit.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Color and contrast, what does it mean?</title>
      <dc:creator>Erik Kroes</dc:creator>
      <pubDate>Tue, 07 Sep 2021 07:44:41 +0000</pubDate>
      <link>https://forem.com/erikkroes/color-and-contrast-what-does-it-mean-40gd</link>
      <guid>https://forem.com/erikkroes/color-and-contrast-what-does-it-mean-40gd</guid>
      <description>&lt;p&gt;The color contrast ratios mentioned in WCAG can give you an insight in how usable your color palette is. How that works isn't very transparent. Learn more about how the color contrast ratio is determined, and what that means for you (and your palette).&lt;/p&gt;

&lt;p&gt;Originally posted on &lt;a href="https://www.erikkroes.nl/"&gt;erikKroes.nl&lt;/a&gt;. Questions are also welcome on &lt;a href="https://twitter.com/erikKroes"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How it used to be
&lt;/h2&gt;

&lt;p&gt;When I started auditing websites and designs, my life was still simple.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I'd grab a color picker tool like the &lt;a href="https://github.com/ThePacielloGroup/CCAe/"&gt;Colour Contrast Analyser&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;For pieces of text, I'd pick the background color.&lt;/li&gt;
&lt;li&gt;And separately I'd pick the foreground color.&lt;/li&gt;
&lt;li&gt;The tool would spit out a number for me; the contrast ratio.&lt;/li&gt;
&lt;li&gt;I'd apply &lt;a href="https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html"&gt;WCAG Succes Criterion 1.4.3: Contrast (Minimum)&lt;/a&gt;. In short, if the ratio is below 3.0:1, it would lack contrast. If it's above 4.5:1, it would be fine. If it's inbetween, I'd have to check the text size. Large text (at least 19px and bold, or at least 24px) would still pass. Fail for anything else. This all assuming an audit at level AA.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Problably no big surprises for many people reading this. A small recap to make sure. I use a tool to measure the contrast between text and its background. WCAG gives us a ratio as a minimum requirement. Large text gets a bit of slack.&lt;/p&gt;

&lt;p&gt;I didn't question the numbers, and the numbers didn't question me. Until I did.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fabric store
&lt;/h2&gt;

&lt;p&gt;This all changed because I ran an online fabric store with my wife. An online store needs a website. We had one, but it was WordPress, and WooCommerce, and a theme, and a child theme, lots of extensions, and two versions of bootstrap at the same time. Let's say there was room for improvement in how things were built.&lt;/p&gt;

&lt;p&gt;So I went for an adequete amount of exaggeration and thought, why not start with the basics? Why not start with... an accessible color palette?&lt;/p&gt;

&lt;p&gt;And that's when things got interesting. I always learn things when I put myself in the shoes of people I usually communicate with. In this case, I dove into something designers usually do. And (spoiler) it's not easy to make such a color palette!&lt;/p&gt;

&lt;h2&gt;
  
  
  Color, it's pretty complicated
&lt;/h2&gt;

&lt;p&gt;Studying photography has taught me color is not an easy subject. You quickly touch on subjects like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How do eyes work?&lt;/li&gt;
&lt;li&gt;How does the brain interpret what it sees?&lt;/li&gt;
&lt;li&gt;How do we display color?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's a colorful rabbit hole, but still a rabbit hole.&lt;/p&gt;

&lt;h2&gt;
  
  
  Color models
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Red, Green and Blue
&lt;/h3&gt;

&lt;p&gt;If you're reading this, I'm assuming you know something about computers. On computers we traditionally define colors with Red, Green and Blue. Why? Because displays work with tiny red, green and blue lights. And together they can be any (sort of) color. An RGB-notation can be used for this.&lt;/p&gt;

&lt;p&gt;In CSS there is a scale of 0 to 255 for color values. 255, 0, 0 means all the red, no green and no blue. This results in red. A harsh blue would be 0, 0, 255. Orange is full red and half green: 255, 127, 0. White is 255, 255, 255. Black is 0, 0, 0. The value is from 0 to 255 because thats 256 and 2 to the power of 8 is 256 and a byte and.. before you know it I start ranting about color again.&lt;/p&gt;

&lt;p&gt;But nevermind. WCAG works differently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hue, Saturation and Lightness
&lt;/h3&gt;

&lt;p&gt;There's also HSL (instead of RGB). It works with Hue, Saturation and Lightness. You might've seen (haha) it before. Hue is like having all tints in a circle. It starts with 0 (degrees) for red. Rotate to 30 and you get orange. Rotate to 60 for yellow. 120 is green. 240 is blue. 360 or 0 (full circle) is red again. Feels much more intuitive to me!&lt;/p&gt;

&lt;p&gt;Saturation is how saturated or full a color is. 100 (percent) for full color and 0 for none. The L is for Lightness. How light an image is with 100 (percent) being white and 0 being black.&lt;/p&gt;

&lt;p&gt;That sounds much more understandable and readable than RGB. It's almost usable! But of course, it's not. Making things easy would be... too easy? Compare the two colors in this image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t4qlxzjN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.erikkroes.nl/assets/media/yellow-blue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t4qlxzjN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.erikkroes.nl/assets/media/yellow-blue.png" alt="A big rectangle that's blue on the left and yellow on the right." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's a blue (240, 100, 50 in HSL) and a yellow (60, 100, 50) in HSL. The only difference is the hue. But to our eyes and in our perception, the blue is much darker than the yellow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nI012E8Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.erikkroes.nl/assets/media/red.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nI012E8Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.erikkroes.nl/assets/media/red.png" alt="Three red squares with varying brightness. The top one is the brightest, and the bottom one is the darkest." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To put it in further perspective. These are three red squares. The first and brightest is 0, 100, 68. It has a contrast ratio of 3.0:1 on white. The second is 0, 100, 47 and a ratio of 4.5:1. The third is 0, 100, 36 and has a ratio of 7.0:1. The ratios were picked because they're practical in a WCAG-context. Don't read too much into them.&lt;/p&gt;

&lt;p&gt;Now what happens if we make a grid with the same saturation, these three luminosities but different hues?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ANaaEiDd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.erikkroes.nl/assets/media/palette.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ANaaEiDd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.erikkroes.nl/assets/media/palette.png" alt="A grid of three by six colored squares. They're red, yellow, green, cyan, blue and magenta. The top one of each color is the brightest, while the bottom one is the darkest." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We get red, yellow, green, cyan, blue and magenta. They're evenly spaced on the hue-scale. They are not, however, evenly scaled in contrast. Where red a nice 3.0, 4.5 and 7.0, yellow is 1.1, 1.2 and 2.1. Much lower numbers! So the L-value is the same, but the contrast isn't. Blue is much like the opposite of yellow in this case with contrasts of 4.8, 9.3 and 12.4. Where the darkest yellow is not contrasty enough (according to WCAG) for large text (it's less than 3.0), the lightest blue is dark enough (more than 4.5) for small text even!&lt;/p&gt;

&lt;p&gt;Check out all the contrast ratios in this table.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Red&lt;/th&gt;
&lt;th&gt;Yellow&lt;/th&gt;
&lt;th&gt;Green&lt;/th&gt;
&lt;th&gt;Cyan&lt;/th&gt;
&lt;th&gt;Blue&lt;/th&gt;
&lt;th&gt;Magenta&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;3.0&lt;/td&gt;
&lt;td&gt;1.1&lt;/td&gt;
&lt;td&gt;1.3&lt;/td&gt;
&lt;td&gt;1.2&lt;/td&gt;
&lt;td&gt;4.8&lt;/td&gt;
&lt;td&gt;2.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4.5&lt;/td&gt;
&lt;td&gt;1.2&lt;/td&gt;
&lt;td&gt;1.6&lt;/td&gt;
&lt;td&gt;1.4&lt;/td&gt;
&lt;td&gt;9.3&lt;/td&gt;
&lt;td&gt;3.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7.0&lt;/td&gt;
&lt;td&gt;2.1&lt;/td&gt;
&lt;td&gt;2.7&lt;/td&gt;
&lt;td&gt;2.5&lt;/td&gt;
&lt;td&gt;12.4&lt;/td&gt;
&lt;td&gt;5.6&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Is that all?
&lt;/h3&gt;

&lt;p&gt;Maybe you know some other models as well. There's RGBA and HSLA, which include opacity. There's HSB (Hue, Saturation and Brightness) used by tools like photoshop. There's CMYK (Cyan, Magenta, Yellow and Key/blacK) for print. Plenty of options!&lt;/p&gt;

&lt;p&gt;And I'm not even going into Color Spaces yet here. I told you color can get complicated!&lt;/p&gt;

&lt;h2&gt;
  
  
  WCAG?
&lt;/h2&gt;

&lt;p&gt;Yeah sorry. WCAG uses none of those really. Contrast in WCAG is based on &lt;a href="https://en.wikipedia.org/wiki/Rec._709"&gt;ITU-R Recommendation BT.709&lt;/a&gt;. What? ITU-R Recommendation BT.709. That's not very clear.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ITU-R Recommendation BT.709, more commonly known by the abbreviations Rec. 709 or BT.709, standardizes the format of high-definition television, having 16:9 (widescreen) aspect ratio. The first edition of the standard was approved in 1990.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That doesn't help much either probably. Sorry about that. Some things that stand out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's a television standard (of course, why not?)&lt;/li&gt;
&lt;li&gt;It has the same color coverage as sRGB (a much used color space, relevant to computer screens)&lt;/li&gt;
&lt;li&gt;It has a component called Luma (component like R in RGB or H in HSL)&lt;/li&gt;
&lt;li&gt;It's a way to measure brightness in sRGB that takes the human eye in account&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Trying to get back to why all of this is relevant. You don't measure RGB values when you use a color contrast tool. What's relevant in the end is the Luma-component. This component can be calculated from RGB (sRGB usually). The contrast is about 72% based on green (because our eyes are generally sensitive to green), 21% based on red and about 7% based on blue. Your eyes don't care much about blue.&lt;/p&gt;

&lt;h2&gt;
  
  
  We have Luma!
&lt;/h2&gt;

&lt;p&gt;Now we have this value, it's used to calculate the contrast. As you may have noticed in contrast tools, the value varies from 1:1 to 21:1. It's never below 1 or above 21. That's due to the formula WCAG uses. It's a practical choice as far as I know.&lt;/p&gt;

&lt;p&gt;So if black is 1, then white is 21. White is 21 times as bright as black in this system. And black is 21 times as dark as white. The implication here, that was the big eye-opener for me, is that it's a ratio with a clearly defined range.&lt;/p&gt;

&lt;p&gt;If black is 1, and a color X has a ratio of 3.0:1 on black.. then X has a ratio of (21/3=7) 7.0:1 on white.&lt;/p&gt;

&lt;p&gt;Trying to phrase this in multiple ways because it took me a bit for the coin to drop. If black is 1, X is 3, and white is 21. Then white/X (21/3) is 7.&lt;/p&gt;

&lt;p&gt;If you have a color Y that's 4.5:1 on black, then it's also (21/4.5=4.67) 4.67:1 on white.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does that mean for color palettes?
&lt;/h2&gt;

&lt;p&gt;If you are aiming for a minimum contrast of 3.0:1 between shades, then there can be only 3. You've got black at 1. Your shade at (at least) 3.0:1. And the next shade would be at (at least) 9.0:1. Because 9.0 has a contrast of 3.0:1 to 3.0. But, you can't triple 9.0 once again. Then you'd get 27. And 27 is more than 21. You can't create something brighter than white.&lt;/p&gt;

&lt;p&gt;The same goes when you want a minimum of 4.5:1. You can do 1, 4.5 and 20.25 (4.5 times 4.5) but multiply it more and you go beyond 21. Not an option.&lt;/p&gt;

&lt;p&gt;If you're going for a higher contrast like 7.0:1 (relevant for text when looking at WCAG AAA), you can't even fit 3 shades. You can do 1, 7 but 7 times 7 is way too high.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's the practical impact on palettes?
&lt;/h2&gt;

&lt;p&gt;Everybody seems to be working on dark mode these days. It's useful to know that if you want to pick one text color that works on both black and white, you don't have many options. Ideally you pick something with a ratio between 4.5:1 and 4.67:1. There's not a lot of space. It's good to be aware of how WCAG contrast influences your palette.&lt;/p&gt;

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

&lt;p&gt;Math is hard. The best way to understand all written here is probably by trying some tools. One of my favorites is &lt;a href="https://contrast-grid.eightshapes.com/"&gt;Contrast Grid&lt;/a&gt; by Eightshapes. You can insert an entire palette and see what color combinations offer acceptable contrasts. You can use this &lt;a href="https://contrast-grid.eightshapes.com/?version=1.1.0&amp;amp;background-colors=&amp;amp;foreground-colors=%23FFF%0D%0A%23F8F8F8%0D%0A%23E7E7E7%0D%0A%23DFDFDF%0D%0A%23B3B3B3%0D%0A%23909090%0D%0A%23727272%0D%0A%23555%0D%0A%23282828%0D%0A%23000%0D%0A%2349C4C4%0D%0A%2311A0A1%0D%0A%23107F84%0D%0A%23005F62%0D%0A%23FF968D%0D%0A%23EF605B%0D%0A%23CC4040%0D%0A%23A41F29%0D%0A%23F6C257%0D%0A%23DDAC40%0D%0A%23B68818%0D%0A%23966A00%0D%0A%23AADE6F%0D%0A%238EC255%0D%0A%23689D31%0D%0A%234B7F0F%0D%0A%23C8A2F8%0D%0A%23A47ED0%0D%0A%238461AE%0D%0A%23654591%0D%0A&amp;amp;es-color-form__tile-size=large&amp;amp;es-color-form__show-contrast=aaa&amp;amp;es-color-form__show-contrast=aa&amp;amp;es-color-form__show-contrast=aa18&amp;amp;es-color-form__show-contrast=dnp"&gt;pretty usable palette by me&lt;/a&gt; as a starting point. It aims to offers many usable color combinations (but feel more than free to aim higher).&lt;/p&gt;

&lt;p&gt;Another tool I enjoy is &lt;a href="https://leonardocolor.io/"&gt;Leonardo&lt;/a&gt;. It's a tool to generate great palettes with lots of control over contrast and other options. Probably a good step before trying Contrast Grid.&lt;/p&gt;

&lt;p&gt;And yes, WCAG 3 will quite likely provide a new way to calculate contrast. That's great news but we're all working with WCAG 2 for now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let me know if my ranting has helped you, and if you have favorite tools of your own!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Oh, and we sold the fabric store. I never ended up making a whole Design System for our little shop. Probably better that way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ThePacielloGroup/CCAe/"&gt;Colour Contrast Analyser&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html"&gt;WCAG Succes Criterion 1.4.3: Contrast (Minimum)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Rec._709"&gt;ITU-R Recommendation BT.709&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://contrast-grid.eightshapes.com/"&gt;Contrast Grid&lt;/a&gt; by Eightshapes&lt;/li&gt;
&lt;li&gt;&lt;a href="https://contrast-grid.eightshapes.com/?version=1.1.0&amp;amp;background-colors=&amp;amp;foreground-colors=%23FFF%0D%0A%23F8F8F8%0D%0A%23E7E7E7%0D%0A%23DFDFDF%0D%0A%23B3B3B3%0D%0A%23909090%0D%0A%23727272%0D%0A%23555%0D%0A%23282828%0D%0A%23000%0D%0A%2349C4C4%0D%0A%2311A0A1%0D%0A%23107F84%0D%0A%23005F62%0D%0A%23FF968D%0D%0A%23EF605B%0D%0A%23CC4040%0D%0A%23A41F29%0D%0A%23F6C257%0D%0A%23DDAC40%0D%0A%23B68818%0D%0A%23966A00%0D%0A%23AADE6F%0D%0A%238EC255%0D%0A%23689D31%0D%0A%234B7F0F%0D%0A%23C8A2F8%0D%0A%23A47ED0%0D%0A%238461AE%0D%0A%23654591%0D%0A&amp;amp;es-color-form__tile-size=large&amp;amp;es-color-form__show-contrast=aaa&amp;amp;es-color-form__show-contrast=aa&amp;amp;es-color-form__show-contrast=aa18&amp;amp;es-color-form__show-contrast=dnp"&gt;Pretty usable palette by me&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leonardocolor.io/"&gt;Leonardo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>a11y</category>
      <category>html</category>
      <category>webdev</category>
    </item>
    <item>
      <title>A photographer’s view on alt text</title>
      <dc:creator>Erik Kroes</dc:creator>
      <pubDate>Thu, 05 Aug 2021 07:51:18 +0000</pubDate>
      <link>https://forem.com/erikkroes/a-photographer-s-view-on-alt-text-gof</link>
      <guid>https://forem.com/erikkroes/a-photographer-s-view-on-alt-text-gof</guid>
      <description>&lt;p&gt;Images are visual communication. Consider what you're trying to communicate before you do.&lt;/p&gt;

&lt;p&gt;The "cover image" of this writing is from a project I did while studying photography. I wanted to discuss photography but not specific photos. I discovered it's almost impossible to talk about photos, without discussing what's in the photos. So I created images that "felt" like photos but didn't have a clear subject. I wrote a script that grabs random blobs of images from Flickr and turns them into a sort of subjectless collage.&lt;/p&gt;

&lt;p&gt;Originally posted on &lt;a href="https://www.erikkroes.nl/"&gt;erikKroes.nl&lt;/a&gt;. Questions are also welcome on &lt;a href="https://twitter.com/erikKroes"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is alt text?
&lt;/h2&gt;

&lt;p&gt;When I say alt text I’m usually talking about the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-alt"&gt;alt-attribute&lt;/a&gt; for the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img"&gt;img-element&lt;/a&gt; in HTML. But most of what I say goes for other text alternatives as well. So maybe the question should be, what is a text alternative?&lt;/p&gt;

&lt;p&gt;An image says more than a thousand words. But if you can't see an image, well, then it doesn't say much does it? A way to compensate for this is to add a text alternative; a bit of text that serves the same purpose as the image.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's the purpose of the image?
&lt;/h2&gt;

&lt;p&gt;This is the big question if you'd ask me. Wether you add an image to an article you're writing, or you're adding it as an icon to a button, you can't avoid this question. What is the purpose? Why are you adding this image? &lt;strong&gt;What are you trying to communicate?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the end, an image is "just" a way of getting something across. When you write, you pick certain words. You write your sentences in a certain way. You can be aware of how you're communicating and what you're bringing across. An image isn't much different in my experience.&lt;/p&gt;

&lt;p&gt;When you pick an image, ask yourself the same questions. What am I trying to communicate? (Notice this question is very much focussed on the person creating the content and not on what a user wants.)&lt;/p&gt;

&lt;h2&gt;
  
  
  What does that mean in practice?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x8Gk58wl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.erikkroes.nl/assets/media/afde93a0-640.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x8Gk58wl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.erikkroes.nl/assets/media/afde93a0-640.jpeg" alt="President Obama speaking from behind a pedestal" width="640" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's take this image as an example. What does it denote? And I'm picking this word because it is one I picked up during my study in photography. The literal meaning of something is its &lt;a href="https://en.wikipedia.org/wiki/Denotation"&gt;denotation&lt;/a&gt;. In this case it could be something like the pretty generic alt text I added in the code: "President Obama speaking from behind a pedestal". The denotation is also right up the alley of image recognition by artifical intelligence (AI). You literally describe what's in the image. Although you could easily go for an even more literal description here like: "A man in a suit behind a pedestal".&lt;/p&gt;

&lt;p&gt;Stating it's President Obama is already more of a &lt;a href="https://en.wikipedia.org/wiki/Connotation"&gt;connotation&lt;/a&gt;. It's an interpretation of what we see. It's a cultural addition. Other connotations could include mentioning it's the first black president, that it's a former president or that he's talking about Donald Trump here.&lt;/p&gt;

&lt;p&gt;And this is where the purpose of the image plays a role. If you're writing an article on the achievements of black people in the USA, you might add Obama as the first black president. If you're writing a course on public speaking, you might add Obama to illustratie that public speaking is very important for presidents. If the image is to supplement information about pedestals, then you might want to focus on highlighting details on the pedestal in the picture. It all about the purpose. Why are you adding the image?&lt;/p&gt;

&lt;p&gt;The denotation has value but the connotation is often why we add an image. When somebody adds a description of an image into the file (like discussed in this &lt;a href="https://twitter.com/jonsneyers/status/1422646901439086592"&gt;Twitter thread&lt;/a&gt;), it might be enough to derive a connotation from it. But to really get the message across, write your own text alternative.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some more tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Don't include that it's an image.&lt;/strong&gt; Or a picture, a graphic, a visual, etc. That only adds noise as it's already clear from the context.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Write out text.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't stylize text.&lt;/strong&gt; Italic and bold text don't change the message (and might not even be communicated). The same goes for anything beyond basic punctuation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Null" the alt of a decorative image.&lt;/strong&gt; In HTML, if an image is &lt;a href="https://www.w3.org/WAI/tutorials/images/decision-tree/"&gt;decorative&lt;/a&gt;, add an &lt;strong&gt;empty&lt;/strong&gt; alt like &lt;code&gt;&amp;lt;img alt&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;img alt=""&amp;gt;&lt;/code&gt;. And I do mean empty. No spaces or other text like "image" (I'm looking at you Twitter 👀).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why I care
&lt;/h2&gt;

&lt;p&gt;For the past few years, I've been working as a specialist in digital accessibility and inclusive design. In this role I work with WCAG, and the addition of text alternatives is pretty much the &lt;a href="https://www.w3.org/WAI/WCAG21/Understanding/non-text-content.html"&gt;first thing&lt;/a&gt; I check in an audit. Through this role, I've formed an opinion on text alternatives.&lt;/p&gt;

&lt;p&gt;Before this job, I was a photographer. I had 5 years of formal education in this direction. Visual communication is awesome and I wish the theory had stuck with me even more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Concluding
&lt;/h2&gt;

&lt;p&gt;Studying photography has taught me that it's all "just" visual communication. Wether it's text or imagery. Think about the message you're trying to communicate, and shape your communication accordingly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://axesslab.com/alt-texts/"&gt;https://axesslab.com/alt-texts/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jakearchibald.com/2021/great-alt-text/"&gt;https://jakearchibald.com/2021/great-alt-text/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.w3.org/WAI/tutorials/images/decision-tree/"&gt;https://www.w3.org/WAI/tutorials/images/decision-tree/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.smashingmagazine.com/2021/06/img-alt-attribute-alternate-description-decorative/"&gt;https://www.smashingmagazine.com/2021/06/img-alt-attribute-alternate-description-decorative/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=IxHng2L_-aQ&amp;amp;t=19s&amp;amp;pp=sAQA"&gt;https://www.youtube.com/watch?v=IxHng2L_-aQ&amp;amp;t=19s&amp;amp;pp=sAQA&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>a11y</category>
      <category>html</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Semantics, what does it mean?</title>
      <dc:creator>Erik Kroes</dc:creator>
      <pubDate>Tue, 19 Jan 2021 08:10:10 +0000</pubDate>
      <link>https://forem.com/erikkroes/semantics-what-does-it-mean-1pe3</link>
      <guid>https://forem.com/erikkroes/semantics-what-does-it-mean-1pe3</guid>
      <description>&lt;p&gt;When people talk about the quality of HTML code, it is often about semantics. But what are semantics? What is semantic HTML, and why should you care about it?&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;What is Semantic HTML?&lt;/li&gt;
  &lt;li&gt;Wat do semantics do?&lt;/li&gt;
  &lt;li&gt;
How should I do it?
    &lt;ol&gt;
       &lt;li&gt;What do I want to communicate?&lt;/li&gt;
       &lt;li&gt;Is my page structure clear?&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Is that it?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="what-is"&gt;What is Semantic HTML?&lt;/h2&gt;

&lt;p&gt;Semantics is communicating your intention through your chosen HTML. This does not guarantee the correct outcome, but if you communicate a different intention than the outcome, then it is not correct anyway.&lt;br&gt;
A well-known HTML tag is, for example, the &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;. This tag is often used for the most important heading (heading 1) on a page.&lt;br&gt;
&lt;code&gt;&amp;lt;h1&amp;gt; Semantics, what does it mean? &amp;lt;/h1&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The tag or element communicates the intention: this is the main heading, this is what the page is about. If (for example due to an error in the CMS) there is an entire article in a &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; then the result does not match the intention.&lt;br&gt;
In the same way, you can create a link (&lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;) that goes nowhere, or a button (&lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;) that does nothing. With semantic HTML you indicate your intention. That is the first step. The next step is to match the result.&lt;br&gt;
You can compare it with TypeScript or other languages ​​that contain typing. These can not only contain data, but also say something about the data they contain.&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%2Freclni2g4kef3uexyhsm.jpeg" 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%2Freclni2g4kef3uexyhsm.jpeg" alt="A power socket in a wall with water streaming out"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="what-do"&gt;What do semantics do?&lt;/h2&gt;

&lt;p&gt;As indicated, semantics express the intention of an element. If tools can rely on this intention (the semantics indeed say something about the data in the elements) then they can use the content of the elements for all kinds of purposes.&lt;br&gt;
Some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Readability tools&lt;/strong&gt; - There are now many ways to read texts in a more readable format. Sometimes they are stand alone like Pocket and Instapaper. In Firefox and Safari there are tools built in. You can present an existing web page in a different (more readable) way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Translation tools&lt;/strong&gt; - Tools like Google Translate can make use of the context that you communicate as a developer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assistive technology&lt;/strong&gt; - Software such as screen readers inform their users of the semantic value of the HTML they are reading. This way a user can understand whether something is important or only secondary, and whether something is a paragraph or a list.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;People Reading Your Code&lt;/strong&gt; - It may sound obvious, but readable code is nice code to work with. You often write HTML code not only for yourself but for others, or even for yourself at a different time. Clearly written HTML is more readable and more future-proof.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom CSS, adblocking, etc&lt;/strong&gt; - Basically anything that "hooks" into your code benefits from readable, resilient and robust code. If a visitor has Custom CSS for readable headings, then there need to be headings first!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SEO&lt;/strong&gt; - Search engines are like actual people sometimes. They also want to know what information you provide and what the context of that information is.
By creating structure in your code you do not end up with something disjointed. It provides guidance for everyone who has to work with it: developers, visitors and automated tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="how-should-i-do-it"&gt;How should I do it?&lt;/h2&gt;

&lt;p&gt;Does this mean you need to memorize &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element" rel="noopener noreferrer"&gt;all HTML elements&lt;/a&gt;? No, thankfully. Even though there aren’t really that many. &lt;br&gt;
It is nice to find out which elements you know though! Have you tried the &lt;a href="https://codepen.io/plfstr/full/zYqQeRw" rel="noopener noreferrer"&gt;HTML Tags Memory Test&lt;/a&gt; yet?&lt;/p&gt;

&lt;h3 id="what-do-i-want-to-communicate"&gt;What do I want to communicate?&lt;/h3&gt;

&lt;p&gt;This question is very valuable in many situations. If you are writing HTML and you add an element, ask yourself if the element represents your intention correctly. Are you writing a paragraph? Then it makes sense to use a &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt;. Are you doing something for purely visual reasons, without wanting to communicate a specific intention? Then you might be fine with a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; or a &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; (these elements don't communicate any intention).&lt;br&gt;
On the other hand, do you use a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; or a &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; while you want to convey a specific intention? Maybe you want to check the list of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element" rel="noopener noreferrer"&gt;all HTML elements&lt;/a&gt; whether there is a suitable alternative.&lt;/p&gt;

&lt;h3 id="is-my-page-structure-clear"&gt;Is my page structure clear?&lt;/h3&gt;

&lt;p&gt;Every page benefits from a good structure. A newspaper relies on sections, columns and clear headlines. A page on the web (and the underlying HTML) aren’t very different from that.&lt;br&gt;
See if you can organize your page with clear HTML landmarks such as &lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;aside&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;footer&amp;gt;&lt;/code&gt;. A landmark works just like a landmark in real life. If a village has five church towers it becomes difficult to say "go left at the church tower".&lt;br&gt;
You can also use headings (just like with a newspaper). The &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; is the main page header; this indicates what the whole page is about. Technically, all content is covered. If you want to use a heading under the &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;, use the &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt;. Everything that falls under the &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; in the code should logically also fall under this in the content. You create a hierarchy with your headings. Do not skip headings (don't go from &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; to &lt;code&gt;&amp;lt;h4&amp;gt;&lt;/code&gt;) and only place something under a heading if it logically falls under it.&lt;/p&gt;

&lt;h2 id="is-that-it"&gt;Is that it?&lt;/h2&gt;

&lt;p&gt;Yes, kind of actually. Communicate as clearly as possible what the intention of your code is (meta data) and do not let your intention be an empty promise.&lt;/p&gt;

</description>
      <category>html</category>
      <category>a11y</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Extending a component library and it’s documentation for speedy design system</title>
      <dc:creator>Erik Kroes</dc:creator>
      <pubDate>Wed, 02 Dec 2020 10:00:31 +0000</pubDate>
      <link>https://forem.com/erikkroes/extending-a-component-library-and-it-s-documentation-for-speedy-design-system-16h8</link>
      <guid>https://forem.com/erikkroes/extending-a-component-library-and-it-s-documentation-for-speedy-design-system-16h8</guid>
      <description>&lt;p&gt;Lion is a set of white label cross-platform Web Components with accessibility and performance built-in. You can extend them with your own styling to create a complete Design System with little effort.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V-c-hRAT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/4080/1%2ANZ6tdtJHHJjxtPmIFxWpGw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V-c-hRAT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/4080/1%2ANZ6tdtJHHJjxtPmIFxWpGw.jpeg" alt="Styling is extremely flexible" width="800" height="384"&gt;&lt;/a&gt;&lt;em&gt;Styling is extremely flexible&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This blog will demonstrate that extending Lion is not limited to components. Documentation and demos can be reused as well. This removes duplicate work such as writing and maintaining documentation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://medium.com/ing-blog/ing-open-sources-lion-a-library-for-performant-accessible-flexible-web-components-22ad165b1d3d"&gt;Learn more about Lion&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://medium.com/ing-blog/ing-open-sources-lion-a-library-for-performant-accessible-flexible-web-components-22ad165b1d3d"&gt;A demo of Lion&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/ing-bank/lion"&gt;Lion on Github&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;A naming convention that is similar to &lt;code&gt;Lion&lt;/code&gt; for class names and &lt;code&gt;lion-&lt;/code&gt; for tag names is required for this to work. For this demo, we use the the names &lt;code&gt;ExampleButton&lt;/code&gt; and &lt;code&gt;example-button&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Setting up, and Extending Lion&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select documentation to re-use&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change input paths&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove, add and replace sections&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Conclusion&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Setting up, and extending Lion
&lt;/h2&gt;

&lt;p&gt;This article assumes some basic terminal knowledge, and a working installation of npm. Yarn can work as well.&lt;/p&gt;

&lt;p&gt;Create a new folder for our components using the terminal. ExampleButton and &lt;code&gt;example-button&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir example-components
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Enter the folder &lt;code&gt;example-components&lt;/code&gt; and run the following command to scaffold a new project using &lt;a href="https://open-wc.org"&gt;open-wc&lt;/a&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init @open-wc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When presented with a menu, pick (at least) the following options.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What would you like to do today? › Scaffold a new project
✔ What would you like to scaffold? › Web Component
✔ What would you like to add? › Demoing (storybook)
✔ Would you like to use typescript? › No
✔ Would you like to scaffold examples files for? › Demoing (storybook)
✔ What is the tag name of your application/web component? example-button
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Enter the folder &lt;code&gt;example-compponents&lt;/code&gt; and run the following command to make lion-button a dependency. It is the component we will be extending.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i @lion/button --save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Within the folder &lt;code&gt;src&lt;/code&gt;, open the following file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example-button/src/ExampleButton.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Replace the content with the following:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { css } from 'lit-element';
import { LionButton } from '@lion/button';

export class ExampleButton extends LionButton {
  static get styles() {
    return [
      super.styles,
      css`
        /* our styles can go here */
      `
    ];
  }

  connectedCallback() {
    super.connectedCallback();
    this._setupFeature();
  }

  _setupFeature() {
    // our code can go here
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You have now extended &lt;code&gt;&amp;lt;lion-button&amp;gt;&lt;/code&gt; and created &lt;code&gt;&amp;lt;example-button&amp;gt;&lt;/code&gt; from it. The component can be experienced in the browser by running &lt;code&gt;npm run storyboook&lt;/code&gt; inside the &lt;code&gt;example-button&lt;/code&gt;-folder. &lt;br&gt;
Feel free to add styles and make it your own. This can be the start of a whole set of Web Components for your Design System.&lt;/p&gt;

&lt;p&gt;For this article we assume you set up the project like mentioned before, using &lt;a href="https://open-wc.org/demoing/"&gt;Prebuilt Storybook&lt;/a&gt; with &lt;a href="https://open-wc.org/mdjs/"&gt;MDJS&lt;/a&gt;. If you already have a repository, you can also add Storybook using &lt;a href="https://open-wc.org"&gt;open-wc&lt;/a&gt;. Enter the following:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init @open-wc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;And pick ‘upgrade an existing project’. Or install it manually by entering the following:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i @open-wc/demoing-storybook --save-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Select documentation to re-use
&lt;/h2&gt;

&lt;p&gt;We need to specify which stories to load in &lt;code&gt;.storybook/main.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Change the following line:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;stories: ['../stories/**/*.stories.{js,md,mdx}'],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;to add the Lion readme&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;stories: ['../stories/**/*.stories.{js,md,mdx}', '../node_modules/@lion/button/README.md'],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This is where we extend the documentation of &lt;code&gt;LionButton&lt;/code&gt;, for our own &lt;code&gt;ExampleButton&lt;/code&gt;. This step, by itself, gives us the &lt;code&gt;LionButton&lt;/code&gt; docs inside our own Storybook.&lt;/p&gt;
&lt;h2&gt;
  
  
  Change input paths
&lt;/h2&gt;

&lt;p&gt;We can change the import paths from &lt;code&gt;LionButton&lt;/code&gt; to the new paths of &lt;code&gt;ExampleButton&lt;/code&gt;. We use &lt;a href="https://lion-web-components.netlify.app/?path=/docs/tools-providence-main--run-providence"&gt;Providence&lt;/a&gt; for this. This tool has a command that creates a full map of all the import paths of a reference project (&lt;code&gt;Lion&lt;/code&gt;) and can replace them with the correct paths of a target project (&lt;code&gt;Example&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Navigate the terminal to &lt;code&gt;example-button&lt;/code&gt; and install this tool by adding it to our &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i providence-analytics --save-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;We can use it by adding a script to our &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"scripts": {
  "providence:extend": "providence extend-docs -r 'node_modules/@lion/*' --prefix-from lion --prefix-to example"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;--prefix-from&lt;/code&gt; is the prefix of the project you extend from (in this case &lt;code&gt;lion&lt;/code&gt;). &lt;code&gt;--prefix-to&lt;/code&gt; is the prefix of our own project (in this case &lt;code&gt;example&lt;/code&gt;).&lt;br&gt;
It will look for the classnames &lt;code&gt;Lion&lt;/code&gt; and &lt;code&gt;Example&lt;/code&gt;, and for the tagnames &lt;code&gt;lion-&lt;/code&gt; and &lt;code&gt;example-&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As we only use a single component from Lion, we can reduce the time the tool needs for analysis. Specify the single package by replacing &lt;code&gt;-r 'node_modules/@lion/*&lt;/code&gt; with &lt;code&gt;-r 'node_modules/@lion/button'&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can review all from/to information in &lt;code&gt;providence-extend-docs-data.json&lt;/code&gt;. Providence creates this critical file.&lt;/p&gt;
&lt;h3&gt;
  
  
  Replacing paths and names
&lt;/h3&gt;

&lt;p&gt;With the information in the JSON-file, we can start transforming the &lt;code&gt;LionButton&lt;/code&gt; documentation to &lt;code&gt;ExampleButton&lt;/code&gt; documentation. We created a babel-plugin called &lt;a href="https://lion-web-components.netlify.app/?path=/docs/tools-babelpluginextenddocs--page"&gt;babel-plugin-extend-docs&lt;/a&gt; for this.&lt;/p&gt;

&lt;p&gt;This plugin will analyse the content of the markdown files, and transform it on the fly in &lt;code&gt;es-dev-server&lt;/code&gt; and when building with Rollup for production.&lt;/p&gt;

&lt;p&gt;To install this plugin, we navigate the terminal back to &lt;code&gt;example-button&lt;/code&gt; and install this plugin by adding it to our &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i babel-plugin-extend-docs --save-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;A babel.config.js in the root of our project is also needed. It should contain:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const path = require('path');
const providenceExtendConfig = require('./providence-extend-docs-data.json');

const extendDocsConfig = {
  rootPath: path.resolve('.'),
  changes: providenceExtendConfig,
};

module.exports = {
  overrides: [
    {
      test: ['./node_modules/@lion/*/README.md', './node_modules/@lion/*/docs/*.md'],
      plugins: [['babel-plugin-extend-docs', extendDocsConfig]],
    },
  ],
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;We import the providence output file (&lt;code&gt;providence-extend-docs-data.json&lt;/code&gt;) and pass it to the plugin options as the &lt;code&gt;changes&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;The babel plugin runs for the files that we specify in the testproperty, replaces the imports, and replaces the tag names inside JavaScript code snippets!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;It will only transform JavaScript snippets that use &lt;a href="https://open-wc.org/mdjs/"&gt;MDJS&lt;/a&gt; syntax such as js script, js story and js preview-story&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We also have to add Babel to our &lt;code&gt;es-dev-server&lt;/code&gt; configuration to make it work with Storybook.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;.storybook/main.js&lt;/code&gt; with the following content:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
  stories: ['../node_modules/@lion/button/README.md', '../packages/**/!(*.override)*.md'],
  esDevServer: {
    nodeResolve: true,
    watch: true,
    open: true,
    babel: true,
  },
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;We should now see the &lt;code&gt;LionButton&lt;/code&gt; instances transformed into our own &lt;code&gt;ExampleButton&lt;/code&gt;!&lt;/p&gt;
&lt;h2&gt;
  
  
  Remove, add and replace sections
&lt;/h2&gt;

&lt;p&gt;We might not want to show all examples of how to use a component. Sometimes information is &lt;code&gt;Lion&lt;/code&gt; specific, or perhaps in your Design System people are not allowed to use a certain feature that we documented in &lt;code&gt;Lion&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In our example, we will remove the &lt;code&gt;Rationale&lt;/code&gt; section that we would normally inherit from the &lt;code&gt;Lion&lt;/code&gt; documentation.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We assume a folder structure here &lt;code&gt;/packages/&amp;lt;package&amp;gt;/...&lt;/code&gt; here. When updating an existing repository, it might be different.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For this step we make use of a remark plugin for the MD content, similar to how we use a babel plugin for JS content. It is called &lt;a href="https://lion-web-components.netlify.app/?path=/docs/tools-remark-extend--page"&gt;Remark extend&lt;/a&gt;. It lets us add, remove or replace sections or specific words.&lt;/p&gt;

&lt;p&gt;Remark extend needs the following content added to &lt;code&gt;.storybook/main.js&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const fs = require('fs');
const { remarkExtend } = require('remark-extend');

function isLion(filePath) {
  return filePath.indexOf('@lion/') !== -1;
}

function getLocalOverridePath(filePath, root = process.cwd()) {
  const rel = filePath.substring(filePath.indexOf('/@lion/') + 7, filePath.length - 3);
  return `${root}/packages/${rel}.override.md`;
}

module.exports = {
  [...],
  setupMdjsPlugins: (plugins, filePath) =&amp;gt; {
    if (!isLion(filePath)) {
      return plugins;
    }
    const newPlugins = [...plugins];
    const markdownIndex = newPlugins.findIndex(plugin =&amp;gt; plugin.name === 'markdown');
    const overridePaths = [`${process.cwd()}/.storybook/all.override.md`];
    overridePaths.push(getLocalOverridePath(filePath));

    let i = 0;
    for (const overridePath of overridePaths.reverse()) {
      if (fs.existsSync(overridePath)) {
        const extendMd = fs.readFileSync(overridePath, 'utf8');
        newPlugins.splice(markdownIndex, 0, {
          name: `remarkExtend${i}`,
          plugin: remarkExtend.bind({}),
          options: { extendMd, filePath, overrideFilePath: overridePath },
        });
      }
      i += 1;
    }
    return newPlugins;
  },
  [...],
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;In the code example mentioned, we have two places in where we can do overrides: &lt;code&gt;./.storybook/all.override.md&lt;/code&gt; for generic overrides and via &lt;code&gt;getLocalOverridePath&lt;/code&gt; for each component. When needed, the &lt;code&gt;rel&lt;/code&gt; needs to be the same in &lt;code&gt;lion&lt;/code&gt; and our own project to be able to override the right file.&lt;/p&gt;

&lt;p&gt;In each file we need to specify which section we want to override. We want to load &lt;code&gt;example-button&lt;/code&gt; in the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```
::addMdAfter(':root')
```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```js script
import '../example-button.js';
```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then replace each &lt;code&gt;button&lt;/code&gt; with it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```js ::replaceFrom(':root')
module.exports.replaceSection = node =&amp;gt; {
  if (node.type === 'code' &amp;amp;&amp;amp; node.value) {
    let newCode = node.value;
    newCode = newCode.replace(/&amp;lt;lion-button/g, '&amp;lt;example-button');
    node.value = newCode;
  }
  return node;
};
```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can remove content by targeting a specific heading:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```
::removeFrom('heading:has([value=Usage with native form])')
```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or we can add an extra paragraph below the content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```
::addMdAfter(':scope:last-child')
```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The documentation of &lt;a href="https://lion-web-components.netlify.app/?path=/docs/tools-remark-extend--page"&gt;Remark extend&lt;/a&gt; has many more options and insights&lt;/p&gt;

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

&lt;p&gt;Writing good extensive documentation can be hard and time consuming. Being able to extend both code (components) and documentation will increase your work speed.&lt;/p&gt;

&lt;p&gt;We set up and adjusted the documentation to fit our extended component. please &lt;a href="https://github.com/ing-bank/lion/#user-content-contact"&gt;contact us&lt;/a&gt; if this article doesn’t answer your questions.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Solid Start</title>
      <dc:creator>Erik Kroes</dc:creator>
      <pubDate>Tue, 04 Aug 2020 10:18:44 +0000</pubDate>
      <link>https://forem.com/erikkroes/solid-start-2cpb</link>
      <guid>https://forem.com/erikkroes/solid-start-2cpb</guid>
      <description>&lt;p&gt;Are you a person that makes digital things for other people? Awesome—because this page is all about making things for people. There are four ways you can improve your creation for everybody. All four are testable, fixable and they improve usability for everybody.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is a copy of &lt;a href="https://www.solidstart.info/"&gt;solidStart.info&lt;/a&gt; and might be less up-to-date. It's meant as a resource to be shared with others. Thanks for taking it to heart!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
Four things to get started
    &lt;ol&gt;
      &lt;li&gt;Keyboard&lt;/li&gt;
      &lt;li&gt;Contrast&lt;/li&gt;
      &lt;li&gt;Alternatives&lt;/li&gt;
      &lt;li&gt;Sizing&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Inclusive Design&lt;/li&gt;
  &lt;li&gt;Contributions&lt;/li&gt;
  &lt;li&gt;Resources&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="four-things"&gt;Four things to get started&lt;/h2&gt;

&lt;p&gt;There is one big assumption in this guide. It assumes you know the basics of your tools. Validate your code.&lt;/p&gt;

&lt;h3 id="keyboard"&gt;1. Keyboard&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;You are not building for you.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not everybody uses a mouse, so you shouldn’t test with just a mouse. The most universal device to test with is a keyboard. A lot of people either use a keyboard, or use something that interacts with your creation like a keyboard.&lt;/p&gt;

&lt;p&gt;Pressing the Tab key should take you to every interactive element in an intuitive order. Pressing Shift+Tab should take you the opposite way. If you can reach &lt;strong&gt;and&lt;/strong&gt; use every bit of functionality, you’re off to a good start.&lt;/p&gt;

&lt;p&gt;People might feel lost when they don’t know where they are. Make sure it is clear which element is focused.&lt;/p&gt;

&lt;h3 id="contrast"&gt;2. Contrast&lt;/h3&gt;

&lt;p&gt;It can be hard to communicate if your content isn’t visible to people. Contrast can help with this. &lt;/p&gt;

&lt;p&gt;There are many tools to measure contrast by providing a ratio. The &lt;a href="https://developer.paciellogroup.com/resources/contrastanalyser/"&gt;Color Contrast Analyser&lt;/a&gt; is used by a lot of people. You can also pick a tool from the resources, or one that might already be inside your favorite environment. Each tool will give you a contrast ratio between two colors, like a foreground and background color. The visibility of a higher contrast ratio is better. Pure black and white can be too harsh for people.&lt;/p&gt;

&lt;p&gt;User interface components and states should have a contrast ratio of at least &lt;strong&gt;3.0:1&lt;/strong&gt;. Measure this ratio against their surrounding colors. The contrast ratio of large text (at least 24px, or at least 19px and bold) should be &lt;strong&gt;3.0:1&lt;/strong&gt; or more. All other text should be at least &lt;strong&gt;4.5:1&lt;/strong&gt;. These are minimum requirements, not goals.&lt;/p&gt;

&lt;h3 id="alternatives"&gt;3. Alternatives&lt;/h3&gt;

&lt;p&gt;Ever tried to watch a movie in a busy place, or listen to a podcast without headphones? When you can’t see or hear, a text is a nice alternative to have! &lt;/p&gt;

&lt;p&gt;Offer captions for video. Offer a transcript for podcasts. For images, offer text alternatives. Text alternatives should convey the purpose of the image or the content of the image. A decorative image needs no alternative.&lt;/p&gt;

&lt;h3 id="sizing"&gt;4. Sizing&lt;/h3&gt;

&lt;p&gt;Compare a mobile phone to a tablet, a laptop or a PC. No screen size is the same. Make sure that what you make offers the same content and functionality to all sizes. Let people experience it at whatever size they want or need.&lt;/p&gt;

&lt;h2 id="inclusive-design"&gt;Inclusive Design&lt;/h2&gt;

&lt;p&gt;Congratulations! Follow these steps and you're helping a lot of people. &lt;/p&gt;

&lt;p&gt;This is also just a first step, and there’s more you can do. Want to know more about Inclusive Design and WCAG (Web Content Accessibility Guidelines)? Check the resources!&lt;/p&gt;

&lt;h2 id="contributions"&gt;Contributions&lt;/h2&gt;

&lt;p&gt;This page is not a collaboration without contributions. It has been created by Erik Kroes with the help of Eric Bailey, Ashley Bischoff, Eric Eggert, Pascal Schilp and others. Your help can make it even better. Create inclusively.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Contribute on &lt;a href="https://github.com/erikkroes/solidStart"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Join a weekly accessibility stream on &lt;a href="https://twitch.tv/erikKroes"&gt;Twitch&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Follow on &lt;a href="https://twitter.com/erikKroes"&gt;Twitter&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="resources"&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.w3.org/WAI/WCAG21/quickref/"&gt;WCAG Quick Reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.paciellogroup.com/resources/contrastanalyser/"&gt;Color Contrast Analyser&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://contrast-grid.eightshapes.com/"&gt;Contrast Grid&lt;/a&gt; - A great tool for color palettes&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.w3.org/WAI/tutorials/images/decision-tree/"&gt;An alt Decision Tree&lt;/a&gt; - A W3C tool to determine the type of text alternative for images.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://webaim.org/projects/million/"&gt;The WebAIM Million&lt;/a&gt; - An annual accessibility analysis of the top 1,000,000 home pages&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.deque.com/axe/"&gt;Axe&lt;/a&gt; - An open source automated tool for testing partial web accessibility. Great for learning and awareness.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dequeuniversity.com/screenreaders/"&gt;Screen Reader Reference&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="courses"&gt;Courses&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.udacity.com/course/web-accessibility--ud891"&gt;Web Accessibility by Google at Udacity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.futurelearn.com/courses/digital-accessibility"&gt;Digital Accessibility by University of Southampton at Future Learn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.edx.org/course/information-and-communication-technology-ict-acces"&gt;ICT Accessibility by Georgia Tech at edX&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>html</category>
      <category>a11y</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Accessible HTML Toggle Button (Switch)</title>
      <dc:creator>Erik Kroes</dc:creator>
      <pubDate>Mon, 29 Jun 2020 10:34:40 +0000</pubDate>
      <link>https://forem.com/erikkroes/accessible-html-toggle-button-switch-o9e</link>
      <guid>https://forem.com/erikkroes/accessible-html-toggle-button-switch-o9e</guid>
      <description>&lt;p&gt;Everybody loves toggle switch on mobile, or so I've heard. But if you're building a website, how do you reproduce this without excluding people.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Originally posted on erikKroes.nl. Questions are also welcome on Twitter or Twitch (I stream about accessibility weekly).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The result
&lt;/h2&gt;

&lt;p&gt;Let's start with the most important part. This is the end result as featured on Codepen:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  What is this?
&lt;/h2&gt;

&lt;p&gt;When I use my phone, I expect a &lt;a href="https://developer.android.com/reference/android/widget/Switch"&gt;Switch&lt;/a&gt; (that's how android calls them) to instantly change a setting. It won't just be selecting an option (like with a checkbox) but the selection will also be submitted instantly.&lt;br&gt;
The web is full of examples on how to style checkboxes to look like a switch, but that doesn't help me much further when I want something more like mobile.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bit by bit
&lt;/h2&gt;

&lt;h3&gt;
  
  
  HTML
&lt;/h3&gt;

&lt;p&gt;Looking at the HTML code, you might first notice the &lt;code&gt;label&lt;/code&gt;. By default, a button will take its contents to create an &lt;a href="https://developer.paciellogroup.com/blog/2017/04/what-is-an-accessible-name/"&gt;accessible name&lt;/a&gt;. Using a &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; and referencing it by using &lt;code&gt;for=&lt;/code&gt; and the id of the &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;, overrides this default behaviour. The content of the &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; becomes the accessible name of the &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;.&lt;br&gt;
It also makes sure that people can click, press, touch or lick the &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; to activate the resulting Switch, just like on Android.&lt;/p&gt;

&lt;p&gt;Then the radical part of this creation, I'm using a &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;. Why? Because I want something to change instantly which a checkbox (&lt;code&gt;&amp;lt;input type=checkbox&amp;gt;&lt;/code&gt;) really should not be doing. In my experience, checkboxes that change things often clash with &lt;a href="https://www.w3.org/WAI/WCAG21/Understanding/on-focus.html"&gt;WCAG Criterion 3.2.1: On Focus&lt;/a&gt;. A &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; aligns better with the goal of instant change.&lt;/p&gt;

&lt;p&gt;The first attribute is &lt;code&gt;type=button&lt;/code&gt;. This should not matter, because we override the semantics later with a &lt;code&gt;role&lt;/code&gt;, but we sure don't want this to be a submit button.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;id&lt;/code&gt; is needed to create a programmatic relationship between the &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; and the &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;. Not doing so would clash with &lt;a href="https://www.w3.org/WAI/WCAG21/Understanding/info-and-relationships.html"&gt;WCAG Criterion 1.3.1: Info and Relationships&lt;/a&gt;, would pretty much defeat the purpose of the &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; in the first place, and should properly annoy people that use assistive technology (voice commands, screen readers, and more).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;role="switch"&lt;/code&gt; is where much of the magic happens. It is a &lt;a href="https://www.w3.org/TR/wai-aria-1.1/#switch"&gt;WAI-ARIA Attribute&lt;/a&gt;. It can communicate semantics that might not be natively present within HTML, and &lt;a href="https://www.w3.org/TR/using-aria/#rule1"&gt;should be used as little as possible&lt;/a&gt;. A Switch like this is a perfect example for such a use case.&lt;/p&gt;

&lt;p&gt;Whenever you use the &lt;code&gt;role="switch"&lt;/code&gt;, there is another required &lt;a href="https://www.w3.org/TR/wai-aria-1.1/#switch"&gt;WAI-ARIA Attribute&lt;/a&gt;. You have to add &lt;code&gt;aria-checked&lt;/code&gt; which takes either a true or false value. This makes sure that you're not just communicating the name and role in code, but also the value of the Switch (on or off). This helps you pass &lt;a href="https://www.w3.org/WAI/WCAG21/Understanding/name-role-value.html"&gt;WCAG Criterion 4.1.2: Name, Role, Value&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Then within the &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; we have 2 &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt;s. They toggle visibly between on and off. If there's one thing that really annoys me with switches; it's how confusing they can be. They're like the USB-plug of HTML. I often have to turn them on and off a few times before I understand which settings is which. That's why we communicate the state in the code (with &lt;code&gt;aria-checked&lt;/code&gt;), by changing colour between grey and green, and by switching between the 'on' and 'off' visual label.&lt;/p&gt;

&lt;h3&gt;
  
  
  CSS
&lt;/h3&gt;

&lt;p&gt;The CSS is about as minimal as I thought would be possible. It makes everything nice and rounded. It does not make it animated, or possible to slide between 'on' and 'off'. But feel free to add that yourself. The colours should meet the WCAG contrast requirements though.&lt;/p&gt;

&lt;p&gt;The CSS does make sure that in 1 state, the first &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; in the &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; has the same color for text and background. And in the other state, the second &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; has those colours. This way it looks like the text disappears, but that's only visual.&lt;/p&gt;

&lt;h3&gt;
  
  
  JavaScript
&lt;/h3&gt;

&lt;p&gt;The JavaScript finds the button in the code, adds an eventListener to it and makes &lt;code&gt;aria-checked&lt;/code&gt; toggle between 'true' and 'false'. It could also remove the &lt;code&gt;aria-checked&lt;/code&gt; instead of toggle to 'false'. I chose not to, to make the code slightly more readable and less bloated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;p&gt;A lot of this component was based on &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/Switch_role"&gt;the example of MDN&lt;/a&gt;. It's a great resource and starting point for everybody.&lt;br&gt;
If you want to get more technical than this writing, you could look at &lt;a href="https://scottaohara.github.io/a11y_styled_form_controls/"&gt;Scott O'Hara&lt;/a&gt;, who has written a great deal more about the subject. Thanks for that!&lt;/p&gt;

&lt;p&gt;And please ask me anything about Accessibility! You are also welcome on &lt;a href="https://twitter.com/erikKroes"&gt;Twitter&lt;/a&gt; or &lt;a href="https://twitch.tv/erikKroes"&gt;Twitch&lt;/a&gt; (I stream about accessibility weekly.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>html</category>
      <category>a11y</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Guide to Accessible Web Components</title>
      <dc:creator>Erik Kroes</dc:creator>
      <pubDate>Wed, 24 Jun 2020 07:31:33 +0000</pubDate>
      <link>https://forem.com/erikkroes/the-guide-to-accessible-web-components-1mkd</link>
      <guid>https://forem.com/erikkroes/the-guide-to-accessible-web-components-1mkd</guid>
      <description>&lt;p&gt;Web Components are a newly supported standard. They're a great match for Design Systems because they're futureproof and work with any framework. Building proper UI Web Components can be quite a task though, especially if you want them to be accessible. Here are some pointers on what to look out for.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Originally posted on &lt;a href="https://www.erikkroes.nl/"&gt;erikKroes.nl&lt;/a&gt;. Questions are also welcome on &lt;a href="https://twitter.com/erikKroes"&gt;Twitter&lt;/a&gt; or &lt;a href="https://twitch.tv/erikKroes/"&gt;Twitch&lt;/a&gt; (I stream about accessibility weekly).&lt;/p&gt;

&lt;p&gt;Throughout this article I'll use &lt;a href="https://github.com/ing-bank/lion"&gt;Lion&lt;/a&gt; a few times as an example. Lion is a collection of white label UI Web Components. There's more information about Lion in the conclusion.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id="contents"&gt;Contents&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What are Web Components?&lt;/li&gt;
&lt;li&gt;What is shadow DOM, and light DOM?&lt;/li&gt;
&lt;li&gt;Extending elements&lt;/li&gt;
&lt;li&gt;
Accessible UI Components

&lt;ul&gt;
&lt;li&gt;Focusable&lt;/li&gt;
&lt;li&gt;Keyboard interaction&lt;/li&gt;
&lt;li&gt;Visible states&lt;/li&gt;
&lt;li&gt;Functional states and properties&lt;/li&gt;
&lt;li&gt;Semantics&lt;/li&gt;
&lt;li&gt;Accessible name&lt;/li&gt;
&lt;li&gt;Relationships&lt;/li&gt;
&lt;li&gt;Global standards and conventions&lt;/li&gt;
&lt;li&gt;Browser bugs and variations&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;The Accessibility Object Model&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;li&gt;Further reading&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="what-are-wc"&gt;What are Web Components?&lt;/h2&gt;

&lt;p&gt;Web Components are a set of standards:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://w3c.github.io/webcomponents/spec/custom/"&gt;Custom Elements&lt;/a&gt;: A way to create your own HTML elements&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/"&gt;ES Modules&lt;/a&gt;: Self-contained modules of JavaScript code that can be reused and extended&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://html.spec.whatwg.org/multipage/scripting.html#the-template-element"&gt;HTML Templates&lt;/a&gt;: Reusable fragments of DOM&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://polymer-library.polymer-project.org/3.0/docs/devguide/shadow-dom"&gt;Shadow DOM&lt;/a&gt;: Encapsulation of DOM&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together these standards enable "Reusable extendable encapsulated self-contained components for the web". That's quite a mouthful, but not very clear.&lt;/p&gt;

&lt;p&gt;In practice, this means you can create your own HTML elements. These elements have their own bit of encapsulated DOM.  In this, and many web-related cases, DOM stands for Document Object Model. The DOM is how we see an HTML or XML document. MDN states "The DOM represents the document as nodes and objects."  MDN has a rather &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction"&gt;good explanation&lt;/a&gt;.&lt;br&gt;
It means the HTML element you make can't be touched or influenced by whatever is outside of the element. They can't be accidentally styled, and they won't mess with your global styles either. And because it's an ES Module, the whole element can be distributed and extended. All these aspects together make up a Web Component. &lt;br&gt;
ES Module stands for EcmaScript Module. It's how JavaScript works with modules and a standard that's &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules#browser_support"&gt;supported by all modern browsers&lt;/a&gt;. 🎉&lt;/p&gt;

&lt;p&gt;A practical example would be a &lt;a href="https://github.com/keanulee/good-map"&gt;Google Maps Web Component&lt;/a&gt;. This Web Component shows a full interactive map on your page with only a few lines of code. You would have to import some JavaScript on your page that defines the component:&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;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"good-map.js"&lt;/span&gt; &lt;span class="na"&gt;async&lt;/span&gt; &lt;span class="na"&gt;defer&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, you can use your custom element anywhere on the page.&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;good-map&lt;/span&gt; &lt;span class="na"&gt;api-key=&lt;/span&gt;&lt;span class="s"&gt;"AIzaSyAQuo91bcoB-KwWXaANroTrzpNZRFcNJ1k"&lt;/span&gt;
    &lt;span class="na"&gt;latitude=&lt;/span&gt;&lt;span class="s"&gt;"52.1664"&lt;/span&gt;
    &lt;span class="na"&gt;longitude=&lt;/span&gt;&lt;span class="s"&gt;"5.9075"&lt;/span&gt; &lt;span class="na"&gt;zoom=&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/good-map&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how the element name has a dash? That's part of the Custom Elements specification and makes it easier for the browser to recognize them.&lt;/p&gt;

&lt;p&gt;A not so practical example would be a &lt;a href="https://github.com/erikkroes/spacer-gif"&gt;spacer-gif&lt;/a&gt; Web Component. (A spacer-gif is an old an redundant technique that does not need a remake.)&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;spacer-gif&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/spacer-gif&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A Lion example could be &lt;a href="https://lion-web-components.netlify.com/?path=/docs/buttons-switch--default-off"&gt;&lt;code&gt;lion-switch&lt;/code&gt;&lt;/a&gt;.&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;lion-switch&lt;/span&gt; &lt;span class="na"&gt;label=&lt;/span&gt;&lt;span class="s"&gt;"Label Text"&lt;/span&gt; &lt;span class="na"&gt;help-text=&lt;/span&gt;&lt;span class="s"&gt;"Help text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/lion-switch&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And all that goodness is based on widely supported web standards.&lt;/p&gt;

&lt;h2 id="what-is-shadow-dom"&gt;What is shadow DOM, and light DOM?&lt;/h2&gt;

&lt;p&gt;"Indeed, that sounds pretty good so far, but what's the catch?"&lt;/p&gt;

&lt;p&gt;As the British will soon discover, there are some downsides to isolating yourself.  Let's say you make a card component. The interface for using it (what you see in your editor or browser) could look 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;my-card&amp;gt;&lt;/span&gt;This is the card content&lt;span class="nt"&gt;&amp;lt;/my-card&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The component, when inspected in the browser, could look 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;my-card&amp;gt;&lt;/span&gt;
    #shadow-root (open)
      &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;"card-wrapper"&lt;/span&gt;&lt;span class="nt"&gt;&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;"card-header"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          Presenting the card content:
        &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;"card-content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;slot&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;#text&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;↴
          &lt;span class="nt"&gt;&amp;lt;/slot&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&amp;gt;&lt;/span&gt;

    This is the card content
  &lt;span class="nt"&gt;&amp;lt;/my-card&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A whole chunk of DOM ("The DOM represents the document as nodes and objects." Remember from before?) is rendered by the component and put into the shadow-root section. Inside the &lt;code&gt;&amp;lt;slot&amp;gt;&lt;/code&gt; it refers to the content we put into the element in the first place. All the DOM that is added, is shadow DOM. All the other "normal" DOM, is what we call light DOM. It's the part that's always visible.&lt;br&gt;
As the shadow DOM is completely encapsulated and isolated, it is also completely disconnected. It's almost like it's a completely different document like an iframe.  Thankfully, keyboard navigation does work through Shadow DOM boundaries. Which means you can &lt;code&gt;&amp;lt;TAB&amp;gt;&lt;/code&gt; in and out of Shadow DOM.&lt;/p&gt;

&lt;p&gt;This becomes a challenge when you want to point a label to an input to create an explicit relationship. In plain HTML, this would be:&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;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"example-input"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Label text&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;id=&lt;/span&gt;&lt;span class="s"&gt;"example-input"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When one of both (the &lt;code&gt;label&lt;/code&gt; or the &lt;code&gt;input&lt;/code&gt;) is in the shadow DOM, they're in a completely different context. This makes it impossible to refer to eachother.&lt;br&gt;
This same dillema also goes for WAI-ARIA attributes like &lt;code&gt;aria-labelledby&lt;/code&gt;, &lt;code&gt;aria-describedby&lt;/code&gt; and other that reference an ID. You need either both elements in the shadow DOM, or both of them in the light DOM. Light DOM does not mean that they both have to be in the same slot though. Light DOM is basically all the DOM that isn't shadow DOM.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://lion-web-components.netlify.com/?path=/story/forms-input--label"&gt;&lt;code&gt;lion-input&lt;/code&gt;&lt;/a&gt; we let the developer declare a label in the label slot. This label ends up in the light DOM.&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;lion-input&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;slot=&lt;/span&gt;&lt;span class="s"&gt;"label"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Label text&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/lion-input&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The component places an input in a &lt;code&gt;slot="input"&lt;/code&gt;, help text in &lt;code&gt;slot="help-text"&lt;/code&gt; and feedback in &lt;code&gt;slot="feedback"&lt;/code&gt;. This means the input can be connected to the label, but also that we can use &lt;code&gt;aria-describedby&lt;/code&gt; to connect the input to help text like instructions and feedback like error messages.&lt;/p&gt;

&lt;h2 id="extending-elements"&gt;Extending elements&lt;/h2&gt;

&lt;p&gt;As it stands right now, it is only possible to create a Web Component by extending a generic HTML element (&lt;code&gt;HTMLElement&lt;/code&gt;) or another Web Component (which should be somewhere deep down, also an extension of &lt;code&gt;HTMLElement&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;For accessibility, it could have been a big win if we could extend any element. Imagine you could, for example, extend a native button (&lt;code&gt;HTMLButtonElement&lt;/code&gt;). You would inherit all its behaviour and it's semantics, and you would only add on to that. You'd have a solid fundament upon which you could build. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z2IvJ_-0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.erikkroes.nl/wp-content/uploads/2020/02/dragons-940x932.jpg.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z2IvJ_-0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.erikkroes.nl/wp-content/uploads/2020/02/dragons-940x932.jpg.webp" alt="4 panel comic. Panel 1 a Little kid on santas lap says: For Christmas I want a dragon. Panel 2 Santa replies: Be realistic. Panel 3 Little kid reconsiders: semantic HTML everywhere. Panel 4 Santa holds a paper to start writing and asks: What color do you want for your dragon? Girl replies: red" width="800" height="793"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/w3c/webcomponents/issues/509"&gt;specification&lt;/a&gt; exists but Safari &lt;a href="https://github.com/w3c/webcomponents/issues/509#issuecomment-230700060"&gt;has stated&lt;/a&gt; to not support this feature. Part of the beauty of Web Components is that it's a supported standard. So even though there is a &lt;a href="https://github.com/ungap/custom-elements-builtin"&gt;Polyfill&lt;/a&gt; for Safari, it creates a path with future uncertainty.&lt;/p&gt;

&lt;h2 id="accessible-ui-components"&gt;Accessible UI Components&lt;/h2&gt;

&lt;p&gt;The most popular usecase for Web Components is probably that of creating custom user interface controls. As we can't extend any native elements, we often end up with either wrapping a native element, or recreating its behaviour by ourselves. Wrapping is often the easiest and most solid solution. Recreating is basically the same as taking a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; as a starting point.&lt;br&gt;
There are so many aspects that come together in a single components, that it is really easy to overlook a feature or behaviour. And when you forget or fail to implement something, you end up creating something that's lacking compared to a native element. That's probably the exact opposite of what you're trying to achieve.&lt;/p&gt;

&lt;p&gt;Here is an overview of aspects that need special attention when creating an accessible user interface control. These points are not specific to Web Components. They are just as relevent for React, Vue, Svelte or any other framework.&lt;/p&gt;

&lt;h3 id="focusable"&gt;Focusable&lt;/h3&gt;

&lt;p&gt;If your custom control is interactive, make sure it is keyboard focusable. For simple controls with a single interactive element, this means adding &lt;code&gt;tabindex='0'&lt;/code&gt; to your control. For more complex controls you might need to implement a &lt;a href="https://developers.google.com/web/fundamentals/accessibility/focus/using-tabindex#managing_focus_in_components"&gt;roving tabindex&lt;/a&gt; or use &lt;a href="https://www.w3.org/TR/wai-aria/#aria-activedescendant"&gt;&lt;code&gt;aria-activedescendant&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id="keyboard-interaction"&gt;Keyboard interaction&lt;/h3&gt;

&lt;p&gt;Users should be able to use your interactive control with a keyboard. For many design patterns, suggested keyboard interactions can be found in the &lt;a href="https://www.w3.org/TR/wai-aria-practices/"&gt;WAI ARIA Authoring Practices&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id="visible-states"&gt;Visible states&lt;/h3&gt;

&lt;p&gt;Interactive controls have several states like focus, hover and active. These should all be clearly visible, and, preferably, each have their own distinctive styling.&lt;/p&gt;

&lt;h3 id="states-and-properties"&gt;Functional states and properties&lt;/h3&gt;

&lt;p&gt;An interactive control can have functional states as well. For example, a disclosure widget (or expandable, accordion, expando, ...) can be open or closed. This state needs to be not just visual, but communicated in code as well. This can be done by toggling  &lt;a href="https://www.w3.org/TR/wai-aria-1.1/#aria-expanded"&gt;&lt;code&gt;aria-expanded&lt;/code&gt;&lt;/a&gt; on your control. &lt;br&gt;
The same goes for properties like &lt;a href="https://www.w3.org/TR/wai-aria-1.1/#aria-multiline"&gt;&lt;code&gt;aria-multiline&lt;/code&gt;&lt;/a&gt;. They communicate properties that might be implicit in native elements, that have to be added manually for assistive technology when you're building custom controls. WAI-ARIA has many &lt;a href="https://www.w3.org/TR/wai-aria-1.1/#aria-multiline"&gt;states and properties&lt;/a&gt; to aid in this.&lt;/p&gt;

&lt;h3 id="semantics"&gt;Semantics&lt;/h3&gt;

&lt;p&gt;Native HTML elements have a semantic meaning and are &lt;a href="https://www.w3.org/TR/html-aam-1.0/#html-element-role-mappings"&gt;mapped to WAI-ARIA roles&lt;/a&gt;. Their semantics are implicit and always there.&lt;br&gt;
A custom element starts out with no role at all, but you can assign one explicitly. WAI-ARIA offers a wide range of &lt;a href="https://www.w3.org/TR/wai-aria-1.1/#role_definitions"&gt;roles&lt;/a&gt; that should cover all use cases. WAI ARIA is more explicit than native semantics though. It's more bolt-on than built-in.&lt;br&gt;
You might notice when using Windows High Contrast Mode, a special tool for Windows. It &lt;a href="https://www.scottohara.me/blog/2019/02/12/high-contrast-aria-and-images.html#whcm-cares-not-for-your-aria-attributes"&gt;does not care for your ARIA attributes&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id="accessible-name"&gt;Accessible name&lt;/h3&gt;

&lt;p&gt;Interactive controls must have a name for them to be identified by. For example, a &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; with the text "Save" can be presented by assistive technology as "Save, button". In this case "Save" is the accessible name of the element. The name is determined by the &lt;a href="https://www.w3.org/TR/html-aam-1.0/#accessible-name-and-description-computation"&gt;Accessible Name and Description Calculation&lt;/a&gt; and there are &lt;a href="https://developer.paciellogroup.com/blog/2017/04/what-is-an-accessible-name/"&gt;multiple ways of adding an accessible name&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id="relationships"&gt;Relationships&lt;/h3&gt;

&lt;p&gt;Visually, it might be clear that certain elements have a relationship. For example, a short text next to an input will likely be the label of that input. Not clarifying those relationships in code can make it impossible for assistive technology to recognize them though. WCAG Success Criterion 1.3.1 mentions quite some &lt;a href="https://www.w3.org/WAI/WCAG21/Understanding/info-and-relationships.html#sufficient"&gt;sufficient techniques&lt;/a&gt; to cover this issue.&lt;/p&gt;

&lt;h3 id="standards-and-conventions"&gt;Global standards and conventions&lt;/h3&gt;

&lt;p&gt;Creating custom elements requires awareness of global standards and conventions. Users expect components to work in a certain way. Reinventing the wheel often leads to a confusing user experience. Following standards and conventions will prevent confusion and create a consistent experience for users.&lt;/p&gt;

&lt;h3 id="browser-bugs"&gt;Browser bugs and variations&lt;/h3&gt;

&lt;p&gt;To create an element that works the same way on each browser and platform is a big challenge. Some native elements even fail to do so. For example, when I use a &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; in Firefox on Mac OS, it will behave differently from when I open it in Chrome. There will even be a difference between Chrome on Mac OS and Chrome on Windows. The nuances and details of making elements work consistently across platforms is a really big challenge.&lt;br&gt;
Bugs can be even harder to find or circumvent. For example, the &lt;a href="https://www.w3.org/TR/wai-aria-practices/"&gt;WAI ARIA Authoring Practices 1.1&lt;/a&gt; recommends using &lt;code&gt;aria-activedescendant&lt;/code&gt; to control focus when using a &lt;code&gt;role="combobox"&lt;/code&gt;. That sounds great, untill you discover that this combination doesn't actually work in all browsers.&lt;/p&gt;

&lt;h2 id="aom"&gt;The Accessibility Object Model&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/WICG/aom"&gt;Accessibility Object Model&lt;/a&gt; (AOM) is a proposed addition to the web platform to make the accessibility API of browsers more transparant and usable for developers. Support for the AOM in browsers would be of great value for Web Components. But as it is still under development and largely unsupported, I'll leave further explanation to others like &lt;a href="https://hiddedevries.nl/en/blog/2019-07-22-meaning-without-markup-accessibility-object-model"&gt;Hidde de Vries&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V0zjcOjm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.erikkroes.nl/wp-content/uploads/2020/02/robust-fix-of-an-issue.jpeg.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V0zjcOjm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.erikkroes.nl/wp-content/uploads/2020/02/robust-fix-of-an-issue.jpeg.webp" alt="Electric wiring outdoors, covered with a little paper umbrella" width="540" height="720"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;It is very much possible to create accessible Web Components. They are ideal for large organizations where a specialized team can make the best building blocks, and give both their developers and users a great consistent experience. It takes a lot of time, knowledge and effort to build these components though. If you'd ask me...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Everybody should use Web Components&lt;br&gt;
Few people should build them&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To ease some of that pain, the Web Components I work on professionaly have an open source base layer called Lion. This is a collection of white-label Web Components that you can easily extend, style and customize. They have been built with all the considerations mentioned above. You can view a &lt;a href="http://lion-web-components.netlify.com/"&gt;live demo&lt;/a&gt; of all the components, or check them out on &lt;a href="https://github.com/ing-bank/lion"&gt;GitHub&lt;/a&gt;. If you find anything that could be improved, please create an issue and maybe even fix it yourself. All accessibility issues are my responsibility.&lt;/p&gt;

&lt;h2 id="further-reading"&gt;Further reading&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/thepassle/web-components-from-zero-to-hero-4n4m"&gt;Web Components: from zero to hero&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://open-wc.org/"&gt;open-wc - Open Web Component Recommendations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.24a11y.com/2019/web-components-and-the-aom/"&gt;Web Components and the AOM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marcysutton.github.io/accessibility-of-web-components/"&gt;The Accessibility of Web Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.paciellogroup.com/blog/2014/09/web-components-punch-list/"&gt;Web Components Punch List&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.24a11y.com/2018/web-components-still-need-to-be-accessible/"&gt;Web Components still need to be accessible&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://brucelawson.github.io/talks/2014/parisweb/index.html"&gt;Web Components - The Right Way&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://adrianroselli.com/2019/08/basic-custom-control-requirements.html"&gt;Basic custom control requirements&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And please ask me anything about Accessibility! You are also welcome on &lt;a href="https://twitter.com/erikKroes"&gt;Twitter&lt;/a&gt; or &lt;a href="https://twitch.tv/erikKroes/"&gt;Twitch&lt;/a&gt; (I stream about accessibility weekly.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>html</category>
      <category>a11y</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
