<?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: Michaël Vanderheyden</title>
    <description>The latest articles on Forem by Michaël Vanderheyden (@th3s4mur41).</description>
    <link>https://forem.com/th3s4mur41</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%2F289330%2F9c66b8a2-69c5-431d-bc77-ede880958302.jpg</url>
      <title>Forem: Michaël Vanderheyden</title>
      <link>https://forem.com/th3s4mur41</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/th3s4mur41"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>Michaël Vanderheyden</dc:creator>
      <pubDate>Wed, 15 Apr 2026 13:14:59 +0000</pubDate>
      <link>https://forem.com/th3s4mur41/-21fg</link>
      <guid>https://forem.com/th3s4mur41/-21fg</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/mfairchild365/embedding-accessibility-into-ai-based-software-development-282k" class="crayons-story__hidden-navigation-link"&gt;Embedding Accessibility into AI based software development&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/mfairchild365" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F152506%2F86319f69-42bd-469e-8c09-996986a2d551.jpeg" alt="mfairchild365 profile" class="crayons-avatar__image" width="460" height="460"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/mfairchild365" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Michael Fairchild
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Michael Fairchild
                
              
              &lt;div id="story-author-preview-content-3344524" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/mfairchild365" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F152506%2F86319f69-42bd-469e-8c09-996986a2d551.jpeg" class="crayons-avatar__image" alt="" width="460" height="460"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Michael Fairchild&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/mfairchild365/embedding-accessibility-into-ai-based-software-development-282k" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 12&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/mfairchild365/embedding-accessibility-into-ai-based-software-development-282k" id="article-link-3344524"&gt;
          Embedding Accessibility into AI based software development
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/a11y"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;a11y&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/llm"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;llm&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/benchmark"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;benchmark&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/mfairchild365/embedding-accessibility-into-ai-based-software-development-282k" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;27&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/mfairchild365/embedding-accessibility-into-ai-based-software-development-282k#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              2&lt;span class="hidden s:inline"&gt; comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Michaël Vanderheyden</dc:creator>
      <pubDate>Thu, 26 Mar 2026 16:45:47 +0000</pubDate>
      <link>https://forem.com/th3s4mur41/-4lce</link>
      <guid>https://forem.com/th3s4mur41/-4lce</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/stuffbreaker/how-declarative-custom-elements-dce-could-improve-web-components-53eg" class="crayons-story__hidden-navigation-link"&gt;How Declarative Custom Elements (DCE) Could Improve Web Components&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/stuffbreaker" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F87382%2F524f7820-0def-4bf8-bea4-2beaf247d75d.jpeg" alt="stuffbreaker profile" class="crayons-avatar__image" width="400" height="400"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/stuffbreaker" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Burton Smith
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Burton Smith
                
              
              &lt;div id="story-author-preview-content-3033126" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/stuffbreaker" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F87382%2F524f7820-0def-4bf8-bea4-2beaf247d75d.jpeg" class="crayons-avatar__image" alt="" width="400" height="400"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Burton Smith&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/stuffbreaker/how-declarative-custom-elements-dce-could-improve-web-components-53eg" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 24&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/stuffbreaker/how-declarative-custom-elements-dce-could-improve-web-components-53eg" id="article-link-3033126"&gt;
          How Declarative Custom Elements (DCE) Could Improve Web Components
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/html"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;html&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javavscript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javavscript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webcomponents"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webcomponents&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/stuffbreaker/how-declarative-custom-elements-dce-could-improve-web-components-53eg" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;5&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/stuffbreaker/how-declarative-custom-elements-dce-could-improve-web-components-53eg#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              1&lt;span class="hidden s:inline"&gt; comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            8 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>html</category>
      <category>javavscript</category>
      <category>webcomponents</category>
    </item>
    <item>
      <title>Making Scrollable Code Blocks Accessible</title>
      <dc:creator>Michaël Vanderheyden</dc:creator>
      <pubDate>Fri, 20 Feb 2026 11:59:17 +0000</pubDate>
      <link>https://forem.com/th3s4mur41/making-scrollable-code-blocks-accessible-3i0o</link>
      <guid>https://forem.com/th3s4mur41/making-scrollable-code-blocks-accessible-3i0o</guid>
      <description>&lt;p&gt;When you work on the web long enough, you get used to browsers disagreeing on the small things. But sometimes those “small things” quietly break accessibility in ways that aren’t obvious until you test with a keyboard.&lt;/p&gt;

&lt;p&gt;This is exactly what happened with scrollable elements.&lt;/p&gt;

&lt;p&gt;Most browsers like Chrome and Firefox automatically make scrollable regions keyboard‑focusable. That means if the content overflows, a keyboard user can tab into it and scroll through the content using the arrow keys. It’s intuitive, consistent, and aligns with WCAG’s requirement that scrollable regions must be keyboard accessible.&lt;br&gt;
Safari, however, doesn't follow this behavior. There's a long‑standing &lt;a href="https://bugs.webkit.org/show_bug.cgi?id=277290" rel="noopener noreferrer"&gt;bug report in WebKit Backlog&lt;/a&gt; where scrollable elements (like long code blocks or tables) do not receive keyboard focus, as reported by &lt;a href="https://adrianroselli.com/2022/06/keyboard-only-scrolling-areas.html" rel="noopener noreferrer"&gt;Adrian Roselli&lt;/a&gt;, making them inaccessible to keyboard users.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0sqa5bb62j99a9eaq9m0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0sqa5bb62j99a9eaq9m0.png" alt="WebKit Bug 277290" width="614" height="190"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Safari doesn’t make scrollable elements focusable
&lt;/h2&gt;

&lt;p&gt;In Safari, an element that becomes scrollable (e.g., long code snippets) does not receive focus by default. That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can see the scrollbar.&lt;/li&gt;
&lt;li&gt;You can scroll with a mouse or trackpad.&lt;/li&gt;
&lt;li&gt;But you cannot tab into it.&lt;/li&gt;
&lt;li&gt;And therefore you cannot scroll it using the keyboard.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a direct accessibility failure under &lt;a href="https://www.w3.org/WAI/WCAG22/Understanding/keyboard.html" rel="noopener noreferrer"&gt;WCAG 2.2’s Keyboard criterion&lt;/a&gt;, which states that all functionality must be operable through a keyboard interface — including scrolling inside overflow regions.&lt;br&gt;
For keyboard‑only users, this effectively traps content. They can see the beginning of the content, but not the rest.&lt;br&gt;
And because Chrome and Firefox “do the right thing,” most developers never notice the issue.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why this matters more than it seems
&lt;/h2&gt;

&lt;p&gt;Scrollable code blocks are everywhere: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Documentation sites&lt;/li&gt;
&lt;li&gt;Developer blogs&lt;/li&gt;
&lt;li&gt;Design system pages&lt;/li&gt;
&lt;li&gt;API references&lt;/li&gt;
&lt;li&gt;Tutorials&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Code blocks are usually implemented using &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; elements. The &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; element is one of the most common non-interactive elements that becomes scrollable by default because it's designed to preserve formatting and not wrap content.&lt;br&gt;
If a code block is long enough to require scrolling, it becomes inaccessible to keyboard users in Safari.&lt;/p&gt;

&lt;p&gt;If a user can’t scroll them, they can’t read them. And if they can’t read them, the content might as well not exist.&lt;br&gt;
This is one of those accessibility issues that isn’t flashy, but has a real impact on real people.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;There is a simple solution to the problem: make scrollable elements keyboard‑focusable by adding &lt;code&gt;tabindex="0"&lt;/code&gt;. This allows keyboard users to tab into the element and use arrow keys to scroll through the content.&lt;br&gt;
However, this requires developers to manually add &lt;code&gt;tabindex="0"&lt;/code&gt; to every scrollable &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; element, which is not ideal. It’s easy to forget, and it adds extra maintenance.&lt;br&gt;
Moreover, it’s not ideal to make every &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; focusable, since not all of them will be scrollable.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The polyfill is only a temporary workaround until Safari implements the expected behavior. It’s not a permanent solution, but it helps bridge the gap in the meantime.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Automatically adding tabindex="0" when needed
&lt;/h3&gt;

&lt;p&gt;To fix this gap, I created a small polyfill: &lt;a href="https://github.com/Th3S4mur41/scroll-focus-polyfill" rel="noopener noreferrer"&gt;scroll-focus-polyfill&lt;/a&gt; that is pretty easy to use by simply including it on your 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;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/scroll-focus-polyfill"&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;The idea is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detect when a &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; element becomes scrollable.&lt;/li&gt;
&lt;li&gt;Automatically add &lt;code&gt;tabindex="0"&lt;/code&gt; so it becomes keyboard-focusable.&lt;/li&gt;
&lt;li&gt;Only apply this where the behavior is not already provided by the browser.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This keeps the behavior consistent across browsers without forcing developers to manually annotate every code block.&lt;br&gt;
It’s intentionally lightweight, unobtrusive, and standards‑aligned.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why not just add &lt;code&gt;tabindex="0"&lt;/code&gt; everywhere?
&lt;/h3&gt;

&lt;p&gt;You could, but that introduces its own problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Non‑scrollable &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; elements don’t need to be in the tab order.&lt;/li&gt;
&lt;li&gt;Adding unnecessary focus targets creates noise for keyboard users.&lt;/li&gt;
&lt;li&gt;It also breaks expected semantics — not every &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; is interactive.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The polyfill only applies focusability where it's actually needed.&lt;/p&gt;
&lt;h3&gt;
  
  
  What about other scrollable elements?
&lt;/h3&gt;

&lt;p&gt;While this polyfill focuses on &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; elements by default for performance reasons, it can be configured to also apply the same logic to other elements like tables, divs with &lt;code&gt;white-space: nowrap&lt;/code&gt;, or any other scrollable container.&lt;br&gt;
For example, if you have a class &lt;code&gt;scrollable&lt;/code&gt; that prevents an element from wrapping, you can easily extend the polyfill to handle any element with that class.&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;"https://unpkg.com/scroll-focus-polyfill"&lt;/span&gt;
        &lt;span class="na"&gt;data-selectors=&lt;/span&gt;&lt;span class="s"&gt;"pre, .scrollable"&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;h2&gt;
  
  
  A subtle bug with real accessibility impact
&lt;/h2&gt;

&lt;p&gt;This is a great example of how accessibility issues often hide in the details. &lt;br&gt;
Safari’s behavior isn’t “wrong” in a spec sense — but it’s inconsistent with user expectations and with other browsers’ accessibility affordances.&lt;br&gt;
And because developers don't always test keyboard navigation explicitly in Safari, the issue slips through unnoticed.&lt;br&gt;
The polyfill bridges that gap until Safari aligns with the behavior of other engines.&lt;/p&gt;

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

&lt;p&gt;Making scrollable code blocks accessible is a small but important step towards a more inclusive web.&lt;br&gt;
By understanding the issue, implementing a simple polyfill, and advocating for better cross‑browser consistency, we can ensure that all users have equal access to content — regardless of their browser or input method.&lt;br&gt;
If you maintain a documentation site, developer blog, or any content with scrollable code blocks, consider implementing this polyfill to improve accessibility for your keyboard users. It’s a small change that can make a big difference.&lt;/p&gt;




&lt;p&gt;Join the conversation on &lt;a href="https://bsky.app/profile/th3s4mur41.me/post/3meqi7ecnjc2z" rel="noopener noreferrer"&gt;Bluesky&lt;/a&gt; or &lt;a href="https://www.linkedin.com/posts/michaelvanderheyden_making-scrollable-code-blocks-accessible-activity-7428049258546737153-_xQi" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://th3s4mur41.me/blog/scroll-focus-polyfill/" rel="noopener noreferrer"&gt;https://th3s4mur41.me&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>wcag</category>
      <category>howto</category>
      <category>keyboardnavigation</category>
    </item>
    <item>
      <title>Contrast: Beyond WCAG Compliance</title>
      <dc:creator>Michaël Vanderheyden</dc:creator>
      <pubDate>Wed, 14 Jan 2026 10:00:00 +0000</pubDate>
      <link>https://forem.com/th3s4mur41/contrast-beyond-wcag-compliance-lh8</link>
      <guid>https://forem.com/th3s4mur41/contrast-beyond-wcag-compliance-lh8</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4sc1qialqdcpaxx2s67.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4sc1qialqdcpaxx2s67.jpg" alt="Comic-style illustration of a bearded developer wearing a baseball cap and samurai-themed shirt, working on a laptop with a samurai sticker. To the side, accessibility icons and the hashtag #A11yTips promote practical accessibility tips for developers." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Contrast is one of the easiest accessibility aspects to evaluate because it can be measured with algorithms. Whether through automated tools or semi‑automatic checks, developers can quickly verify if text and background combinations meet established standards. This makes contrast a practical starting point for improving accessibility - though, as we'll see, compliance alone doesn't always guarantee the best user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  WCAG vs APCA: Understanding the Difference
&lt;/h2&gt;

&lt;p&gt;While &lt;a href="https://www.w3.org/TR/WCAG22/#contrast-minimum" rel="noopener noreferrer"&gt;WCAG guidelines&lt;/a&gt; provide a solid foundation for color contrast, strict compliance sometimes leads to suboptimal results with certain colors. Consider using the &lt;a href="https://git.apcacontrast.com/documentation/APCAeasyIntro" rel="noopener noreferrer"&gt;APCA (Accessible Perceptual Contrast Algorithm)&lt;/a&gt; as an alternative or in addition to WCAG checks. APCA offers a more nuanced approach to contrast that better reflects human perception.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fth3s4mur41.me%2F_astro%2Fcontrast-wcag-vs-apca.DU4TBag9_Z1uOBIv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fth3s4mur41.me%2F_astro%2Fcontrast-wcag-vs-apca.DU4TBag9_Z1uOBIv.png" alt="Same background, different verdicts: APCA favors readability of white text on orange background, while WCAG prefers&amp;lt;br&amp;gt;
black. A striking example of how contrast standards can diverge." width="737" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Visual clarity vs legacy metrics: Though WCAG favors black text on orange background, users often find white more&lt;br&gt;
readable. APCA captures this perceptual nuance, challenging traditional contrast assumptions.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Try the demo interactively:&lt;/p&gt;

&lt;h3&gt;WCAG Levels in Brief&lt;/h3&gt;

&lt;h3&gt;
  
  
  Real-world example: Stack Overflow
&lt;/h3&gt;

&lt;p&gt;For example, Stack Overflow recently transitioned to APCA for their accessibility design, improving readability and user experience. You can read more about their approach and lessons learned in their blog post: &lt;a href="https://stackoverflow.blog/2024/08/07/accessibility-by-design-building-interfaces-for-everyone-at-stack-overflow/" rel="noopener noreferrer"&gt;Accessibility by Design at Stack Overflow&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To keep contrast checks in their automated accessibility testing, they also built custom Axe rules that validate APCA contrast levels (instead of the traditional WCAG contrast ratio checks). That work is available publicly as &lt;a href="https://github.com/StackExchange/apca-check/tree/main" rel="noopener noreferrer"&gt;StackExchange/apca-check&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to check contrast (DevTools + quick tools)
&lt;/h2&gt;

&lt;p&gt;Even if you run automated checks, it’s useful to spot‑check contrast right in the browser while you build.&lt;/p&gt;

&lt;h3&gt;
  
  
  Chrome / Chromium-based browsers
&lt;/h3&gt;

&lt;p&gt;You can see contrast information in a few places:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the element picker (“Select an element in the page to inspect”, usually + + ) to inspect the text you care about.&lt;/li&gt;
&lt;li&gt;In the &lt;strong&gt;Styles&lt;/strong&gt; panel, open the color picker for the &lt;code&gt;color&lt;/code&gt; property; DevTools can display contrast results for the foreground/background pairing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fth3s4mur41.me%2F_astro%2Fchrome-inspect-popover.CAogomm4_Z1QFJmV.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fth3s4mur41.me%2F_astro%2Fchrome-inspect-popover.CAogomm4_Z1QFJmV.png" alt="Chrome DevTools element picker highlighting a text element and showing the inspect&amp;lt;br&amp;gt;
popover." width="178" height="254"&gt;&lt;/a&gt; &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fth3s4mur41.me%2F_astro%2Fchrome-color-picker.ChK_ceAM_Z1VOITq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fth3s4mur41.me%2F_astro%2Fchrome-color-picker.ChK_ceAM_Z1VOITq.png" alt="Chrome DevTools color picker showing contrast information for the selected foreground and background&amp;lt;br&amp;gt;
colors." width="277" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Chrome DevTools: use the element picker to target the exact text you want to evaluate, or use the&lt;br&gt;
 picker to view contrast results.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Known DevTools issue:&lt;/strong&gt; Chrome DevTools has a known issue (&lt;a href="https://crbug.com/1414206" rel="noopener noreferrer"&gt;Chromium bug 1414206&lt;/a&gt;) where contrast ratios aren’t displayed if a color is applied to an element containing children (or even a comment node). Until it’s fixed, check contrast directly on the actual text node(s), or use an external checker.&lt;/p&gt;

&lt;p&gt;If you want to switch DevTools to the APCA algorithm, open &lt;strong&gt;DevTools Settings&lt;/strong&gt; → &lt;strong&gt;Experiments&lt;/strong&gt; and enable the APCA contrast option. The main downside is that DevTools typically shows either WCAG &lt;em&gt;or&lt;/em&gt; APCA results, not both at once.&lt;/p&gt;

&lt;h3&gt;
  
  
  Firefox
&lt;/h3&gt;

&lt;p&gt;Firefox DevTools also shows contrast in the color picker for the &lt;code&gt;color&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fth3s4mur41.me%2F_astro%2Ffirefox-color-picker.BeedRq-v_yPOKI.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fth3s4mur41.me%2F_astro%2Ffirefox-color-picker.BeedRq-v_yPOKI.png" alt="Firefox DevTools color picker displaying contrast information for the selected text&amp;lt;br&amp;gt;
color." width="260" height="246"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Firefox DevTools: check contrast in the color picker for the property.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  When you want WCAG and APCA side-by-side
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://visbug.web.app/" rel="noopener noreferrer"&gt;VisBug&lt;/a&gt; is a good alternative for quick checks, since its contrast checker shows WCAG and APCA results side by side.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd39x1oqrvy3xr125at2b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd39x1oqrvy3xr125at2b.png" alt="VisBug contrast checker showing WCAG and APCA results side by side." width="347" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;VisBug: handy for quick spot-checks when you want WCAG and APCA at the same time.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Warning: Contrast tools have limits
&lt;/h2&gt;

&lt;p&gt;All of these tools are helpful, but they have a limitation: they can only reliably validate contrast by following the normal DOM and paint flow to determine the “effective” background behind text.&lt;/p&gt;

&lt;p&gt;If you use visual stacking (for example via CSS Grid overlap, positioned layers, or a background created with a pseudo-element like &lt;code&gt;::before&lt;/code&gt;) where the foreground and background colors live on different elements, tools can pick the wrong background to compare against.&lt;/p&gt;

&lt;p&gt;In the following demo, both boxes look identical, but most tools report a contrast of 1 (no contrast) for the second box because they compare the text against the page background (e.g. &lt;code&gt;body&lt;/code&gt;) rather than the yellow background painted by &lt;code&gt;::before&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;Tools and rules are there to help you make better decisions, not to replace judgment. The real goal of contrast work isn’t “passing a checker”, it’s making content that people can comfortably read and use.&lt;/p&gt;

&lt;p&gt;Ideally, aim to satisfy both WCAG and APCA. But when you can’t (or when the two point you in different directions), favor real user experience over compliance: validate with real content, real contexts, and—when possible—real users.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>wcag</category>
      <category>apca</category>
      <category>colorcontrast</category>
    </item>
  </channel>
</rss>
