<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Adam Liptrot</title>
	<subtitle>Accessibility fan, builds websites.</subtitle>
	<link href="https://liptrot.org/feed.xml" rel="self"/>
	<link href="https://liptrot.org/"/>
	<updated>2025-02-08T13:00:00Z</updated>
	<id>https://liptrot.org/</id>
	<author>
  <name>Adam Liptrot</name>
  <email>adam@liptrot.org</email>
	</author>
	
    
      
      <entry>
        <title>Mobile app accessibility</title>
        <link href="https://liptrot.org/posts/mobile-app-accessibility/"/>
        <updated>2025-02-08T13:00:00Z</updated>
        <id>https://liptrot.org/posts/mobile-app-accessibility/</id>
        <content type="html"><![CDATA[
          <h2>Contents</h2>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#choice-of-code-framework">Choice of code framework</a></li>
<li><a href="#versions-matter">Versions matter</a></li>
<li><a href="#designing-for-native-apps-is-different">Designing for native apps is different</a></li>
<li><a href="#applying-accessibility-best-practice">Applying accessibility best practice</a></li>
<li><a href="#checking-apps-for-accessibility">Checking apps for accessibility</a></li>
<li><a href="#the-need-for-closer-team-collaboration">The need for closer team collaboration</a></li>
<li><a href="#wrap-up">Wrap-up</a></li>
<li><a href="#further-reading">Further reading</a></li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>Mobile app accessibility has some similarities with web development, but it is also important to be aware of the differences so we can account for them during development.</p>
<p>This article assumes some knowledge of how websites manage accessibility and is mainly aimed at web developers and designers who have made the jump to app development.</p>
<h2 id="choice-of-code-framework">Choice of code framework</h2>
<p>The official frameworks are SwiftUI on iOS and Compose on Android. These will give you access to the best accessibility features to use when coding your interfaces as they use the native languages for each platform. Frameworks which allow you to code once and then deploy both iOS and Android apps from the same codebase (such as React Native) can end up sacrificing accessibility in order to do this.</p>
<p>The choice of framework may only be found to be an issue when an accessibility issue is raised and you find that the one you are using cannot support the code you need to write.</p>
<p>Using native languages is perhaps the ultimate “shift left” for accessibility. Yes it is extra work writing to those two codebases but it means you can ensure you are likely to be able to support most accessibility improvements. But it is not without tradeoffs in speed of delivery and consistency.</p>
<h2 id="versions-matter">Versions matter</h2>
<p>Just as different browser versions support different features of CSS, different versions of iOS and Android support different accessibility features. This may require conditional logic within the app to determine if these features can be used.</p>
<h2 id="designing-for-native-apps-is-different">Designing for native apps is different</h2>
<p>If you are used to designing responsive web-based products, there are differences in how native mobile apps should be approached. A native app needs to be considered in a different way to a mobile view in a browser.</p>
<p>Websites have a lot of accessibility features they can use to help users understand content. HTML is heavily semantic at its core and <a href="/posts/aria/">ARIA</a> allows designers and developers to be really explicit about how accessibility is translated to the user.</p>
<p>On native mobile this is not as clear or as well developed. We need to keep native mobile interfaces simple and avoid complex components. For this reason just porting a responsive website's mobile view to a native mobile app is potentially going to introduce accessibility pitfalls, especially for screen-reader users.</p>
<h3>Tools for designers</h3>
<ul>
<li><a href="https://www.figma.com/community/plugin/1208180794570801545/includeaccessibility-annotations">Include Figma plugin from eBay</a></li>
<li><a href="https://www.figma.com/community/file/1331647574396908226/accessibility-annotation-kit-for-ios">iOS Annotations Figma plugin from CVS</a></li>
</ul>
<h2 id="applying-accessibility-best-practice">Applying accessibility best practice</h2>
<p>The first thing to appreciate when designing or building native mobile apps is that <a href="/posts/guidelines-and-legalities/#wcag">WCAG</a> still applies. Whilst WCAG was not directly written for native apps (it was originally written before they existed), most of the criteria can be applied to them as WCAG is platform agnostic.</p>
<p>The <a href="https://www.w3.org/TR/mobile-accessibility-mapping/">W3C created a guide</a> to help teams understand how WCAG principles apply to mobile. Whilst this concentrates on mobile versions of websites it does contain some useful reminders for how small screens and predominantly touch-based devices can affect a design.</p>
<p>Let's have a look at some specifics of things which should be considered when designing or building a native app.</p>
<h2 id="checking-apps-for-accessibility">Checking apps for accessibility</h2>
<p>We will be discussing some visual adaptations and <a href="/posts/assistive-technology/">assistive software</a> but in particular what we need to think about when looking at native apps.</p>
<h3>Roles</h3>
<p>Just as on the web, native apps can communicate some semantic information in how the components are coded. On the web this is done using particular HTML tags or explicit <code>role</code> attributes. On native these are done by using accessibility <code>traits</code>.</p>
<p>These can be checked using tools (see below) or a screen-reader.</p>
<h3>Accessible names</h3>
<p>Images should in most cases have good alternate text descriptions as you would normally do. Form inputs should be correctly labelled, and links and buttons should have accessible names. On native apps these are referred to as <code>accessibleLabels</code> but are just as important.</p>
<p>These can be checked using tools (see below) or a screen-reader.</p>
<h3>Headings</h3>
<p>iOS supports different heading levels, but Android does not, so whilst iOS users can determine hierarchy from the different levels of headings this is not something Android users can benefit from.</p>
<p>Frameworks which compile down to both iOS and Android such as React Native look to have devolved to the Android state. This means even when iOS supports an accessibility feature this can be prevented from being used by the framework.</p>
<h3>Colour contrast</h3>
<p>Checking colours on-device can be tricky but if you can mirror the device to your development computer screen it makes it easier. Otherwise you may need to screenshot the app and export it to somewhere you can use a contrast checker with a colour picker, such as the <a href="https://www.tpgi.com/color-contrast-checker/">TPGi Colour Contrast Analyser</a>.</p>
<h3>Dynamic content</h3>
<p>On the web where we have dynamic content we can use ARIA live regions to keep screen-reader users up-to-date with changes to page content.</p>
<p>We need to do the same with our native apps, whether this is error messages or other notifications.</p>
<h3>Touch target size</h3>
<p>With the small size of mobile screens we can find we have scaled down controls too much in an effort to squeeze them all in.</p>
<p>Touch targets need to be a minimum of 44 by 44pt on iOS, and 48 by 48dp on Android.</p>
<h3>Larger font sizes</h3>
<p>Many users will adjust the font-size on their devices to make it easier for them to read content. Native apps should support this by using responsive fonts (on iOS this is known as <em>Dynamic Type</em> and as <em>Scalable Pixels</em> on Android).</p>
<p>Whilst using responsive fonts is the first step, you also need to ensure the text is allowed to expand as it grows. Otherwise text can be cut off or truncated and become unreadable.</p>
<p>We are firstly wanting to check that the font actually increases in size in response to the user's preferences.</p>
<p>Once we are happy that is happening then we also want to check that all the text is still readable and none of the previously readable content has been cut off or otherwise truncated.</p>
<figure>
<img src="/assets/images/modules/mobile-font.png" data-orient="portrait" alt="The Tesco shopping app. Some text is cut off with an ellipsis." />
<figcaption>We can see on the Tesco app that when increasing the font size the central section does not expand enough to accomodate the text and as a result the text is cut off.</figcaption>
</figure>
<p>On iOS there is a “Larger Accessibility Sizes” toggle which gives access to 5 larger font sizes than those in the standard display settings. These should be tested too. Apps may have areas where these larger fonts cannot be displayed (such as in the tab bar). Where this is the case the app should make use of the iOS <a href="https://developer.apple.com/videos/play/wwdc2019/261/">“Large Content Viewer”</a>. This allows the user to long press on the item to see a zoomed version of it on-screen.</p>
<p>Note the Large Content Viewer should <strong>only</strong> be used where sizing text is not possible - such as the tab bar where sizing the tabs up would obscure the main content. It should not be used for body copy or where layout changes could allow larger font sizes.</p>
<figure>
<img src="/assets/images/modules/mobile-lcv.png" data-orient="portrait" alt="The BBC iPlayer app with large fonts enabled. The tab bar font is still small but the app is showing a large view of the home tab in the middle of the screen." />
<figcaption>Here is the Large Content Viewer in action on the BBC iPlayer app where the content text size has increased but the tab bar has not. The user has long-pressed on the Home tab and a zoomed in version is shown in the middle of the screen.</figcaption>
</figure>
<h3>Larger display size</h3>
<p>Android also has a setting called <em>Display Size</em>. This increases the size of UI elements (such as icons) which just increasing font sizes does not.</p>
<p>Larger display sizes should also be tested in conjunction with larger font sizes as it likely these will both be used together.</p>
<h3>Orientation</h3>
<p>This is something often overlooked on native apps. Take a look at some of the apps on your phone. How many of them rotate their view when you turn your phone to landscape?</p>
<p>Orientation is a user preference and so should be respected and supported just as we do on the web. Some users may not be able to use their devices in any other way other than landscape.</p>
<p>The app should be viewable in both portrait and landscape. Crucially here we also want to check that not only has the orientation switch worked but also that nothing in the layout has broken as a result, and content can still be read.</p>
<p>For example Audible on Android does not switch orientation until you have selected and are listening to a title when it does present a landscape mode.</p>
<figure>
<img src="/assets/images/modules/mobile-orientation.png" data-size="intrinsic" alt="The Audible app in landscape orientation, showing a title being played with the controls aligned with the device orientation" />
<figcaption>Here the Audible app is playing a title and accomodates the landscape orientation.</figcaption>
</figure>
<figure>
<img src="/assets/images/modules/mobile-orientation1.png" data-size="intrinsic" alt="The Audible app in landscape orientation, showing the homescreen title browser. Here the app does not allow for use in landscape mode." />
<figcaption>But when using the app to browse your library or shop the orientation of the device is not respected.</figcaption>
</figure>
<h3>Larger viewports</h3>
<p>We can forget to review designs for how they present on larger viewports. For mobile apps in particular we need to think about tablets and how that extra real-estate can affect accessibility.</p>
<p>For example a button attached to the right side of the screen on mobile may not cause any issues, but on a tablet not adjusting the design can lead to that same button being very isolated. This could cause issues for some users such as those using screen-magnification.</p>
<p>Also be aware that other components may change between these device types. For example on iOS main navigation will be shown in a tab bar at the bottom of the screen, but on iPadOS it will move to the top of the screen or even as a sidebar. These different versions will need to be checked for contrast and keyboard accessibility in both versions.</p>
<h3>Voice Entry</h3>
<p>When users are being asked to enter data into fields not all users will want to type an answer. Virtual keyboards allow voice entry now by using the microphone option. We need to ensure input fields which we present to users do not prevent this type of entry, but also that we are forgiving of simple issues this may create.</p>
<h3>Switch control</h3>
<p>We can set up an external keyboard (see below) to act as our switch input, just as we might on a laptop.</p>
<p>Switch control can work slightly differently on native apps than it does on websites. By segmenting our screens we can present <em>groups</em> of controls which a switch control user can navigate in sets to reduce time in making a selection.</p>
<figure>
<img src="/assets/images/modules/mobile-switch.png" data-orient="portrait" alt="The BBC iPlayer app showing a group of navigation buttons surrounded by a bright blue border." />
<figcaption>The BBC iPlayer app shows how grouping controls allows switch devices to more quickly navigate a screen. Here the user can stop the scanning on this group and scanning will then move through the items in the group to allow the user to pick one.</figcaption>
</figure>
<p>Another thing to consider is avoiding reliance on gestures to control the interface. Whereever gesture controls are added it is best to have a non-gesture option.</p>
<h3>External keyboard</h3>
<p>Just as with websites, keyboard access is often overlooked, but this happens a lot more with native apps as the assumption is users will be using the touch-screen.</p>
<p>The easiest way to test is by using an external bluetooth keyboard.</p>
<p>On iOS in order to move through an app using a keyboard you will need to turn on “full keyboard access” under Accessibility in Settings.</p>
<p>On iOS you also have the option of using “keyboard gestures” by using the <kbd>Tab + G</kbd> command. This then allows you to make swipe gestures. However bear in mind that not all users will be aware of this and Android phone users do not have this option. It is always best to provide keyboard users with buttons to accomplish what other users may do with gestures.</p>
<p>Navigating within the app will be a mix of tab and arrow keys, but arrow keys will be the primary way. This differentiates native app testing from website testing and can take a little getting used to.</p>
<p>Other than how you navigate, we are looking for largely the same issues we might with websites - can we reach and activate everything and can we see where our focus is easily?</p>
<h3>Screen-readers</h3>
<p>Screen-readers work largely as they would on websites. In fact it is easier to test on mobile apps because there is one less complexity - the absence of the browser. We are also only going to need to test with the native options - TalkBack on Android and VoiceOver on iOS and iPadOS.</p>
<p>One thing to note is that native apps may not announce roles (or traits) in the same way as websites do. For example a button may just announce the label and “Double tap to activate.”</p>
<h3>On/off labels</h3>
<p>This is an iOS-specific user setting. It adds an &quot;on&quot; or &quot;off&quot; text label to switches within the app to help users who may have difficulty determining the state of the switch. We should verify that any toggle switches are correctly updated when this option is set.</p>
<figure>
<img src="/assets/images/modules/mobile-toggle.png" data-size="intrinsic" alt="Screenshots of toggle buttons showing how when the setting is enabled a visual indicator is added within the button to indicate its state." />
<figcaption>Here we can see how this setting changes the toggle buttons on the BBC iPlayer app. When enabled each toggle button gets an additional indicator shown as a vertical line for “on” or a cirlce for “off”.</figcaption>
</figure>
<h3>Other tests</h3>
<p>These tests will work very much as they would with websites:</p>
<ul>
<li>text-to-speech - Select-to-speak (Android) and Spoken Content (iOS)</li>
<li>speech-recognition - Voice Access (Android) and Voice Control (iOS)</li>
<li>colour filters - Simulate Colour Space (Android) and Colour Filters (iOS)</li>
</ul>
<h3>Testing tools</h3>
<p>On native apps we don't have access to code in the same way as you do with websites and browser developer tools. However there are a couple of tools which can help with some basic checks.</p>
<h4>Android accessibility scanner</h4>
<p>This is an app which you install on the same device as the app you are testing. It then appears as a floating button which you activate when you are on the app you want to test. You can choose to snapshot test the screen you are currently viewing, or set it to record and it will check as you move through the app.</p>
<p>With either method it will generate an interactive overlay where you can zoom in on particular issues. You can then export this set of results via email.</p>
<figure>
<img src="/assets/images/modules/mobile-android.png" alt="Two screenshots. The first shows an app homepage with various elements highlighted with coloured boxes. The second has zoomed in on one of these and shows information about the colours used in the app and the contrast ratio." />
<figcaption>Here we see the scanner result screen for an app, highlighting the potential issues. Here we have focussed on a potential text contrast issue and the scanner shows that the text is indeed below the required level.</figcaption>
</figure>
<figure>
<img src="/assets/images/modules/mobile-android2.png" alt="Two screenshots. The first shows several images of various app screens in a row with one highlighted and show larger below. The second shows all the screens larger each with a number in a circle." />
<figcaption>When run in record mode the scanner will check each screen, including scrolls. The snapshots can then be viewed one at a time (first image), or as an overview (second image) with numbers indicating the amount of issues found. It will even collate these issues by type across the entire recording.</figcaption>
</figure>
<p>Issues this scanner may find include:</p>
<ul>
<li>using height or width restricted containers for dynamic text sizes</li>
<li>colour contrast issues</li>
<li>touch target size</li>
<li>missing labels on elements</li>
<li>duplicate labels or descriptions</li>
<li>unexposed text (visible text which has been hidden from assistive technology)</li>
</ul>
<h4>XCode Accessibility Inspector</h4>
<p>By connecting the device running the app to a Mac with XCode this will allow you to inspect the various elements on the screen with the Mac's “Accessibility Inspector”.</p>
<p>The inspector has 3 modes: “Inspection”, “Audit” and “Settings”.</p>
<h5>Inspection</h5>
<p>This is useful for spot-checks on specific elements or helping with debugging an issue you spotted with something like VoiceOver or Voice Control. It allows you to pick an element and see a bunch of information such as <code>traits</code>.</p>
<figure>
<img src="/assets/images/modules/mobile-ios-inspector.png" alt="Screenshot of the app showing information on one element including the label, traits and hint" />
<figcaption>The Accessibility Inspector inspection mode showing details about one element.</figcaption>
</figure>
<p>It also has a VoiceOver emulator which allows you to hear the elements read out (through the Mac) as a VoiceOver user might hear it. This can be handy for some quick checks but should not replace testing with VoiceOver on the actual device.</p>
<h5>Audit</h5>
<p>This allows you to run a scan on the current screen and get a list of potential issues. You can also bring up a screenshot of the screen with the item being talked about in the issue highlighted.</p>
<figure>
<img src="/assets/images/modules/mobile-ios-audit.png" alt="The inspector showing a list of issues. One has been opened and a screenhot of the app with the item with the issue is highlighted." />
<figcaption>The Accessibility Inspector audit mode showing details about one issue, note the screenshot indicates where on the screen the issue is.</figcaption>
</figure>
<h5>Settings</h5>
<p>This allows you to control certain OS-level preferences such as font-size, reduce motion and more. This feeds off the device settings so it will display any existing state of these settings here. Updating one of these will also show immediately on the attached device, so it is a good way to check some settings quickly.</p>
<figure>
<img src="/assets/images/modules/mobile-ios-settings.png" alt="Screenshot of the a settings screen showing various options with checkbnoxes." />
<figcaption>The Accessibility Inspector settings mode.</figcaption>
</figure>
<p>Note that the upper half of the font-size slider here equates to the “Larger Accessibility Sizes” toggle on the device. So the maximum setting of the slider in the Inspector settings is equivalent to having the Larger Accessibility Sizes setting toggled <strong>and</strong> the font-size slider on device all the way to the right.</p>
<h2 id="the-need-for-closer-team-collaboration">The need for closer team collaboration</h2>
<p>HTML is a fairly easy to understand language. Even if a designer is not comfortable with writing it they can follow along as it is a succinct set of tags which are largely readable. When it comes to native app development it is much more akin to using javascript to create DOM nodes from scratch and assign attributes. This abstraction coupled with the need for more specialist software to build apps and the associated learning curve means it is more difficult for designers to engage directly with the code.</p>
<p>As such it is vitally important that designers and coders of native apps work closely together to develop accessible solutions.</p>
<h2 id="wrap-up">Wrap-up</h2>
<p>Just as with websites, native mobile apps need to consider accessibility and implement a range of checks to ensure we don't leave users behind when we move from the web to native.</p>
<h2 id="further-reading">Further reading</h2>
<h3>General guidance</h3>
<ul>
<li><a href="https://www.youtube.com/watch?v=cgm8qQpoDt0&amp;t=952s">Intro to mobile app accessibility</a></li>
<li><a href="https://appt.org/en">Appt guide for making apps accessible</a></li>
<li><a href="https://getevinced.github.io/mcag/">Evinced mobile app accessibility guidelines</a></li>
<li><a href="https://bsky.app/profile/steady5063.bsky.social">Mark Steadman on BlueSky</a></li>
<li><a href="https://bsky.app/profile/dadederk.bsky.social">Dani Devesa on BlueSky</a></li>
</ul>
<h3>iOS references</h3>
<ul>
<li><a href="https://developer.apple.com/design/human-interface-guidelines/accessibility">iOS Human Interface Guidelines - accessibility section</a></li>
<li><a href="https://developer.apple.com/accessibility/">iOS developer guidelines - accessibility section</a></li>
<li><a href="https://developer.apple.com/documentation/swiftui/accessibility-fundamentals">SwiftUI Accessibility Fundamentals</a></li>
<li><a href="https://github.com/cvs-health/ios-swiftui-accessibility-techniques">CVS Health iOS SwiftUI</a></li>
</ul>
<h3>Android references</h3>
<ul>
<li><a href="https://developer.android.com/guide/topics/ui/accessibility/principles">Android accessibility principles</a></li>
<li><a href="https://github.com/cvs-health/android-compose-accessibility-techniques">CVS Health Android Compose</a></li>
<li><a href="https://www.youtube.com/watch?v=cgm8qQpoDt0&amp;t=952s">Building accessible Android apps with Jetpack Compose</a></li>
</ul>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>10 accessibility mistakes on the new Whitehouse website</title>
        <link href="https://liptrot.org/posts/10-accessibility-mistakes-on-the-new-whitehouse-website/"/>
        <updated>2025-01-22T13:00:00Z</updated>
        <id>https://liptrot.org/posts/10-accessibility-mistakes-on-the-new-whitehouse-website/</id>
        <content type="html"><![CDATA[
          <p>I thought it would be interesting to see how the new <a href="https://www.whitehouse.gov/">Whitehouse website</a> did on accessibility, so here are a few places where I think it falls short.</p>
<img loading="lazy" src="/assets/images/posts/wh-full.png" alt="Full-page screenshot of the Whitehouse homepage." data-oreint="portrait" />
<h2>Contents</h2>
<ul>
<li><a href="#auto-playing-full-screen-video">Auto-playing full-screen video</a></li>
<li><a href="#not-respecting-user-preferences-for-reduced-motion">Not respecting user preferences for reduced motion</a></li>
<li><a href="#alt-text">Alt text</a></li>
<li><a href="#not-updating-aria">Not updating ARIA</a></li>
<li><a href="#menu-dialog-issues">Menu dialog issues</a></li>
<li><a href="#headings">Headings</a></li>
<li><a href="#inaccessible-links">Inaccessible links</a></li>
<li><a href="#use-of-title-attribute">Use of title attribute</a></li>
<li><a href="#poor-contrast">Poor contrast</a></li>
<li><a href="#missing-programmatic-information">Missing programmatic information</a></li>
<li><a href="#other-issues">Other issues</a></li>
<li><a href="#verdict">Verdict</a></li>
</ul>
<h2 id="auto-playing-full-screen-video">Auto-playing full-screen video</h2>
<p>The Whitehouse website has a full-window video auto-play when you first visit the site <em>(edit 18 Feb 2025 - it looks like this may now have been removed)</em>.</p>
<p>Having a large video auto-play on page load is an issue for some users - we can’t assume users will know how to set a preference so we should always avoid this kind of addition.</p>
<p>It is also not great for first impressions as on slower connections it can stumble. At 8.4MB it is also a heavy load for users on data limits. Disabled users in general have lower disposable incomes due to employment issues and additional expenses, so this is an accessibility issue.</p>
<p>On the plus side at least the sound is muted and the user can dismiss the video immediately (although even doing that allows 4.2MB of video download). On 3G I ran out of patience before the video even loaded.</p>
<p>Thankfully you only see it on first visit as a local storage flag is set.</p>
<h2 id="not-respecting-user-preferences-for-reduced-motion">Not respecting user preferences for reduced motion</h2>
<p>Related to the first point, the website does not respect where a user has asked for reduced motion in their settings.</p>
<figure>
<img loading="lazy" src="/assets/images/posts/wh-reduced.png" alt="Four options in a settings panel. One of them states reduce motion and has a toggle button showing as active alongside.">
<figcaption>MacOS settings for Reduce Motion</figcaption>
</figure>
<p>The auto-playing video, the heavy use of zoom effects in hover states and animation of the carousel on smaller viewports can all trigger issues for users.</p>
<p>There are simple mechanisms for websites to check for this setting and adjust the interactions based on it.</p>
<h2 id="alt-text">Alt text</h2>
<h3>Missing alt text</h3>
<p>There are a couple of places where alt text has been left blank. For example the 47th president logo and adjacent signature. These could have been given explanatory descriptions as they do mean something.</p>
<figure>
<img loading="lazy" src="/assets/images/posts/wh-seal.png" alt="The presidential seal with the number 47 below it. Alongside is a signature.">
<figcaption>The presidential seal and number indicating this is the 47th president, alongside the president’s signature.</figcaption>
</figure>
<h3>Repetition caused by alt text</h3>
<p>Elsewhere alt text has been used and created repetition where a better pattern would have prevented it, such as the 3 links to &quot;White House&quot;, &quot;Camp David&quot; and &quot;Air Force One&quot; towards the bottom of the page:</p>
<figure>
<img loading="lazy" src="/assets/images/posts/wh-repetition.png" alt="Three images each with text above. The text reads The White House, Camp David, and Air Force One">
<figcaption>The White House links</figcaption>
</figure>
<p>Here the images are the links and the text above is unlinked. The images each have alt text which repeats the text above. So a screen-reader will get repeated content as they move through - it will be announced something like this:</p>
<blockquote>
<p>“Camp David, Camp David link”</p>
</blockquote>
<p>A better solution would be to use a card pattern which would use the text as the link and add a click-handler to include the image. This would allow users to click the text (as well as the image) and also allow us to add proper descriptive alt text to the images. For example:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>wh-card<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> /* js click handler added to this container */
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>The White House<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>  
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>wh.webp<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Exterior of the White House on a summer's day<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
</code></pre>
<h3>Overly basic alt text</h3>
<p>Finally on images, the two large images of Trump have very basic alt text of “Donald J Trump“ which whilst true does not put across any of the emotion I am sure the designers are intending to convey with those images.</p>
<h2 id="not-updating-aria">Not updating ARIA</h2>
<p>The search button in the top right has an ARIA attribute applied to indicate that it triggers something which is currently closed:</p>
<figure>
<img loading="lazy" src="/assets/images/posts/wh-aria.png" alt="The text Search alongside an icon of a magnifying glass.">
<figcaption>The button which opens the search form in a dialog.</figcaption>
</figure>
<pre class="language-html"><code class="language-html">​<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">aria-expanded</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span> <span class="token attr-name">title</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Open search<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Search<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<p>But when the button is pressed the ARIA is not updated which then conflicts with the information the user is now getting from the accessible name (which has been updated):</p>
<pre class="language-html"><code class="language-html">​​<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">aria-expanded</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span> <span class="token attr-name">title</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Close search<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Close<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<p>Oddly the team managed to do this correctly with the menu dialog.</p>
<h2 id="menu-dialog-issues">Menu dialog issues</h2>
<h3>Keyboard</h3>
<p>When the user opens the menu dialog keyboard users are not restricted to the modal. A keyboard user can tab to the page behind the dialog which can mean their focus becomes obscured.</p>
<h3>Screen-readers</h3>
<p>Screen-reader users don't fair much better as once the modal has opened the close button is unreachable as it sits outside the dialog bounds despite being visible.</p>
<p>We can see the issue when we look at the elements list for NVDA and see the buttons are there when the dialog is closed:</p>
<figure>
<img loading="lazy" src="/assets/images/posts/wh-modal-closed.png" alt="NVDA element list showing the Menu and search buttons which can also be seen in the page behind.">
<figcaption>With the modal closed NVDAs element viewer lists the search and menu buttons</figcaption>
</figure>
<p>But the same elements are missing when the dialog is open, despite being visible:</p>
<figure>
<img loading="lazy" src="/assets/images/posts/wh-modal-open.png" alt="NVDA element list showing the menu and search buttons are not visible to the screen-reader despite still being visible on the page behind.">
<figcaption>Now the modal is open the button list is empty but the buttons are visible on the page</figcaption>
</figure>
<p>Fortunately the dialog has been hooked up to be closed via the Esc key so both users can close it if they are aware of the shortcut.</p>
<p>These issues are most likely a result of using <code>role=”dialog”</code> instead of the dialog element and not thinking through the impact of doing this. The dialog element brings with it some functionality, such as making the rest of the page inert and trapping focus. Using <code>role=”dialog”</code> is the equivalent of using <code>role=”button</code> on a <code>div</code> - you need to bring the functionality yourself.</p>
<h3>Missing accessible name</h3>
<p>Using a <code>role=”modal”</code> also requires that you give your modal an accessible name, for example using <code>aria-label</code>. This is not present here so adds another issue.</p>
<h2 id="headings">Headings</h2>
<p>It is important that headings are correctly applied as they are one of the main navigation methods for screen-reader users on longer pages. They also give an indication of grouping of content and provide an important introduction to the content the user may find next.</p>
<h3>Missing semantics</h3>
<p>On the homepage &quot;The Administration&quot; text which introduces the photos of the president and others is just marked up as plain text:</p>
<figure>
<img loading="lazy" src="/assets/images/posts/wh-heading.png" alt="Text which reads The Administration above a set of images. The size of the text suggests it is a heading">
<figcaption>The text appears to be a heading but it is not programmatically set as such.</figcaption>
</figure>
<pre class="language-html"><code class="language-html">​<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>wp-block-whitehouse-front-administration__headline<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
  The Administration
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
</code></pre>
<p>So if we take a look at the HeadingsMap browser extension (which lists all headings on a page and constructs a tree diagram) we can see that the first heading we will encounter after the h1 is actually below this group:</p>
<figure>
<img loading="lazy" src="/assets/images/posts/wh-headingmap.png" alt="A tree structure of the headings on the page.">
<figcaption>The Administration should present as a heading between the h1 of “America is Back” and the h2 of “Our priorities“</figcaption>
</figure>
<h3>Non-unique headings</h3>
<p>Another issues is that we can also see from this list that despite the h2 further down the page visually saying &quot;About the White House&quot;:</p>
<img loading="lazy" src="/assets/images/posts/wh-unique.png" alt="A section heading which says About the White House. The word about is smaller and sits just above the other words.">
<p>This is not what is communicated as the &quot;About&quot; is actually sitting outside the h2:</p>
<pre class="language-html"><code class="language-html">​<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>About<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h2</span><span class="token punctuation">></span></span>The White house<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h2</span><span class="token punctuation">></span></span>
</code></pre>
<p>This then means we have two headings adjacent to each other with the same content, but with different levels and with different meanings. The word “about” needs to be included in that h2 - something which should happen even if it didn’t cause the non-unique error.</p>
<h2 id="inaccessible-links">Inaccessible links</h2>
<p>While we are looking at the Administration section, the links for the 4 items are unreachable for both keyboard users and screen-reader users. This is also the case for the &quot;Executive Actions&quot; and &quot;News&quot; links above. This constitutes the majority of the content on the website.</p>
<figure>
<img loading="lazy" src="/assets/images/posts/wh-links.png" alt="A grid of 6 images.">
<figcaption>None of these sections can be reached by keyboard or screen-reader.</figcaption>
</figure>
<p>Looking at the code it looks like there has been a decision made to not wrap the link element around any content, but instead use CSS to position it above the content:</p>
<pre class="language-html"><code class="language-html">​<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>.../jd-vance/<span class="token punctuation">"</span></span> <span class="token attr-name">aria-hidden</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token attr-name">tabindex</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>-1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>.../jdvance.jpg<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>J D Vance<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
</code></pre>
<p>The lack of accessible name on the link is obviously one concern, but the link also has an <code>aria-hidden</code> attribute (which hides it from screen-readers) and a <code>tabindex=&quot;-1&quot;</code> attribute which removes the link from the focus order. Both are very conscious decisions and suggest they are attempting to implement a card pattern.</p>
<p>The card pattern would normally have included making the main call-to-action (in this case the name) a link and letting keyboard and screen-reader users discover that and then have some positioned area as a mouse/touch option covering the whole card.</p>
<h3>Looking at a fix</h3>
<p>So the first step in fixing this would be to link up the main text for each item:</p>
<pre class="language-html"><code class="language-html">​<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>.../jd-vance/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>J D Vance<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p>This works, however we still have our odd, heavily attributed and nameless link. Adding <code>aria-hidden</code> to a control such as a link is never a good idea as it causes a slew of odd behaviours.</p>
<p>For example if we just left it like this, then screen-readers suddenly start picking up both links (the initial one is now showing as the document name from the href):</p>
<figure>
<img loading="lazy" src="/assets/images/posts/wh-fix.png" alt="The card component showing two links in the NVDA element list, one visible and one not. The one which is not visible has taken the accessible name form the href of the link.">
<figcaption>NVDA’s element list showing how the addition of the new link exposes the first.</figcaption>
</figure>
<p>For this to work as we want we need the card link to be removed and instead replaced by a click handler on the container. This is ok as without js we still have the new link to fall back on.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>container<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> /* add click handler to this using the link href as target */
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>.../jdvance.jpg<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
  ​<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>.../jd-vance/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>J D Vance<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
</code></pre>
<p>We can improve this further by swapping the position of the image and link and adding alt text to the image. We could even include the secondary text as part of the link.</p>
<p>But at least now the content will be usable!</p>
<p>In short, never use <code>aria-hidden</code> on interactive things.</p>
<h2 id="use-of-title-attribute">Use of title attribute</h2>
<p>The <code>title</code> attribute has been used a lot on images and controls across the site. The title is problematic because it has a dual nature. It is really an accessible name source of last resort - so if there is no 'standard' accessible name provided (via content, alt text, labels or aria) then this would be used. However where an accessible name is provided the title is demoted to an accessible description, which means it will be read out after the given accessible name.</p>
<p>For example, the White House logo at the top of the screen:</p>
<img loading="lazy" src="/assets/images/posts/wh-title.png" alt="Header logo showing a line drawing of the White House above the text The White House President Donald J Trump">
<figure>
<img loading="lazy" src="/assets/images/posts/wh-title-dev.png" alt="Chrome developer tools accessibility panel showing the accessible name computation for the link.">
<figcaption>We can see in devTools how the title was contributing to the accessible name of the link until it was overwritten by the link contents. This changes the title to be the accessible Description.</figcaption>
</figure>
<pre class="language-html"><code class="language-html">​<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span> <span class="token attr-name">title</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>The White House<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span>The White House<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span>President Donald J Trump<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p>Will be read out by a screen-reader as</p>
<blockquote>
<p>&quot;The White House President Donald J Trump The White House&quot;</p>
</blockquote>
<p>Whilst not a major issue this repetition can become confusing and is unnecessary.</p>
<h2 id="poor-contrast">Poor contrast</h2>
<p>It wouldn't be a list of accessibility issues without at least one for poor contrast. While the text overlaid on the images on the homepage could potentially cause issues, I am going to look at one of the subpages for a more clear-cut example:</p>
<figure>
<img loading="lazy" src="/assets/images/posts/wh-contrast.png" alt="Four navigation links on a dark background. One is white whilst the others are darker.">
<figcaption>The links as they currently stand</figcaption>
</figure>
<p>Here we can see the sub navigation has poor contrast with the exception of the currently active page. The contrast here is 4:1 which is below that required for AA conformance.</p>
<p>When the contrast is so close to passing it is not going to require a full re-think of colour choices. Here the non-selected links are set using a 0.42 opacity of the white colour. If we tweak it to 0.62 opacity instead:</p>
<figure>
<img loading="lazy" src="/assets/images/posts/wh-contrast-fix.png" alt="The same links but the darker links are slightly brighter">
<figcaption>With the tweak to the opacity the non-selected links are easier to read.</figcaption>
</figure>
<p>We now get a 7.4:1 contrast which is a pass. However we are left with another issue.</p>
<p>The original 0.42 opacity gave us exactly a 4.5:1 contrast with the selected option and increasing the opacity has made this worse. I think here we should be looking at adding an extra visual indicator for the current page, such as the underline used on other pages:</p>
<img loading="lazy" src="/assets/images/posts/wh-nav.png" alt="Three navigation links, all the same colour. One has an underline suggesting it is selected.">
<h2 id="missing-programmatic-information">Missing programmatic information</h2>
<p>Another issue with this navigation is that whilst it is showing the current page visually through the colour change, this is not being reflected programmatically.</p>
<p>This is simply done through the use of aria-current=”page” on the currently active link:</p>
<pre class="language-html"><code class="language-html"> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> 
  <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>is-current<span class="token punctuation">"</span></span> 
  <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://www.whitehouse.gov/presidential-actions/<span class="token punctuation">"</span></span> 
  <span class="token attr-name">aria-current</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>page<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    Presidential Actions
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p>We could even use this as a hook for CSS to help us improve our accessibility right at the start and get rid of the is-current CSS class entirely:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">[aria-current]</span><span class="token punctuation">{</span>
  ...
<span class="token punctuation">}</span>
</code></pre>
<p>You could try to argue that the <code>h1</code> does this job (and I suspect this is what the thought process was with this as the <code>aria-current</code> attribute is used elsewhere), but we cannot assume screen-reader users navigate sequentially or understand the relationship between these two components.</p>
<h2 id="other-issues">Other issues</h2>
<p>These are just the main issues which jumped out at me after a quick look and only picking up a screen-reader. But there are other issues, such as poor error messages on the email form (along with a lack of error announcement for screen-reader users) and missing autocomplete on the same (although this is likely not to be an issue as most broswers will do a decent job of figuring this out in this instance). This administration has also removed the Spanish language version of the site, which in one move has made accessing information more difficult for a huge group of users.</p>
<p>This does show however that just a few simple checks can expose some quite major accessibility issues.</p>
<h2 id="verdict">Verdict</h2>
<p>I think it is good to say what a team have done well, so here are a few accessibility areas where they did ok too:</p>
<p>The dialogs are dismissable with the <kbd>Esc</kbd> key - without this the other issues would be more serious.</p>
<p>Landmarks are being used which will help screen-reader users. They have used several <code>nav</code> elements and whilst the footer ones do not have accessible names, where they have been using in-page such as for pagination controls, these have been given meaningful names.</p>
<p>Skip to content link is present and most importantly actually works, taking keyboard users beyond the main navigation.</p>
<p>In the main the team have used semantic elements. This goes a long way to improving accessibility, although they have shot themselves in the foot a couple of times.</p>
<p>ARIA has been used but not massively overused. Yes they have made some mistakes but you can see the thought process and adding some testing will help with these.</p>
<p>This goes to show that regardless of how your stakeholders view accessibility, there are accessibility wins which you can bring to a project just as part of doing your job.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Team process and role-based accessibility</title>
        <link href="https://liptrot.org/posts/team-process-and-role-based-accessibility/"/>
        <updated>2024-12-16T13:00:00Z</updated>
        <id>https://liptrot.org/posts/team-process-and-role-based-accessibility/</id>
        <content type="html"><![CDATA[
          <h2>Contents</h2>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#accessible-by-default">Accessible by default</a></li>
<li><a href="#time-and-budget">Time and budget</a></li>
<li><a href="#think-about-the-entire-journey">Think about the entire journey</a></li>
<li><a href="#using-3rd-party-services">Using 3rd-party services</a></li>
<li><a href="#wcag-aa-is-the-baseline-not-the-aim">WCAG AA is the baseline, not the aim</a></li>
<li><a href="#team-responsibility">Team responsibility</a></li>
<li><a href="#embedding-accessibility-in-team-processes">Embedding accessibility in team processes</a></li>
<li><a href="#dealing-with-accessibility-debt">Dealing with accessibility debt</a></li>
<li><a href="#wrap-up">Wrap-up</a></li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>Accessibility is a complex thing and it involves all aspects of a product's lifecycle from the initial idea, to design, development, testing and maintenance. It also needs support to be implemented cohesively and robustly.</p>
<p>Without a process to work to we become too reliant on the goodwill of individuals and when these individuals leave accessibility knowledge and practice leaves with them. Processes mean the entire team is brought along and accessibility becomes part of everyone's job.</p>
<h2 id="accessible-by-default">Accessible by default</h2>
<p>We should not see accessibility as an add-on or a nice-to-have, it should be just part of how we work, whether that is during kick-off discussions, during a discovery phase or during a build. We should never see accessibility as something we can deprioritise or leave until later.</p>
<h2 id="time-and-budget">Time and budget</h2>
<p>Accessibility in a project will add some additional time (and budget), but it will result in a much better product.</p>
<p>Make sure you allow time for your team to get up to speed and learn as they go. Think about avenues for help for the team - is there an in-house an accessibility team they can run things past for example? Think about setting up some process right at the start of the project (see Definiions of Ready and Done below).</p>
<p>The most important thing is don’t wait - it is never too early to start thinking aout accessibility and including users in your discovery phase.</p>
<p>Finally, make sure you schedule time both to prepare and undertake accessibility audits (especially if your team is in the Public Sector).</p>
<h2 id="think-about-the-entire-journey">Think about the entire journey</h2>
<p>Accessibility doesn’t start and end with the code we put on a screen. The user has to get to the product in the first place - how do they do that? Is it through a social channel, an email, a print campaign or something else? Are we looking at the whole journey and making sure it is as accessible as possible?</p>
<p>It’s no good if the online product is accessible if the social media posts are not.</p>
<p>Also think about the off-ramps from the product. Are contact mechanisms capable of supporting all the users - is there a range of contact options to allow users to choose the one which might suit them best? How about 3rd party integrations such as help-desks? If a user needs to raise a support ticket can they use the platform provided to follow it up?</p>
<p>An example of poor ancillary communication methods is a <a href="https://www.leighday.co.uk/news/news/2023-news/dwp-in-breach-of-equality-laws-after-failure-to-communicate-accessibly-with-blind-benefits-claimants/">case against DWP</a> where it was found they had discriminated against a blind user by not providing communication in an accessible format.</p>
<p>Then think about any support staff, are the systems they work with accessible? How about how the user logs into the product? Are those authentication methods accessible?</p>
<h2 id="using-3rd-party-services">Using 3rd party services</h2>
<p>If you are embedding or paying for 3rd party services then the responsibility for their accessibility comes down to your product. Do some investigation before signing up to any 3rd party services and where possible ensure accessibility is covered in any contracts.</p>
<p>Claims of WCAG compliance is one metric but it is often cited with no real data to back it up so treat such claims with caution if there is no evidence or demonstration of processes. Look for the ability to request fixes to bring in compliance where it is lacking. This expectation of the level of support should be covered in any contract.</p>
<h2 id="wcag-aa-is-the-baseline-not-the-aim">WCAG AA is the baseline, not the aim</h2>
<p>There is often a confusion that WCAG AA compliance should be the aim of a product. Unfortunately this would leave a lot of users behind as the WCAG criteria are not all-encompassing. There are lots of ways a product can be WCAG compliant but place barriers in front of their users.</p>
<p>Because of this we should view WCAG AA compliance as only the baseline for accessibility. We should always aim beyond this, leaning on testing with actual users, assistive technology and devices to bring a holistic approach to accessibility. If a user is having problems with a product, pointing to your WCAG compliance statement is not going to help them.</p>
<p>Just working to passing WCAG rather than true accessibility means we are just doing the bare minimum to make something <em>just accessible</em>. That's not enough.</p>
<p><a href="/posts/guidelines-and-legalities/">Read more about WCAG, guidelines and legalities.</a></p>
<h2 id="team-responsibility">Team responsibility</h2>
<p>Everyone, regardless of their team role, can contribute to making a product more accessible. We should never leave it to one person on the team to always be pushing for accessibility. Having one person with sole responsibility means others aren’t contributing their own valuable experience and makes it too easy for pushback. It also means the team never upskills. Reliance on a single person will mean they will quickly get overwhelmed and burn out as they try to fix issues caused by the rest of the team.</p>
<p>The only way forward is for everyone to take responsibility for their area. Look at drawing up a <a href="https://afixt.com/developing-a-raci-matrix-for-accessibility/">RACI matrix</a> to show who is responsible for what at each stage of the project.</p>
<h3>Example RACI matrix</h3>
<p>This example shows that each role is responsible for their own section and shows how responsibility for accessibility moves through the team along with the work. Notice also that previously responsible team members still need to be consulted so that solutions are correctly implemented.</p>
<ul>
<li>A = Accountable (the person ultimately accountable for the task)</li>
<li>R = Responsible (the person doing the task)</li>
<li>C = Consulted (people who should be involved in decisions)</li>
<li>I = Informed (people to keep in the loop)</li>
</ul>
<div class="tablewrapper" role="region" aria-label="An example RACI matrix" tabindex="0">
<table>
<thead>
<tr>
<th>Accessibility Task</th>
<th>Stake-holders</th>
<th>Project Manager</th>
<th>Business Analyst</th>
<th>Content Designer</th>
<th>UR &amp; UX Designer</th>
<th>Developer</th>
<th>QA Tester</th>
</tr>
</thead>
<tbody>
<tr>
<td>Define requirements</td>
<td>I</td>
<td>A</td>
<td>R</td>
<td>C</td>
<td>C</td>
<td>C</td>
<td>I</td>
</tr>
<tr>
<td>Create, test &amp; fix content</td>
<td>I</td>
<td>A</td>
<td>I</td>
<td>R</td>
<td>I</td>
<td>I</td>
<td>I</td>
</tr>
<tr>
<td>Design, test &amp; fix UX</td>
<td>I</td>
<td>A</td>
<td>I</td>
<td>C</td>
<td>R</td>
<td>C</td>
<td>I</td>
</tr>
<tr>
<td>Develop, test &amp; fix code</td>
<td>I</td>
<td>A</td>
<td>I</td>
<td>C</td>
<td>C</td>
<td>R</td>
<td>I</td>
</tr>
<tr>
<td>Monitor</td>
<td>I</td>
<td>A</td>
<td>I</td>
<td>C</td>
<td>C</td>
<td>C</td>
<td>R</td>
</tr>
<tr>
<td>Test for compliance</td>
<td>I</td>
<td>A</td>
<td>I</td>
<td>I</td>
<td>C</td>
<td>C</td>
<td>R</td>
</tr>
</tbody>
</table>
</div>
<div class="note note--insight">
<h3>Applying an accessibility maturity model to a team</h3>
<p>The W3C have developed an <a href="https://www.w3.org/TR/maturity-model/">accessibility maturity model</a> which we can use to help understand what is needed to embed accessibility into team culture.</p>
<p>This model goes beyond creating an accessible product and looks at how the team communicates internally and how it could support team members with access needs.</p>
<p>The AMM is split into several sections:</p>
<h4>Communications</h4>
<p>Ensuring a process is in place to deliver an accessible outcome and then following that up with actual accessible deliverables.</p>
<h4>Knowledge and skills</h4>
<p>Does the whole team have the skills they need to deliver accessible outcomes? Start by identifying gaps in knowledge, ensuring new hires have this knowledge or can undergo training.</p>
<h4>Support</h4>
<p>For an individual site this might be ensuring support channels are present for disabled users - for example an accessibility statement with contact information. But it also means that the team itself produces accessible internal documentation.</p>
<h4>Development lifecycle</h4>
<p>This covers the team responsibilities such as making sure:</p>
<ul>
<li>user research includes disabled users</li>
<li>accessibility forms part of the design process</li>
<li>user testing is undertaken with disabled users</li>
<li>accessibility forms part of the definitions of done and ready (see below)</li>
<li>accessibility is robustly tested before release</li>
<li>accessibility issues are taken seriously and preferably forms a release gate</li>
</ul>
<p>Having the team take responsibility for accessibility within their scope of work and not deferring it to someone else is one of the key indicators of a mature team.</p>
<h4>Personnel</h4>
<p>Could your team integrate a team-mate with disabilities if needed? Think about team activities, how the team operates or how they share information. Would any of these exclude this team member?</p>
<h4>Procurement</h4>
<p>If you are incorporating third-party content or services, have they been reviewed for accessibility (and the vendors been made aware of the requirement)?</p>
<h4>Culture</h4>
<p>Does accessibility permeate everything the team does and have buy-in from stakeholders down?</p>
</div>
<h2 id="embedding-accessibility-in-team-processes">Embedding accessibility in team processes</h2>
<blockquote>
<p>“Accessibility lives in people, processes and tools”</p>
<p>Derek Featherstone</p>
</blockquote>
<p>Our aim should be to have accessibility embedded in the team processes so everyone knows their role and no one person is taking on all the accessibility work and responsibility.</p>
<h3>Treat accessibility issues as bugs</h3>
<p>This means we treat accessibility issues as what they are - bugs, not features. Any other situation where users are having barriers placed in front of them by the code or design would be jumped on, but for some reason if it is an accessiblity concern it tends to get put way down on the backlog.</p>
<p>Having the accessibility-issues-as-bugs mindset will push us more to fixing any accessibility issues in the current ticket within that ticket’s timeframe rather than spinning off another ticket to fix it later.</p>
<h3>Real-world testing</h3>
<p>Where possible we should be including people with assistive needs in all stages of our product design and development. This goes hand-in-hand with real device testing to ensure what we are producing both satisfies the needs of the user and the abilities of the technology they use.</p>
<p>How users have their assistive technology or adaptations configured can impact on how they interact with the product, so getting this insight early on is key to developing a truly accessible product. Try to work in regular user testing throughout the project.</p>
<h3>Consider accessibility in every ticket</h3>
<p>Sometimes accessibility will obviously not apply, but if we get into the habit of at least thinking of how accessibility might play into a ticket then we go a long way to catching issues before we write any code, and that is where the savings really come. See Definition of Ready below for more on this.</p>
<h3>Implement robust testing</h3>
<p>Good accessibility testing means multiple stages and types of tests.</p>
<p>Testing should begin at the design phase and follow through all the way to go-live and beyond. The person responsible for delivering the content, design or code is ultimately responsible for ensuring this testing is done and what is delivered is accessible.</p>
<p>Designs in particular need to consider how different groups of users will perform the required tasks and how the design will adapt to different user preferences such as font size. Questioning designs before they are passed onto the development team is an important aspect of this. All this information needs to be communicated to the development team .</p>
<ul>
<li>manually triggered automated testing on design documents, during code development, code reviews and QA testing</li>
<li>automated testing as a pipeline tool for continual baseline assurance</li>
<li>manual testing to catch issues automated tooling cannot, again at all stages of development. This can range from simple keyboard tests to more complex assistive technology testing.</li>
</ul>
<p>Testing is something which team members need to be aware of and then know how to conduct so there is a bit of a learning curve. Like many skills this will become easier with continual application.</p>
<p>Some tests such as screen-reader checks will require more effort but a few simple commands can cover most of the requirements.</p>
<p><a href="/posts/testing-strategies-and-accessibility/">Read more about testing strategies</a></p>
<h4>Add automation but don’t rely on it</h4>
<p>Automated tests in accessibility are useful but should not be relied on to take care of your accessibility concerns for you. Automated tests can only check against specific criteria and a lot of accessibility depends on context and wider aspects of relationships and information conveyed by the page as well as different states.</p>
<p>Because automated tests do not have the contextual awareness needed to check effectively they are often cited as only being able to find around 30-40% of issues.</p>
<p>However this does not mean that automated tests are not useful. They should be seen as a baseline - a zero failure in automated tests is an easy benchmark but should be seen as the minimum start-point.</p>
<p>Automated testing in a pipeline can be very useful in flagging any issues creeping in, it will allow you to see when things are getting worse, but also when things are getting better. If the team has access to this data it can be just the mental boost they need.</p>
<p>Manual testing will be required to take us beyond that and into true accessible products.</p>
<h3>Definition of Ready</h3>
<p>When looking at work which needs to be brought in to a sprint, take some time to look at how accessibility requirements might be addressed.</p>
<p>Be really specific when asking questions - for example “How will someone using speech recognition access the information on this page and navigate successfully?”</p>
<p>Annotating designs in Figma or Mural can help convey important information about desired page markup (such as relationships between content, heading hierarchy, non-visual copy, or use of <a href="/posts/aria/">ARIA</a>) to developers and will help inform questions before the work is started.</p>
<p>Some questions to ask:</p>
<ul>
<li>how will this work on smaller viewports?</li>
<li>does the content have the appropriate reading level, are we using language which can cause issues such as metaphors?</li>
<li>what is the heading hierarchy - does it follow the visual hierarchy?</li>
<li>will someone who cannot see the screen still get the information and the relationships between the content?</li>
<li>do all the interactive elements have focus indicators?</li>
<li>do non-decorative images have meaningful alt text copy written?</li>
<li>are all the different error messages considered and are they helping the user fix the issue they are facing?</li>
<li>do visually-identical links have hidden contextual copy to make them unique for screen-reader users?</li>
<li>are interactive elements without visual labels given meaningful accessible names so they can be addressed by speech-recognition users and understood by screen-reader users?</li>
<li>does this journey require users to remember details from previous pages?</li>
<li>is there a need for the user to do work which we could do for them?</li>
<li>are we making any assumptions? For example are we assuming how a screen-reader would work with this component or have we actually tested it?</li>
<li>be prepared to take a ticket back to the design phase if accessibility issues are raised. It is better to have an accessible design to work from rather than build an inaccessible one and have to retro-fit accessibility later.</li>
</ul>
<p>Think about each user group, for example:</p>
<ul>
<li>screen-magnification users</li>
<li>screen-reader users</li>
<li>switch users</li>
<li>keyboard-only users</li>
<li>speech-recognition users</li>
<li>users with reduced dexterity</li>
<li>English as a second language</li>
<li>users with memory impairments</li>
<li>user who find dealing with numbers difficult</li>
<li>users with cognitive difference such as ADHD, ADD, dyslexia</li>
<li>colour-blind users</li>
<li>users with vision impairments</li>
</ul>
<p>Depending on the specific work a set of accessibility requirements can be drawn up. For example:</p>
<blockquote>
<p>As a sighted keyboard-only user</p>
<p>In order for me to successfully navigate the page</p>
<p>I need interactive elements to show a clear focus indicator</p>
</blockquote>
<h3>Definition of Done / PR ready</h3>
<p>Issues found after the code has been merged will normally become the responsibility of another ticket in the backlog, rather than be fixed at point of causation. It is only by finding and fixing issues as they are created that accessibility will be seen as an integral part of development practices.</p>
<p>The desired outcome here is to effectively add a release gate so we are not introducing accessibility issues to the codebase which will need to be picked up later at a greater cost.</p>
<p>Any accessibility failures should be found and fixed before a PR is raised, but the code review should also look at potential accessibility issues which have been missed.</p>
<p>When looking at the outcomes of a piece of work, specifically when it is a code ticket there are some tests we can do to ensure the work is accessible, beyond what has been raised as part of the Definition of Ready. These checks should be done both by the ticket-holder but also by the code-reviewer.</p>
<ol>
<li>View the page being worked on in the browser. It is often eye-opening how often this simple check can be overlooked. Whenever work is done on a page which is rendered to the user the page should be viewed to verify the output.
<ul>
<li>If the changes are complex also verify how the page renders in different browsers and devices.</li>
</ul>
</li>
<li>HTML validation - while this may not always expose an accessibility issue it is an easy check</li>
<li>Check no issues are raised by automated tools (such as Axe or Wave plugins).</li>
<li>If using a pattern library, verify the page follows the guidance - these often have a lot of advice around how to code up specific examples and are not just for designers.</li>
<li>Check all hidden copy (including those added using <code>aria</code> and <code>alt</code> attributes) are correctly rendering (no-one likes exposed message keys) and translated where applicable.</li>
<li>Finally, manually test the page. This is the most important aspect when it comes to accessibility as so much in the published specs is not supported in assistive technology or cannot be checked with automated tooling.</li>
</ol>
<h2 id="dealing-with-accessibility-debt">Dealing with accessibility debt</h2>
<p>It is often the case that accessibility only gets raised as an issue part-way through a build, or even at the end after launch. Whilst it will now cost more in time and budget to fix any issues found it is still important to tackle any potential accessibility debt.</p>
<p>First you should put in place some processes to avoid technical debt from increasing any more:</p>
<ul>
<li>set up automated checks in the pipeline if possible to help give some baseline metrics and show if the debt is getting larger (and help with a morale boost when you start to reduce it).</li>
<li>use the steps outlined elsewhere in this article to embed accessibility in the team processes and limit the number of new accessibility issues being introduced</li>
</ul>
<p>Then you need to know how big of an issue you may be looking at:</p>
<ul>
<li>find out what you don’t know - use a full accessibilty review of the product to find out what issues you have</li>
<li>make sure issues from this review are recorded on the backlog with an epic so progress can be tracked</li>
</ul>
<p>Work through the issues which you find:</p>
<ul>
<li>triage the issues and prioritise them</li>
<li>set some realistic timescales for fixes</li>
<li>add firebreaks into feature build timelines to allow the team to fix accessibility issues</li>
<li>document the current state and keep track of progress to keep the team and stakeholders informed and motivated</li>
</ul>
<h2 id="wrap-up">Wrap-up</h2>
<p>It may not be perfect immediately. Accessibility is tough and some aspects may seem simple but have hidden complexities. You will likely make mistakes.</p>
<p>Take it one step at a time, it’s easy to get overwhelmed. Processes help keep everyone on the same page and provide structures of support.</p>
<p>Just make it better today than it was yesterday.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Assistive technology</title>
        <link href="https://liptrot.org/posts/assistive-technology/"/>
        <updated>2024-12-11T13:00:00Z</updated>
        <id>https://liptrot.org/posts/assistive-technology/</id>
        <content type="html"><![CDATA[
          <h2>Contents</h2>
<ul>
<li><a href="#contents">Contents</a></li>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#custom-styles">Custom styles</a></li>
<li><a href="#page-zoom">Page zoom</a></li>
<li><a href="#screen-magnifiers">Screen-magnifiers</a></li>
<li><a href="#font-size">Font-size increase</a></li>
<li><a href="#hardware">Hardware assistance</a></li>
<li><a href="#switch">Switch controllers</a></li>
<li><a href="#eye-tracking">Eye-tracking</a></li>
<li><a href="#text-to-speech">Text-to-speech</a></li>
<li><a href="#screen-readers">Screen-readers</a></li>
<li><a href="#speech-recognition">Speech-recognition</a></li>
<li><a href="#high-contrast">Windows High Contrast</a></li>
<li><a href="#user-preferences">User preferences</a></li>
<li><a href="#wrap-up">Wrap up</a></li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>It can be very easy to fall into the trap of only considering the type of browsing and input methods which we ourselves use every day. For many in digital teams this is heavily mouse-oriented, but not thinking about how others may interact with our products can lead to unintentionally excluding users.</p>
<p>Whilst we will be exploring screen-readers and speech-recognition, there are a lot of different adaptations users might use and which we need to consider when building accessible interfaces.</p>
<h3>The economics of assistive technology</h3>
<p>Before we look at specific assistive technology we should take a moment to look at how disabilities can affect the performance of some technology.</p>
<p>Users with disabilities are more likely to have a lower disposable income than those without. This can have a knock-on effect in the age of hardware or software being used due to the costs involved in keeping them up-to-date. On top of this is the concern that any software update - either to the operating system, the standard software or the assistive software - will render the computer unworkable or mean time having to trouble-shoot or relearn interfaces.</p>
<p>For this reason it may be that the user of some of the following may not be using the latest version of the technology stack. This along with the additional processing overheads of running assistive technology can mean poor performance metrics for websites can have a greater impact on these end-users.</p>
<h3>Do not assume conditions based on tools</h3>
<p>When looking at supporting particular assistive technology it can be helpful to concentrate on the tool first. These tools are used by a myriad of users for many different conditions so do not assume that a particular tool is only used by one group or that one group only uses one tool. Users are just as likely to jump between tools based on their current needs.</p>
<p>For example a user with low vision may use a screen-magnifier but switch to a screen-reader when they become tired. Users may also have multiple conditions and use a selection of tools in concert.</p>
<h3>Design for no tools</h3>
<p>Something else to bear in mind is that not all users who would benefit from assistive technology may be using it. They may not be aware of the existence of the different options, or they may not be confident enough to install and use it, or they may just not consider themselves as needing it. We should build our interfaces to as much as possible be accessible without users having to rely on tools to make it so.</p>
<h2 id="custom-styles">Custom styles</h2>
<p>When we design a page we are making a lot of assumptions about our user, but it is also not possible to produce a design which accomodates all users to the extent that might be optimal for them.</p>
<p>Whilst this should not stop us designing as accessible a page as possible from the start, we need to be aware that some users may need to go beyond what we provide and we should not prevent them from adapting our design themselves.</p>
<p>The most common way a user may adapt our page styles is through use of a custom style plugin for their browser. This will allow them to change various elements of the page.</p>
<p>Something to be aware of here is that the more specific our styles are (for example styles set on the element itself, rather than using the css cascade), the more styles the user then has to override with their own and the harder it will be for them to adapt your site.</p>
<figure>
    <img src="/assets/images/modules/stylebot.png" data-size="implicit" alt="A before and after of a page using Stylebot to change the page. The links have been updated from green on grey to a larger font with white on pink. The body font has also been updated to a more spaced out one. The Stylebot editor can be seen to the side.">
    <figcaption>Stylebot browser plugin editor transforming a BBC page to more suit the user</figcaption>
</figure>
<h2 id="page-zoom">Page zoom</h2>
<p>This is something which all desktop browsers have available to them. These allow the entire page to be zoomed up to around 500% in increments.</p>
<p>Something to note here is that this will typically trigger a mobile viewport style, so even if you are not expecting mobile users you still need to develop and robustly test a mobile-friendly style. These users will be using keyboard on that view rather than their fingers as they would on an actual mobile, so we need to test that mobile view with keyboards too.</p>
<figure>
    <img src="/assets/images/modules/page-zoom.png" data-size="implicit" alt="A website on a desktop browser. The page has been zoomed and is showing the mobile layout.">
    <figcaption>A zoomed page can trigger a mobile view even on a large monitor.</figcaption>
</figure>
<p>As some users may require a higher level of zoom than this allows, they may prefer an alternate method or combine this with another.</p>
<h2 id="screen-magnifiers">Screen-magnifiers</h2>
<p>This is a piece of software which might be either built into the operating system or installed and which acts as a magnifying glass on the screen. These can take various forms:</p>
<ul>
<li>full-screen - the entire screen is zoomed</li>
<li>split-screen - half the screen is retained at standard zoom and half shows the zoomed view. This can help users with orientation on a page.</li>
<li>picture-in-picture - essentially a digital magnifying glass shows a small section zoomed</li>
</ul>
<p>They can be set to different levels of magnification suited to the user and the user can adjust the magnification to suit different situations.</p>
<figure>
    <img src="/assets/images/modules/magnification.png" data-size="implicit" alt="Screenshot of an article with a box floating in front of it. The box contains a zoomed version of the text under it.">
    <figcaption>A screen-magnifier using a picture-in-picture format. The floating box follows the mouse pointer.</figcaption>
</figure>
<p>The main thing to be aware of with this type of magnification is that the user has a much reduced view of the wider page - it could be as small as a few words across. This can then impact on the understanding of how elements visually relate to each other but also on cause-and-effect interactions.</p>
<p>For example when a user clicks on a button and something happens at the top of the page, someone using a screen-magnifier might not see this - to avoid this we should look to closely locate triggers and the things they trigger so the effect is easier to understand.</p>
<h2 id="font-size">Font-size increase</h2>
<p>Browsers also have the option to just increase the size of the text. This tends to be hidden in the browser settings menus (except for Safari on iOS) but generally allows text to be increased up to 200%.</p>
<p>This is useful because it preserves the layout of the page (it doesn't switch to a different viewport layout like page zoom does) and be a better user experience because of this. However because it is not something which is tested during development we tend to see broken layouts when this is employed.</p>
<figure>
    <img src="/assets/images/modules/font-size.png" data-size="implicit" alt="Screenshots of a Sky Sports menubar at 100% and 200% font-size. The 200% has lost several menu items and account links have had other links overlap them.">
    <figcaption>Not testing for font-size preferences can mean users may not even be able to access some of your content or it may become impossible to read.</figcaption>
</figure>
<p>Container heights set in absolute (rather than font-size-relative) units mean they don't scale along with the font. This means text either gets cut-off or overlays other content.</p>
<figure>
    <img src="/assets/images/modules/font-size-fix.png" data-size="implicit" alt="Screenshot of the same Sky Sports menubar. All menu options are now visible.">
    <figcaption>A few tweaks to css allows the menu to scale gracefully and still be fully usable.</figcaption>
</figure>
<h2 id="hardware">Hardware assistance </h2>
<p>Outside of software assistance, some users may also use hardware to assist them. An example of this is a keyboard overlay to help a user with mobility issues to only trigger the key they want and not inadvertantly trigger neighbouring keys.</p>
<p>These type of adaptations may not directly impact how the user interacts, but is worth keeping in mind as it can illustrate the difficulty some users may have in just typing. This is why we should try and help users reduce the amount of typing they need to do, either in the design of the page or in being forgiving of data submitted in form fields.</p>
<p>As some users may also require their mobile to be held in a cradle it might be that they are unable to change orientation. So we should also make sure we are not forcing any particular orientation to view our sites.</p>
<h2 id="switch">Switch controllers</h2>
<p>This is a group of hardware and software tools which allow users who have limited mobility to interact with a screen using just a single click at a time with no mouse. They consist of one or two physical switches mapped to specialist software. Mac OS has switch support built in.</p>
<p>The switch software moves through the options available and the user activates the switch when the desired one is highlighted.</p>
<p>For data input the user will use a virtual keyboard, first selecting the line of keys the desired character sits in, then the second switch trigger will select the key on that row.</p>
<figure>
    <img src="/assets/images/modules/switch-keyboard.png" data-size="implicit" alt="Mac OS' virtual keyboard for switch users. One row of keys is highlighted.">
    <figcaption>MacOS virtual keyboard for switch.</figcaption>
</figure>
<p>For on-screen navigation the user will trigger first a vertical line moving across the screen, stopping it when it is over the target. Then a horizontal line moves across the screen and again the user will action the switch to create a cross-hairs where the two intersect.</p>
<figure>
    <img src="/assets/images/modules/switch-navigation.png" data-size="implicit" alt="Mac OS' switch mouse control showing how horizontal and vertical lines are used to create a crosshair to target where to click. For each of the vertical and horizontal coordinates a set of lines first sets the initial range in which a second line allows fine-grained placement.">
    <figcaption>MacOS virtual keyboard for switch. For each click, multiple switch activations are required.</figcaption>
</figure>
<p>As you can see, using a switch will greatly slow down a user compared to a mouse user, and entering text can be time-consuming. We should also look to ensure there is adequate space between controls to avoid mis-clicks.</p>
<h2 id="head-tracpointerking">Head pointer</h2>
<p>This was addd to Mac OS and makes it easier for those who might otherwise use a Switch device. It allows head movement to be mapped using a webcam and to control a mouse pointer's movements. Using alternative pointer options also allows commands such as clicks, key-presses and shortcuts to be added using facial expressions.</p>
<figure>
    <img src="/assets/images/modules/head-tracking.png" data-size="implicit" alt="Mac OS' alternative pointer options showing how raiing eyebrows can be used to trigger a mouse-click.">
    <figcaption>MacOS alternative pointer options. <a href="https://youtu.be/NL0x-b6zZ8Y?si=JWzWIb4LtJWjmSzt&t=25">Watch a video from a head pointer user on YouTube</a></figcaption>
</figure>
<h2 id="eye-tracking">Eye-tracking</h2>
<p>Eye-tracking software translates the user's gaze (tracked using a camera and LED targeted at the user's eye) to mouse clicks or gestures. Like switch devices it allows users who find it tiring, difficult or impossible to use a mouse to interact with sites.</p>
<p>As with switch users, although eye-tracking software may also include zoom options to increase accuracy, we should look to provide margin for error in making sure our controls are both large enough and well spaced. Eye-tracking also uses on-screen keyboards to allow users to enter data.</p>
<figure>
    <img src="/assets/images/modules/eye-tracking.png" data-size="implicit" alt="An eye-tracking user has a screen in front of them with Facebook loaded. They are using an on-screen keyboard to type a message.">
    <figcaption>An Eyegaze user interacting on Facebook. <a href="https://www.youtube.com/watch?v=bsLyBpoOrq8">Watch a video about eye-tacking on YouTube</a></figcaption>
</figure>
<p>Eye-tracking also has similarities with other assistive technology such as screen-readers and speech-recognition in that they are code-aware - such as being able to identify links on a page. For this reason it is important to use the correct elements when marking up the page.</p>
<p>One other consideration is that the user is having to use their eye movement for all mouse movement and keyboard entry, so their time looking at the screen is increased, so fatigue can become an issue. Help these users by avoiding overly bright content and distracting animations which pull their gaze away from their task.</p>
<h2 id="text-to-speech">Text-to-speech</h2>
<p>This is software which reads out the content on the page. There are lots of different versions as well as some which are part of the operating system or browsers.</p>
<p>These are helpful for some low vision users, but can also help with cognitive conditions, such as dyslexia and other reading difficulties, and those who find reading tiring.</p>
<p>Most will provide reading aides as well - for example MS Edge browser's Read Aloud will highlight the line and each word as it is read out.</p>
<figure>
    <img src="/assets/images/modules/readaloud.png" data-size="implicit" alt="Edge's Read Aloud on an article, the current line of text is highlighted in blue and the words are highlighted in yellow as they are read.">
    <figcaption>The Edge browser's Read Aloud highlighting content as it is read.</figcaption>
</figure>
<p>Unlike screen-readers, they do not expose accessibility information or hidden copy, purely reading the visible content. They do not announce if the copy is a link for example and will not read out image alt text.</p>
<p>Well structured content where sentence length is not allowed to become too long can help users take in spoken information easier. A similarity with full screen-reader software is that ensuring the language of the page is set correctly will allow the software to load the correct voice engine to provide accurate pronunciation.</p>
<h2 id="screen-readers">Screen-readers</h2>
<p>Screen-readers are software which produces an audible, or braille, version of what is on-screen. They are available on all operating systems, including mobile, both as part of the OS and as installable software.</p>
<p>Screen-reader is a little of a misnomer as they do so much more than just read the screen and so are more complex to use and have a lot more options than a text-to-speech reader. Along with the content, a screen-reader will announce a set of meta data for that content which helps the user to figure out the page structure and how the interface works.</p>
<p>It is also assumed that all screen-reader users are blind but partially-sighted and those with some cognitive conditions find them helpful too.</p>
<p>The information which gets passed in addition to the content includes data about the type of content (input, heading, link and so on) along with any status information (such as a radio input being selected or not).</p>
<p>For example with a simple heading such as this:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h2</span><span class="token punctuation">></span></span>Extremely small margins<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h2</span><span class="token punctuation">></span></span>
</code></pre>
<p>a screen-reader may hear:</p>
<blockquote>
<p>&quot;Extremely small margins, heading, level two&quot;</p>
</blockquote>
<p>So the user can tell this content is a heading but also that it is a level two heading, information a visual user may get from the visual styling.</p>
<p>Find out more about <a href="/posts/accessible-names/">accessible names</a> and <a href="/posts/accessibility-tree-and-assistive-technology/">how screen-readers work</a>.</p>
<p>Screen-readers also allow users to move around the page in a non-linear manner to prevent them from having to read each page from top to bottom. For example a user could move from heading to heading in order to understand the page structure and find the section they want.</p>
<p>This data is built from the code we write. This means we can have significant impact on what gets passed to the screen-reader and what gets ignored, as well as being able to manipulate the information sent. This is why screen-readers are often highlighted as having particular issues when it comes to accessibility as we can actually make things worse for the end-user if we aren't certain about the effects the code we write has.</p>
<h2 id="speech-recognition">Speech-recognition</h2>
<p>This allows the user to navigate and enter data using just their voice. This software is built into both Windows and Mac, but there are also commercial options.</p>
<p>The user typically interacts by stating the name of the thing they want to click. Because of this they rely heavily on the visual text associated with the control (for example the link text) or well-established conventions (such as “close” for a cross icon on a popup).</p>
<figure>
    <img src="/assets/images/modules/speech.png" data-size="implicit" alt="Screenshot of an article with some social icons. The thunbs up and thumbs down icons do not have any text except numbers alongside. A share icon has the word 'share' next to it.">
    <figcaption>Providing visible text alongside icons can help speech-recognition users with trigger words. The two icons with just numbers may cause problems.</figcaption>
</figure>
<p>Sometimes using the visible text, or trying to guess when there is no text, does not work. Some speech-recognition software allows the user to request the names of elements be displayed.</p>
<figure>
    <img src="/assets/images/modules/speech-names.png" data-size="implicit" alt="Screenshot of an article with some social icons. The names of each icon have been overlaid.">
    <figcaption>Whilst these icons have common names for them, such as “Like”, at the start of their accessible names, the length and complexity can make it difficult to trigger, even when exposed.</figcaption>
</figure>
<p>Different speech-recognition software has different tolerances for how much of the accessible name is needed to trigger a response. If they are unable to trigger the control in this way they can ask the software to number elements and then choose one of those numbers.</p>
<figure>
    <img src="/assets/images/modules/speech-numbers.png" data-size="implicit" alt="Screenshot of an article with each link numbered.">
    <figcaption>Numbering makes for much easier targeting.</figcaption>
</figure>
<p>As a last resort and as a way the user can also perform more complex interactions, such as drag and drop, the user can overlay a grid (called a ”mouse grid”). Each square is numbered and choosing a square reveals another grid inside similarly numbered. By repeated choices the user can direct a click or other action.</p>
<figure>
    <img src="/assets/images/modules/speech-grid.png" data-size="implicit" alt="Screenshot of an article with a grid overlaid. Each square has a number inside.">
    <figcaption>Grids allow targeting even if no accessible name has been assigned or numbering fails.</figcaption>
</figure>
<p>When it comes to entering data (such as in a form), doing this by dictation can be difficult if the software doesn't pick up the word correctly. Where possible we want to again avoid having the user type unnecessarily, so offering options which don't involve typing (such as picking from a list) can be helpful.</p>
<h2 id="high-contrast">Windows High Contrast</h2>
<p>Windows has a High Contrast set of themes which the user can choose from and even edit to an extent. Note this is different from <a href="#user-preferences">high contrast user preference settings</a>.</p>
<p>These are primarily used by people with low vision (<a href="https://webaim.org/projects/lowvisionsurvey2/#at">around 30% of low vision users use high contrast modes</a>), where the increased constrast helps them pick out elements on screen. They are also used by people who find the standard display too bright as it allows them to enforce a theme which suits them better.</p>
<p>When the user chooses to use one of these themes it is to enable them to read the page so the visual design must take second place to practical readability.</p>
<figure>
    <img src="/assets/images/modules/whc.png" data-size="implicit" alt="Comparison screenshots of an article with and without windows high contrast mode active. In the active one, images are not affected, but background colours have been removed and links and buttons have their colours set by the theme or user.">
    <figcaption>Windows High Contrast in action. Some design is sacrificed to ensure readability.</figcaption>
</figure>
<p>Windows High Contrast mode has several preset options but also allows the user to edit the default colours. This allows the user to adjust the colours to best suit their own requirements.</p>
<figure>
    <img src="/assets/images/modules/whc-edit.png" data-size="implicit" alt="Screenshot of the theme edit options for Windows High Contrast. The user can set colours for the page background, text, hyperlinks, inactive text, selected text and button background and text.">
    <figcaption>Windows High Contrast theme editor allows the user to adjust the important aspects of the page to benefit readability.</figcaption>
</figure>
<p>As we have seen already, using semantic HTML is important to accessibility and it is here too. By using standard HTML elements for buttons and links we can ensure a consistent experience for Windows High Contrast users. For example Windows High Contrast <a href="/demos/whc-aria/">does not recognise aria attributes when assigning styles</a>.</p>
<p>Whilst css can be used to tweak our designs in Windows High Contrast mode this should be done very sparingly and in a very specific way. This is because we can't be sure what colours the user might use so we need to be careful not to end up with something unreadable by forcing specific colours.</p>
<h2 id="user-preferences">User preferences</h2>
<p>When we talk about user prefernces we are looking at the various options the user can set via their operating system's settings panel. Whilst these might not do anything with a website on their own, they give us the ability to respect these preferences when we are coding our interfaces.</p>
<h3>Colours</h3>
<p>As we have seen already users may want to adjust the colours on-screen for a variety of reasons, from reducing fatigue to making it easier to percieve elements or make reading easier. There are a few options which allow this.</p>
<h4>Dark and light mode</h4>
<p>We can check for the active operating system dark or light theme and align our site's dark or light mode with it using the <code>prefers-color-scheme</code> media query. However we should always provide an on-site switch to let the user change the theme independently of the OS.</p>
<h4>High contrast</h4>
<p>High contrast is where the operating system performs a system-wide colour switch. Although both Windows and Mac also provide options to heighten the standard contrast used across the OS this doesn't affect web pages automatically. We can implement changes however using the <code>prefers-contrast</code> css media query.</p>
<h4>Inverted colours</h4>
<p>Whilst Macs provide the option to invert colours it is not customisable by the user, but we can help designs work with it via css <code>inverted-colors</code> media queries. Just as with Windows High Contrast care should be taken not to override the reason the user enabled it in the first place.</p>
<h3>Motion</h3>
<p>Some users may have conditions which are triggered by animation - especially large animations or repeating ones. Anything from carousels to parallax scrolling to advertising can cause unwanted distraction or even a physical reaction, such as intense headaches or nausea.</p>
<p>The user can request reduced motion at the operating system level and we can hook into this with the <code>prefers-reduced-motion</code> css media query to disable or tone down animations and movement.</p>
<p>This can be demonstrated using a carousel (on BBC's iPlayer site) which has been coded to respect this user preference.</p>
<figure>
    <video src="/assets/images/modules/motion-on.mov" controls="show"></video>
    <figcaption>With reduced motion off, the carousel movement is animated with new panels sliding in from the right.</figcaption>
</figure>
<figure>
    <video src="/assets/images/modules/motion-off.mov" controls="show"></video>
    <figcaption>But with reduced motion enabled the animation is removed and the carousel snaps from one view to the next.</figcaption>
</figure>
<p>Something as seemingly small as this can make the difference between a user being able to access content or not.</p>
<h2 id="wrap-up">Wrap up</h2>
<p>When we consider these different methods of interaction when designing and building our interfaces we are more likely to deliver an accessible product at the end.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>ARIA</title>
        <link href="https://liptrot.org/posts/aria/"/>
        <updated>2024-11-07T13:00:00Z</updated>
        <id>https://liptrot.org/posts/aria/</id>
        <content type="html"><![CDATA[
          <h2>Contents</h2>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#what-can-it-be-used-for">What can it be used for?</a></li>
<li><a href="#the-rules-of-aria">The rules of ARIA</a></li>
<li><a href="#what-is-aria-not">What is ARIA not?</a></li>
<li><a href="#support-vs-the-specification">Support vs the specification</a></li>
<li><a href="#roles-to-avoid">Roles to avoid</a></li>
<li><a href="#things-to-consider-when-using-aria">Things to consider when using ARIA</a></li>
<li><a href="#wrap-up">Wrap-up</a></li>
<li><a href="#further-reading">Further reading</a></li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>ARIA stands for Accessible Rich Internet Applications. It is a set of attributes which are applied to HTML elements to provide additional information to users of <a href="/posts/assistive-technology/">assistive technology</a>. <a href="https://www.w3.org/TR/wai-aria/">There is an entire specification for it (W3C).</a></p>
<h2 id="what-can-it-be-used-for">What can it be used for?</h2>
<p>ARIA has a lot of different uses but the main theme is to improve a user's understanding of the page.</p>
<p>Let's have a look at some examples of some of the more common use-cases of ARIA which you might come across.</p>
<h3>Providing accessible names</h3>
<p>An element's <a href="/posts/accessible-names/">accessible name</a> can be modified by using one of a couple of ARIA attributes, <code>aria-label</code> or <code>aria-labelledby</code>.</p>
<p>For example, it can help provide an accessible name to a button which may just have an icon:</p>
<img src="/assets/images/modules/aria-carousel.png" data-size="implicit" alt="A carousel button consisting of a circle with a right-facing arrow inside.">
<p>A button like this might be coded like this, where the image is applied using CSS:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>icon-arrow-r<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<p>This is an issue because whilst there is a <em>visual</em> affordance to what the button does and what we might expect if we click on it, a screen-reader user may not be able to benefit from this. To a screen-reader user this would just be announced as:</p>
<blockquote>
<p>&quot;Button&quot;</p>
</blockquote>
<p>Not very useful. This is because the <code>button</code> has no current accessible name - it has no contents and no attributes which would provide one.</p>
<p>By using the ARIA attribute <code>aria-label</code> we can make sure it has a meaningful accessible name:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Next<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>icon-arrow-r<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<p>To a screen-reader user this would now be announced as:</p>
<blockquote>
<p>&quot;Next, button&quot;</p>
</blockquote>
<p>Much better.</p>
<p>As well as providing an accessible name where one is missing, we can also override the current accessible name. In the example below we are overriding the one provided by the content (&quot;Change&quot;):</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Change name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Change<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p>Now instead of &quot;Change&quot; the link has an accessible name of &quot;Change name&quot; and will be announced to screen-readers as:</p>
<blockquote>
<p>&quot;Change name, link&quot;</p>
</blockquote>
<p>The <code>aria-label</code> attribute takes content directly - you place the content in the attribute itself. The <code>aria-labelledby</code> attribute is different in that it takes one or more ID <em>references</em>. This means we can re-use existing content as the accessible name.</p>
<p>The accessible names of the elements with the referenced IDs will be used as the accessible name. You need to add the IDs to the attribute <em>in the order in which you want them to be announced</em> by the screen-reader.</p>
<p>You can self-reference the element the aria is on to include its own natural accessible name in the computed one. For example, the link below has an accessible name of &quot;Continue reading Travelling to Newcastle&quot; because it is referencing the preceding <code>h2</code> as well as itself to construct a compound name:</p>
<div class="example example--render">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h2</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>article-title-1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Travelling to Newcastle<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h2</span><span class="token punctuation">></span></span>
...
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>article-link-1<span class="token punctuation">"</span></span> <span class="token attr-name">aria-labelledby</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>article-link-1 article-title-1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Continue reading<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<img src="/assets/images/modules/aria-labelledby.png" data-size="implicit" alt="Chrome devTools showing the accessible name computed from two content items referenced by aria-labelledby">
</div>
<h4>Potential mishaps</h4>
<h5>Getting reference IDs out of order</h5>
<p>As mentioned, the order of IDs in <code>aria-labelledby</code> matters and getting it wrong can have bad consequences, from changing the meaning of an accessible name to making a control difficult to target for speech-recognition users.</p>
<h5>Misunderstanding of the impact</h5>
<p>Using either of these attributes will override any natural accessible name of the element. So the text content of a <code>button</code> will be overriden by these attributes, as will the association with a <code>label</code> for a form <code>input</code>.</p>
<p>Not understanding the impact of this and <a href="https://www.w3.org/TR/html-aam-1.0/#accname-computation">how accessible names are calculated (W3C)</a> can lead to the wrong accessible name being delivered to the user.</p>
<h5>Limits of aria-labelledby</h5>
<p>Using <code>aria-labelledby</code> will only &quot;hop&quot; once. So you can reference another element and its accessible name (even if created using an <code>aria-label</code>) will be used. However if the element you target uses <code>aria-labelledby</code> then that attribute will be ignored and other accessible name sources will be used. This is to stop circular references.</p>
<h5>Fragile ID references</h5>
<p>Because <code>aria-labelledby</code> uses IDs it is possible to inadvertently end up with an incorrect accessible name.</p>
<p>For example if you mistakenly have more than one ID with the same reference (they should be unique) the browser will pick the first matching one it finds. This may not be the one you expected and you can end up with a different accessible name to the one you wanted.</p>
<p>Similarly if the target ID is removed or changed this will affect the accessible name of the element with the attribute, potentially removing its accessible name entirely.</p>
<p>For this reason I recommend developer teams only ever use IDs for ARIA so their purpose is clear. If you use IDs as testing hooks I recommend you use <code>data-</code> attributes instead - for example <code>data-test=&quot;card1&quot;</code>. This separates concerns and reduces the potential for mistaken altering or deletion of IDs.</p>
<h5>Hidden names</h5>
<p>It can be too easy to add <code>aria-label</code> to an icon button (as above) without thinking if the name is obvious to all users.</p>
<p>Speech-recognition users will not know what name you used so have to try to interpret the image - does the arrow mean &quot;right&quot; or &quot;next&quot; or something else?. They need to use the accessible name in order to target that button using speech Whilst there are fallback strategies they can use we should always strive for the simplest option. For this reason I'd recommend using visible text alongside the icon instead of ARIA.</p>
<h5>Not having the visual copy at the start</h5>
<p>You should also be careful to always have the <strong>visible</strong> content as the start of the accessible name. This makes it easier for speech-recognition users to interact with it as some software will only match the connection when the accessible name starts with what the user says.</p>
<p>For example doing the following will cause an issue as the speech-recognition user will not be aware of how you have manipulated the accessible name and will say &quot;Click change address&quot; to access the link:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Change Bob's address<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Change address<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p>Instead do this which places the entire visible text at the start of the computed accessible name:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Change address for Bob<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Change address<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p>What we don't want to do is make it better for one group (screen-reader users) whilst making it more difficult for another group (speech-recognition). This is one of the balancing acts we need to make with accessibility.</p>
<h5>Maintenance slip-ups</h5>
<p>Finally, because aria attributes are less visible it can be possible for the visible copy to get updated and the ARIA attributes to be forgotten about. This can lead to a mismatch between the two.</p>
<p>Take this example which works for screen-reader and speech-recognition users:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Change address<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Change<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p>Then some updates are made to the copy and the link text is updated to &quot;Edit&quot;, but the aria-label copy is missed (as it is not readily visible):</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Change address<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Edit<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p>Now a speech-recognition user will not be able to action the link by saying &quot;click Edit&quot; (the visible text) because that is no longer a match for the accessible name.</p>
<h3>Providing additional information</h3>
<p>The <code>aria-describedby</code> attribute operates in the same way as <code>aria-labelledby</code> in that it takes one or more ID references, though in this case the result affects the element's <strong>accessible description</strong>. The accessible description is announced after the accessible name and a short pause and is there to provide some supporting information.</p>
<div class="note note--insight">
<p>You might be wondering about <code>aria-description</code>.</p>
<p>If <code>aria-labelledby</code> works like <code>aria-describedby</code>, then surely there must be an <code>aria-description</code> to work like <code>aria-label</code>?</p>
<p>There is but this attribute is still in the <a href="https://w3c.github.io/aria/#aria-description">draft stage of the specification</a> so it <em>should not be used</em> as support is patchy or non-existent.</p>
</div>
<h4>Potential mishaps</h4>
<p>Just as with <code>aria-labelledby</code>, <code>aria-describedby</code> can suffer from the same issues with having to reference another element.</p>
<h5>Semantics are stripped</h5>
<p>Another thing to note is that the content referenced will be stripped of any semantics, so if it includes something such as a link or a heading only the text will be carried over.</p>
<p>Take this example:</p>
<div class="example example--render">
<label for="ref">Order reference</label>
<div id="order-hint">
    Your order reference is 10 digits, 
    <a href="...">find my order</a>
</div>
<input id="ref" type="text" aria-describedby="order-hint">
<br/>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>ref<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Order reference<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>order-hint<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    Your order reference is 10 digits, 
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>find my order<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>ref<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token attr-name">aria-describedby</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>order-hint<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
</code></pre>
</div>
<p>The accessible description will be announced as:</p>
<blockquote>
<p>&quot;Your order reference is 10 digits, find my order&quot;</p>
</blockquote>
<p>Note no mention is made that there is a link present.</p>
<p>For this reason avoid referencing anything other than simple text with these attributes.</p>
<h5>Complex markup can be truncated</h5>
<p>More complex markup can also result in the screen-reader stopping after the first part, despite the entire block being referenced. For example:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>app-hint<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>Tell us if one of the following is true:<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ul</span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span>You have moved house in the past 3 months<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span>
        ...
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>ul</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
...
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>fieldset</span> <span class="token attr-name">aria-describedby</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>app-hint<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
...
</code></pre>
<p>Whilst other screen-readers may read out all the referenced content this will be annouced by MacOS Voiceover as:</p>
<blockquote>
<p>&quot;Tell us if one of the following is true&quot;</p>
</blockquote>
<p>This is a good example of why we test with multiple screen-readers.</p>
<h5>There is a delay in announcing a description</h5>
<p>Finally, as already mentioned there is a short delay between announcing an accessible name and the accessible description. For this reason you need to be careful of using <code>aria-decribedby</code> on a submit <code>button</code> to reference things like terms and conditions such as in the example below:</p>
<div class="example example--render">
<p id="t&c">By clicking submit I agree ...</p>
<button aria-describedby="t&c">Submit</button>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>t&amp;c<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>By clicking submit I agree ...<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">aria-describedby</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>t&amp;c<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Submit<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
</div>
<p>Because of the delay between announcements, a user is likely to hear “Submit, button” and activate it before they hear the description.</p>
<h5>It may not be heard at all</h5>
<p>An accessible description is categorised as a &quot;hint&quot; to screen-readers. Some screen-readers allow users to turn off hints (which cover a wide variety of announcements) to reduce noise. Unfortunately this can mean that some users may never hear the accessible description.</p>
<p>For this reason avoid putting important information in an accessible description. Where possible ensure accessible descriptions can be accessed as part of the normal document flow so users can find them when hints are turned off.</p>
<h3>Providing update notifications</h3>
<p>Sometimes we might update content on a page without refreshing the page. Think of &quot;success&quot; or &quot;error&quot; notifications, or when just part of a page is updated such as search results.</p>
<p>This can be difficult for screen-reader users as they may not be aware that the content has been updated. We don't necessarily want to place their focus on the new content as this can be very disorientating and unexpected.</p>
<p>So how do we tell the screen-reader user that something has changed without moving their focus? This is where ARIA live regions come in.</p>
<p>A live region is a part of the page which we mark with ARIA to tell the screen-reader that this will be getting updated and it should monitor it. Any new content will then be announced to the user.</p>
<p>For example in the screenshot below we see an ecommerce site with a grid of search results and a set of filters.</p>
<img src="/assets/images/modules/aria-live.png" alt="An ecommerce page with a set of filters in a sidebar. Above the product results is highlighted a count of how many products were found." />
<p>Each time the user changes a filter the grid updates, but a screen-reader user will not know this (or know how many results were returned). This means a screen-reader user will need to figure out that the page is doing this and then will need to explore the page to see how many results were returned.</p>
<p>By using an <code>aria-live</code> region on the result count (highlighted in the screenshot) we can ensure a screen-reader user is told how their filter selection is affecting the number of results. They get this information as a discrete announcement without them having to navigate to the results themselves.</p>
<p>An aria live region is marked up using the <code>aria-live</code> attribute. The value we pass to that attribute is very important as it indicates whether we should interrupt whatever the user is listening to (<code>assertive</code>), or wait until they have finished (<code>polite</code>). By default you should <em>always</em> use <code>polite</code> unless it is something the user really needs to know <strong>right now</strong> (for example if they don't push a button in the next 30 seconds they will lose some data).</p>
<p>For the ecommerce example above we could wrap the result count in a live region like this:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">aria-live</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>polite<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    14 items
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
</code></pre>
<div class="note note--insight">
<p>Note that we do not want to wrap the entire product result grid in a live region as this would cause the <em>entire contents</em> to be read out. ARIA live region announcements should always be short, maybe a sentence at most.</p>
<p>We want to provide the user with a short announcement to tell them enough to provide the information they need. In this case the number of results is ideal.</p>
<p>If you expect the live region to have several updates in a short period (as our filter example may have) then the shorter the announcement the better.</p>
</div>
<p>The default is for an <code>aria-live</code> region to look for text being added to it. By using the <code>aria-atomic</code> attribute we can instruct whether it should just read out the change or re-announce the whole live region.</p>
<p>Whilst we can theoretically ask it to also look for content being removed by also using the <code>aria-relevant</code> attribute, support for this can be hit and miss so this information should be communicated directly. The best way to do this will depend on the situation, but an example might be another live region only visible to screen-reader users.</p>
<p>Some ARIA <code>roles</code> have an implicit <code>aria-live</code> and will act as live regions but with added semantic meaning. These include <code>role=&quot;alert&quot;</code> (defaults to &quot;assertive&quot; announcements), <code>role=&quot;progressbar&quot;</code> and <code>role=&quot;status&quot;</code> (both default to &quot;polite&quot; announcements). They should only be used where their semantics make them appropriate.</p>
<h4>Potential mishaps</h4>
<h5>Not triggering the announcement</h5>
<p>Because live regions only get reliably triggered with <em>new</em> content, you should always add a live region to the page first and <em>then</em> add the new content (a split second is normally enough). Otherwise you may find the screen-reader is seemingly ignoring the live region entirely.</p>
<p>This behaviour can vary between screen-readers and is why we need to test in more than one.</p>
<h5>Providing too much information</h5>
<p>A common mistake is to include an entire component or section as the live region. This will be overwhelming to hear as all the content will be read out every time. This will also make it difficult to identify what has changed, negating the purpose of the live region.</p>
<p>A live region announcement is normally not there to tell the user all the changes, just to make them aware that something has changed - in our example we tell the user the number of products returned, not which products.</p>
<p>Make sure the live region only contains a short piece of text to tell the user what changed. If the page has been laid out well the user will know where to go to explore the actual changes.</p>
<h5>Not considering other users</h5>
<p>Whilst live regions help screen-reader users they do not assist screen-magnification users. If the notification or updated content is remote from their position on the screen these users can still miss the updates. Best practice is to try to place updates as close to where the user is as possible to make them obvious to visual users. This will often be the place where the update was triggered from.</p>
<h5>Skipping testing</h5>
<p>You should always test a live region with multiple screen-readers to make sure it is doing what you expect it to, especially when using <code>roles</code> with implicit live regions.</p>
<p>If you use an <code>assertive</code> live region you can inadvertently make a page or component unusable by a screen-reader as the user will not be able to hear feedback from other actions as they are constantly getting bombarded by live region updates.</p>
<p>When using <code>assertive</code> be careful that is it only going to be providing occasional updates.</p>
<h3>Providing a sense of place</h3>
<p>Often we may use a visual indicator to tell our users that a page in a menu is the one they are looking at:</p>
<img src="/assets/images/modules/aria-current.png" data-size="implicit" alt="A site navigation showing home, blog and guide links. The blog link has a border showing it is selected.">
<p>But screen-reader users who are relying just on the code will not get this purely visual information. The blog link will be announced as any other link:</p>
<blockquote>
<p>&quot;Blog, link&quot;</p>
</blockquote>
<p>This is where the <code>aria-current</code> attribute helps.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Home<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/blog/<span class="token punctuation">"</span></span> <span class="token attr-name">aria-current</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>page<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Blog<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/about/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>About<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span>
</code></pre>
<p>By applying this attribute a screen-reader will now announce the link as:</p>
<blockquote>
<p>&quot;current page, Blog, link&quot;</p>
</blockquote>
<p>In this way ARIA has conveyed the information which was previously just visual. This attribute has a few different options for values besides &quot;page&quot; and can be used to indicate the current item in a range of things, from the current day in a calendar view to the current step in a journey.</p>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current">Read more about <code>aria-curent</code></a></p>
<h4>Potential mishaps</h4>
<p><code>aria-current</code> is quite low risk and the only issue can really come from poor implementation. This could lead to it not announcing at all or not being updated as the interface updates and the user being told they are somewhere they are not.</p>
<h3>Providing state information</h3>
<p>ARIA can help us provide additional information to a user about a component's state which might be difficult to convey in normal HTML.</p>
<h4><code>aria-pressed</code></h4>
<p>As the button below acts like a toggle, either on or off, we need to indicate when the button is pressed (on).</p>
<figure>
<img src="/assets/images/modules/aria-mute.png" data-size="implicit" alt="A sound button with two states, one pressed and one not pressed">
<figcaption>The two states of our button. When pressed the speaker icon changes to show sound is muted.</figcaption>
</figure>
<p>We can use an <code>aria-pressed</code> attribute to communicate the state of the element which will also mean this information is passed onto screen-readers:</p>
<pre class="language-html"><code class="language-html">// Off state
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">aria-pressed</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Mute<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<blockquote>
<p>&quot;Mute, toggle button, not pressed&quot;</p>
</blockquote>
<pre class="language-html"><code class="language-html">// On state
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">aria-pressed</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Mute<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<blockquote>
<p>&quot;Mute, toggle button, pressed&quot;</p>
</blockquote>
<p>You can also see that by adding this state information the <strong>button</strong> <code>role</code> announcement has also changed to a <strong>toggle</strong> which helps a screen-reader user identify how they might expect it to behave before they use it.</p>
<h4><code>aria-expanded</code></h4>
<p>Just like the <code>aria-pressed</code> example, <code>aria-expanded</code> allows us to provide more information to a user which would otherwise only be available visually.</p>
<p>The most common use-case for this is with menus where clicking a button opens additional options, like in the example below.</p>
<figure>
<img src="/assets/images/modules/aria-expanded.png" data-size="implicit" alt="A button labelled Channels with an arrow icon alongside indicating it is open. Below is a list of radio and tv channels.">
<figcaption>The BBC iPlayer Channels button uses `aria-expanded` to indicate when the menu showing the channels is open.</figcaption>
</figure>
<p>Without ARIA a screen-reader user would not know if the button had done anything or not.</p>
<p>However with ARIA added the screen-reader user is told:</p>
 <div class="example example--render">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">aria-expanded</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Channels<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<blockquote>
<p>Channels, button, collapsed</p>
</blockquote>
<img src="/assets/images/modules/aria-expanded-false.png" data-size="implicit" alt="A button labelled Channels with an arrow icon alongside indicating it is closed.">
 </div>
<p>when they land on it, which immediately tells them that clicking this will open something. When they click it, javascript is used to update the attribute and the announcement changes to:</p>
<div class="example example--render">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">aria-expanded</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Channels<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<blockquote>
<p>Channels, button, expanded</p>
</blockquote>
 <img src="/assets/images/modules/aria-expanded.png" data-size="implicit" alt="A button labelled Channels with an arrow icon alongside indicating it is open.">
  </div>
<p>so now they know there is new content for them to access.</p>
<div class="note note--insight">
<p>There is a related ARIA attribute, <code>aria-controls</code> which can be placed on the button too. This is intended to indicate, via an ID reference, the thing which is revealed. However real-world support is pretty much non-existent (only JAWS has support but it is off by default and is hidden in settings) but it can be added for future support.</p>
</div>
<h4>Potential mishaps</h4>
<h5>Discoverablility</h5>
<p>As you may have guessed it is all very well adding in more content, but how will the screen-reader user know where it is?</p>
<p>This is the reason why new content should always be added immediately after the thing which triggered it in the source code. This ensures the next move the user makes will put them in contact with that new content.</p>
<h5>Keeping on top of state</h5>
<p>As with all ARIA state attributes (such as <code>aria-pressed</code>) the key is keeping on top of the current state so the announcement is correct. So when the menu in our example is closed, ensure the attribute is updated to indicate that. This will require javascript to be written to do this.</p>
<h3>Overriding a <code>role</code></h3>
<p>HTML elements all have their own impicit <code>role</code>. This tells the accessibility tree what kind of thing it is, what the user might be able to do with it but also what attributes can be applied to it and some other rules which apply.</p>
<p>You can view the roles provided for each element as part of the detail in the accessibilty inspector in Chrome.</p>
<p>Most of the time a <code>role</code> is derived from the element type and its semantic meaning and while it appears in the accessibilty tree it is not normally defined on the element itself in the HTML. So a <code>button</code> element has a <code>role</code> of <code>button</code>, whilst a <code>ul</code> has a <code>role</code> of <code>list</code>. As you might expect <code>listitem</code> roles (such as the <code>li</code> element) need to be placed as children of a <code>list</code>.</p>
<figure>
 <img src="/assets/images/modules/role-list.png" data-size="implicit" alt="A screenshot of a list of options, one is highlighted. Alongside is a screenshot of a code inspector showing the highlighted item has a role of listitem.">
 <figcaption>Here we can see the role for the <code>li</code> is shown as a "listitem" in the Chrome Accessibility Panel.</figcaption>
</figure>
<p>Some elements like <code>div</code> and <code>span</code> do not have any semantic meaning, so these have what is called a <code>generic</code> role.</p>
<p>Where it gets interesting is that roles can also be explicit. We can set it by using the <code>role</code> attribute. As doing this is essentially changing the element's semantics we need to be very careful when we do this.</p>
<p>For example we can change an <code>a</code> element's role from <code>link</code> to be a <code>tab</code> using the <code>role</code> attribute. As there is no native HTML element for a tab control this is a common use-case:</p>
<div class="example example--render">
<img src="/assets/images/modules/role-tab.png" data-size="implicit" alt="A screenshot of a tab component. The first tab is selected and the related panel is shown below.">
<p>Here is the code for the first tab (note the use of some of the other attributes we have already discussed)</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> 
    <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#past-day<span class="token punctuation">"</span></span> 
    <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>tab<span class="token punctuation">"</span></span>
    <span class="token attr-name">aria-controls</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>past-day<span class="token punctuation">"</span></span>
    <span class="token attr-name">aria-selected</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    Past day
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
</div>
<p>Bear in mind that <code>tab</code> roles require other roles to also be present (<code>tablist</code> and <code>tabpanel</code>) as well as some javascript to handle functionality.</p>
<h4>Potential mishaps</h4>
<p>As mentioned, we need to be super-careful when doing this, not only because we can make interfaces confusing for assistive technology users (and potentially future maintainers!), but also as we need to keep track of the requirements for the role we applied, both to the element we changed but also its children.</p>
<p>Changing an element's role is normally only a last-resort - in reality you are often better off changing the element itself if possible.</p>
<div class="note note--insight">
<h4 id="roles-to-avoid">Roles to avoid</h4>
<p>There are some roles - namely <code>application</code> and <code>menu</code> - which you should generally avoid using in web pages. These require you to add all the interactivity and focus management which are expected when using these roles.</p>
<p>When they encounter one of these roles, screen-readers which use single key navigation will pass their normal navigation keystrokes straight to the browser, so as a developer it is now your responsibility to have them do something. For example the <code>menu</code> role needs you to add key commands (arrow) to navigate up and down the items.</p>
<p>Also bear in mind that whilst screen-reader users may get some idea of what to expect via the <code>role</code> announcement, keyboard-only users will not. This can leave keyboard users wondering why their normal navigation modes are no longer working.</p>
<p>TL;DR - using these doesn’t help the user (often the opposite) and makes life harder for you.</p>
<details>
<summary>More about role="application"</summary>
<div>
You might see this on something like Google's GMail in the browser. But unless you are building something of a similar scale you should avoid using this. Even Adobe's online Photoshop editor does not use this.
<p>This is because when using the web screen-readers typically capture all the users keystrokes and only pass some along directly to the browser. This allows the user to use keys to perform actions within the screen-reader rather than on the page - for example, pressing <kbd>down arrow</kbd> in NVDA or JAWS will read out the next block rather than scroll the page.</p>
<p>When we set <code>role=&quot;application&quot;</code> this tells the screen-reader to send <em>all</em> the keystrokes to the browser. So now you are responsible for supplying all the navigation for screen-reader users <em>and</em> keyboard users. Even if done well (and it is very easy to not do this well), your users may still get confused especially if they were not expecting it.</p>
</div>
</details>
<details>
<summary>More about role="menu"</summary>
<div>
This is supposed to replicate the application menu system where arrow keys are used to move up and down lists of options. Where it should not be used is inside a normal web page, even for something like a navigation menu. Adobe's online Photoshop product does make use of this, but only because it is trying to replicate the desktop application and only in a couple of places.
<p>As with <code>application</code> it is rarely implemented correctly. The <code>menu</code> role in particular has a strict nesting hierarchy of required related roles which increases the liklihood of poor implementation and an unusable interface. Even if done well, the different way of navigating will disorient users and most likey cause some to abandon the site thinking it is broken.</p>
<p>The one place you really don't want to have access issues is in your navigation - use a <code>nav</code> element and normal links and buttons instead.</p>
</div>
</details>
<details>
<summary>Special mention - role="grid"</summary>
<div>
This also requires the developer to manage focus navigation for everything inside it. It also can be disorientating if it is not very intuitive to the user how they go about navigating when inside the grid.
<p>However <code>grid</code> is more of a “be careful” rather than “don‘t” as it can be very useful in certain situations where a different keyboard navigation might be expected or be advantageous. For example a calendar date picker could be marked up as a <code>grid</code> to allow the user to move around a month of dates but still quickly navigate via tabbing to the other controls without having to pass through all of the days.</p>
</div>
</details>
</div>
<h2 id="the-rules-of-aria">The rules of ARIA</h2>
<p>ARIA is really powerful and can be crucial to the accessibility of an interface when correctly used. However the flip-side of this is that you can absolutely make a page less accessible, or even totally unaccessible, if you just throw ARIA at elements without knowing exactly what effect they will have.</p>
<p>With ARIA more than <em>anything</em> else you <strong>need</strong> to test with multiple screen-readers to make sure what you think it does will actually happen.</p>
<p>The power of ARIA has led to a set of rules you must follow when considering adding ARIA to a page:</p>
<h3>Rule 1 - don't use ARIA if you can use HTML instead</h3>
<p>This is sometimes mis-quoted as <q>The first rule of ARIA is do not use ARIA</q>. Whilst a little off the actual meaning of the first rule's wording it is still a good mantra to use as a guide and the <a href="https://www.imdb.com/title/tt0137523/quotes/?item=qt0479119">Fight Club (IMDB)</a> reference makes it stick in people's minds.</p>
<img src="/assets/images/modules/aria-fight-club.png" alt="A scene from the movie Fight Club with the words The first rule of ARIA is you do not use ARIA overlaid.">
<p>The issue with ARIA is that it is sometimes the first thing developers reach for when trying to make a page accessible. In reality it should be used very sparingly and only when there is not an existing HTML way of achieving the same result.</p>
<p>ARIA is often used without fully understanding the impact it will have, often it seems also without testing the output with screen-readers or other assistive technology.</p>
<p>When <a href="https://webaim.org/projects/million/#aria">WebAim performed their survey</a> of the top 1 million homepages they found those with ARIA present had 34.2% more detected errors than those without. Whilst this undoubtably has some relationship to the complexity of those homepages, there is certainly some evidence to suggest that ARIA is not always used wisely.</p>
<p>If you can use a native HTML element instead of building a component using ARIA, do so. ARIA is great for sprinkling on helpful touches or even for creating interctive components which don't exist in native HTML, but all too often ARIA is used to do work which can be done better with plain HTML.</p>
<p>Native HTML elements include a lot of functionality which you might not even be aware of. If you are trying to replicate an HTML element without using the actual HTML element you will likely miss something. You will also save having to write a lot of javascript.</p>
<div class="note note--insight">
<p>As an example of native HTML element functionality which is unknown by those who don't use it all the time, buttons have a feature where a user can cancel a spacebar trigger using the keyboard.</p>
<p>Just like you might cancel a mouse-click by pulling your mouse away before releasing it, keyboard users can hit the tab key whilst the spacebar is still pressed.</p>
</div>
<p>So to avoid using ARIA where we can, instead of writing:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>button<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Save<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
</code></pre>
<p>and then having to add a stack of javascript to handle the different kinds of input the user might use (touch, mouse, keyboard etc) and more javascript to cope with all the native options you didn't know existed, you can write:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span><span class="token punctuation">></span></span>Save<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<p>You just saved yourself a lot of effort and potential for things to break.</p>
<h3>Rule 2 - don't change semantics</h3>
<p>Unless you <em>really</em> need to you should avoid changing the sematics of an element.</p>
<p>This example shows a developer trying to assign a <code>region</code> to a list.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ul</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>region<span class="token punctuation">"</span></span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>my list<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span> ...
</code></pre>
<p>However by assigning the <code>region</code> to the <code>ul</code> it has overridden the native ARIA role, meaning it will no longer be seen as a list and the list items (<code>li</code>) inside will be orphaned.</p>
<p>Because there are rules around how <code>roles</code> interact, such as <code>listitem</code> roles being direct decendants of a <code>list</code> role, this will generate errors on those <code>li</code> elements, but more importantly the list will no longer be announced as a list to screen-readers.</p>
<p>Instead you could wrap the <code>ul</code> with the <code>region</code>:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>region<span class="token punctuation">"</span></span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>my list<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ul</span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span> ...
</code></pre>
<h3>Rule 3 - interactive elements must be keyboard friendly</h3>
<p>This goes for any interactive element, no matter how it has been built, but care should especially be taken when building components with ARIA.</p>
<p>Remember that adding ARIA attributes <em>just adds semantics and information</em> to the element, not any functionality (including being able to interact with it with a keyboard), so we need to add that ourselves.</p>
<h3>Rule 4 - don't hide focussable elements from screen-readers</h3>
<p>Sometimes we might see something like this:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">aria-hidden</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    Am I hidden?
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<p>The <code>aria-hidden=&quot;true&quot;</code> attribute tells the browser to exclude this item from the accessibility information sent to assistive technology. Essentially this hides the item for screen-reader users and those using speech-recognition - but does not hide it visually.</p>
<p>This means speech-recognition users and some screen-reader users will be able to visually see the button. Removing it from the accessibility information will prevent them from using the button they can see which will be confusing.</p>
<p>Screen-reader users will also still be able to focus on the button using the tab key (as this does not hide it from keyboard users) but when they navigate using the screen-reader key commands the button will not be exposed. More confusion. A quick test is that if a keyboard user can still focus on something, then so can a screen-reader user.</p>
<h3>Rule 5 - interactive elements must have an accessible name</h3>
<p>If a user can do something with an element, then that element needs an accessible name. Without an accessible name it is like having a link with no text, the user will not know what it is or what interacting with it might do.</p>
<p>Ideally all interactive components will have an accessible name which is also visually presented so speech-recognition users can see what they need to say to trigger it.</p>
<p><a href="/posts/accessible-names/">See more about accessible names</a></p>
<h3>Rules about what you can use where</h3>
<p>As well as rules around when you should use ARIA, there are also a lot of rules around <a href="https://www.w3.org/TR/html-aria/#docconformance">which ARIA attributes you can use where (W3C)</a>.</p>
<ul>
<li>you can only use some aria attributes on certain <code>roles</code></li>
<li>some <code>roles</code> require other <code>roles</code> to be nested as children (think of lists and list items - a list item without a containing list does not make sense)</li>
</ul>
<p>For example, you cannot add an <code>aria-label</code> to an element with a <code>role=&quot;generic&quot;</code> - which includes elements such as <code>span</code> and <code>div</code> - as this is one of the <a href="https://www.w3.org/TR/wai-aria-1.2/#namefromprohibited">&quot;Roles which must not be named (W3C)&quot;</a>. So this is not valid:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>About you<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> ... <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
</code></pre>
<p>When we talk about not being valid with ARIA, this means it can have either no effect, some odd kind-of-works effect, or a plain-just-unwanted effect. So it is best to stick to valid usage, but then test with actual screen-readers for real-world support.</p>
<p>Invalid use of ARIA is normally caught by the various automated browser plugins (such as AXE or Wave) as it is syntax based and easy to check for automatically.</p>
<h2 id="what-is-aria-not">What is ARIA not?</h2>
<p>What it does not do is provide <em>any functionality</em> beyond the announcement of the attribute.</p>
<p>For example the HTML button below has ARIA added to tell the user that clicking it will expand additional content such as a navigation menu:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">aria-expanded</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Menu<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<p>However as it stands it won't tell the user that the menu state has changed after the button has been clicked. To do that we will need to add javascript to toggle the ARIA attribute (to <code>aria-expanded=&quot;true&quot;</code>). There are a few ARIA attributes which deal with state so for these javascript is necessary to help us improve accessibility.</p>
<p>If we created that button entirely with ARIA (which is possible but not recommended):</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>button<span class="token punctuation">"</span></span> <span class="token attr-name">aria-expanded</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Menu<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
</code></pre>
<p>then we would also need to add things like some way of that button getting keyboard focus (as <code>div</code> elements don't get focus), and provide event handlers for both keyboard and pointer (mouse and touch) users.</p>
<p>ARIA is also purely for users of assistive technology <em>which uses the accessibility tree</em>. That includes screen-readers and speech-recognition. But not all assistive technology makes use of the accessibility tree and these will gain no benefit from ARIA. For example Windows High Contrast will not highlight links and buttons created using ARIA in the same way as it will native HTML links and buttons.</p>
<h2 id="support-vs-the-specification">Support vs the specification</h2>
<p>ARIA support can be somewhat patchy. This is a combination of the complexities of implementation and communication between the various involved parties and conflicting demands on screen-reader development teams.</p>
<p>To correctly support a feature the correct information needs to be passed from the browser into the accessibility tree, which needs to be communicated via an accessibility API to the assistive technology.</p>
<p>All the following can have an impact on whether a feature is available:</p>
<ul>
<li>different browser support and interpretation of spec</li>
<li>different accessibility APIs used</li>
<li>different assistive technology vendors</li>
<li>regression issues or bugs in any of the above</li>
<li>different support depending on browsing modes (for example tocuh vs keyboard, browse mode vs forms mode)</li>
<li>assistive technology vendor heuristics (where deviations from spec are deliberately introduced to improve user experience)</li>
</ul>
<p>This means that just reading and following the spec may not guarantee that the user will get the result you expect. Developers just following the spec and either not fully understanding it or assuming it is fully supported (not an unreasonable thought) are the main reasons why ARIA implementations can cause issues.</p>
<p>Even if you test with a screen-reader and browser and get the result you want, a different screen-reader and browser might mean you get a very different result.</p>
<p>There is an <a href="https://aria-at.w3.org/">ARIA-AT project (W3C)</a> which is trying to standardise how assistive technology announces or reacts to ARIA, but this is in the early stages.</p>
<p>For now, use the specification to guide what might be possible and within the rules of ARIA, but then test robustly in multiple screen-readers and speech-recognition software. If what is in the specification does not work then you will need to look for an alternative solution.</p>
<p>As an example, I was consulting on a webchat project, but the per-specification <code>role=&quot;log&quot;</code> which should have been a perfect fit, worked poorly and inconsistently with different screen-readers and browsers. Instead I used a solution which generated dynamic <code>aria-live</code> regions to achieve the effect we wanted in a robust and consistent way.</p>
<h3>The APG - a warning</h3>
<p>The W3C produces something called the &quot;<a href="https://www.w3.org/WAI/ARIA/apg/">ARIA Authoring Practices Guide</a>&quot; or APG. This on the face of it is a useful guide to different patterns and practices for using ARIA.</p>
<p>However, <strong>this guide is written to the specification</strong>. The patterns it showcases are idealised solutions which are intended as guidelines for browser and assistive technology vendors to aim at for support (a bit like the old <a href="https://www.acidtests.org/">Acid tests for CSS</a>). They do not claim to be real-world usable nor to support mobile or touch interfaces.</p>
<p>Whilst these can be used by teams building sites as a <em>starting point</em>, they should not be just dropped into production without extensive testing with different assistive technology.</p>
<h2 id="things-to-consider-when-using-aria">Things to consider when using ARIA</h2>
<p>There is another phrase which is often used:</p>
<blockquote>
<p>“No ARIA is better than bad ARIA”</p>
</blockquote>
<p>What this means is that in many cases an interface is still <em>usable</em> without ARIA, but if ARIA is added in a poor way it can make it truly inaccessible. So it is worth double-checking any time you are looking at adding ARIA that what you are doing is necessary, is done in the correct way and has been robustly tested.</p>
<p>Here is a short checklist to use when looking at adding ARIA into your codebase.</p>
<ul>
<li>What is the problem I am trying to fix?​ Is ARIA the right tool?</li>
<li>Can I do this without ARIA?​</li>
<li>Would a small redesign solve this instead?​</li>
<li>Am I adding content only for screen-reader users? Will other users benefit?​</li>
<li>Can a speech-recognition user understand what they need to say?​</li>
<li>Will this make the interface audibly noisy?​</li>
<li>Have I followed the rules of ARIA?</li>
<li>Is this supported in the real world?​</li>
<li>Do I have a robust testing structure in place?</li>
</ul>
<h2 id="wrap-up">Wrap-up</h2>
<p>Whilst ARIA is a very powerful tool in making our sites more accessible to users, it is one which needs careful handling. You need to know exactly the reason why you are adding ARIA and what effect you want it to have and then confirm it.</p>
<p>ARIA is simple to add but tougher to test, but not testing can really mess up your site's accessibility if not done.</p>
<p>If you add ARIA to your page or component, you must then test it with multiple screen-readers.</p>
<h2 id="further-reading">Further reading</h2>
<ul>
<li><a href="https://css-tricks.com/aria-spackle-not-rebar/">ARIA is spackle, not rebar (CSS Tricks)</a></li>
<li><a href="https://www.youtube.com/watch?v=kPseLCVlM3">ARIA 101 (YouTube)</a></li>
</ul>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Prioritising accessibility</title>
        <link href="https://liptrot.org/posts/prioritising-accessibility/"/>
        <updated>2024-10-24T13:00:00Z</updated>
        <id>https://liptrot.org/posts/prioritising-accessibility/</id>
        <content type="html"><![CDATA[
          <h2>Contents</h2>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#the-causes-of-accessibility-issues">The causes of accessibility issues</a>
<ul>
<li><a href="#lack-of-awareness">Lack of awareness</a></li>
<li><a href="#deferring-responsibility">Deferring responsibility</a></li>
<li><a href="#assumed-cost-of-implementation">Assumed cost of implementation</a></li>
<li><a href="#assumed-impact-on-deadlines">Assumed impact on deadlines</a></li>
<li><a href="#accessibility-as-a-checkbox-item">Accessibility as a checkbox item</a></li>
<li><a href="#reliance-on-out-of-the-box-automation">Reliance on out-of-the-box automation</a></li>
<li><a href="#lack-of-support-from-processes">Lack of support from processes</a></li>
<li><a href="#find-out-the-reason-for-any-pushback">Find out the reason for any pushback</a></li>
</ul>
</li>
<li><a href="#a-roadmap-for-accessibility">A roadmap for accessibility</a>
<ul>
<li><a href="#just-complaining-rarely-works">Just complaining rarely works</a></li>
<li><a href="#fixing-a-lack-of-awareness">Fixing a lack of awareness</a></li>
<li><a href="#skill-gap">Skill gap</a></li>
<li><a href="#present-a-plan">Present a plan</a></li>
<li><a href="#build-accessibility-into-team-processes">Build accessibility into team processes</a></li>
<li><a href="#measuring-success">Measuring success</a></li>
<li><a href="#legislation">Legislation</a></li>
</ul>
</li>
<li><a href="#wrap-up">Wrap-up</a></li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>Tackling accessibility is a multi-stage approach. Often the most difficult part is not the remediation of issues but instilling a culture where those issues are caught before they reach any backlog.</p>
<h2 id="the-causes-of-accessibility-issues">The causes of accessibility issues</h2>
<p>When we talk about accessibility we are generally talking about the barriers which are placed in front of people wanting to complete a task.</p>
<p>For the most part, on the web at least, these barriers can be fixed in some way or other. So we have to examine if this is the case, then why are so many websites still inaccessible when accessibility has been on the professional radar for so long?</p>
<p>The likely cause is unfortunately related to the processes which are involved in the building of those products.</p>
<p>This can take several forms:</p>
<ul>
<li>lack of awareness</li>
<li>deferring responsibility</li>
<li>assumed cost of implementation</li>
<li>assumed impact on deadlines</li>
<li>accessibility as a checkbox item</li>
<li>reliance on out-of-the-box automation</li>
<li>lack of support from processes</li>
</ul>
<p>This needs to be managed by the delivery leads on a project to ensure that both the stakeholders and wider team are aware of the need to prioritise accessibility.</p>
<h3 id="lack-of-awareness">Lack of awareness</h3>
<p>This can take a couple of forms, a lack of knowledge or a misunderstanding of the principles.</p>
<p>It might be that no-one has ever broached <a href="/posts/introduction/">the subject of accessibility</a> before. This is the easiest blocker to fix as it probably means there are no preconceived ideas, so some upskilling may be all that is needed.</p>
<p>Sometimes it might be that there is a misunderstanding of what disability means or who it affects. Let's examine a couple of the common misunderstandings:</p>
<h4>“None of our users are disabled”</h4>
<p>Well 1 in 5 people in the UK are disabled, so that is unlikely.</p>
<div class="note note--insight">
<p>Check DfE’s <a href="https://design.education.gov.uk/learn/how-many-users/">“How many people”</a> tool for an estimate of how many disabled users you can expect for your product.</p>
</div>
<p>Often this thinking is a result of an assumption that people with disabilities don't use the internet - certainly not blind users who surely cannot see the screen? It is also likely due to a narrow view of what conditions are within the scope of accessibility, and thinking it won't include users with cognitive or degenerative conditions, users with low vision or colour blindness or older users.</p>
<h5>The hidden nature of many conditions</h5>
<p>What people may mean by “none of our users are disabled” is that they’ve never heard of a user who explicity stated they were disabled use their product. Why would they? Many people keep their disabilities or conditions hidden, or don’t even see their condition as a disability.</p>
<p>People have adaptations or coping mechanisms which they use to work around their condition which reduce the outward presentation but do not lessen the impact.</p>
<p>Things like screen-readers or page zoom or high contrast mode don’t show up in analytics (nor should they), so they would never know if someone was using assistive technology.</p>
<h5>Negativity of poor accessibility</h5>
<p>What stakeholders might see is negative reviews about a product because of their lack of accessibility, or alternatively see praise heaped upon a competitor because they took accessibility seriously.</p>
<p>A product with poor accessibility is essentially shouting that they do not care about you as a customer. Why would you give such a company your business, especially when there is an alternative?</p>
<p>As users who need to make adaptations to use digital products are so used to poor accessiblity, when a product is accessible it means that this becomes a straight recommendation. It could even win customers over from a theoretically more capable or cheaper competitor.</p>
<p>If they really don’t have disabled users it is likely be because their product is inaccessible and they are leaving revenue on the table.</p>
<h5>The uncertainty of tomorrow</h5>
<p>Let's for a moment say that they can be absolutely sure none of their users are disabled. They cannot be sure those same users won’t be disabled tomorrow. Disability is a group which anyone can join at almost a moments notice.</p>
<p>No product can dismiss accessibility because they feel they know their users that well. The truth is they don’t and that knowledge is transitory at best.</p>
<h4>“This is an internal product”</h4>
<p>I've heard this a lot as a reason for not thinking about accessibilty on internal products. The assumption is that they “know” there are no disabled users on the team which will be using it, so why go to all the effort to make it accessible?</p>
<p>As hinted at above, it is not the responsibility of our users to declare medical conditions when using a site. Accessiblity is not just for publicly-available products. If someone needs to use something as part of their work then they have the same rights as those accessing public sites. <a href="/posts/guidelines-and-legalities/">Read more about the legalities of accessibility.</a></p>
<p>All the same arguments apply here as the previous example - you do not know everything about your users and certainly cannot know your future users. This is even more true now as working from home has increased and conditions and adaptations (such as using a screen-magnifier) are less visible.</p>
<p>You also have a duty of care for your staff. For example, you have a small team using an internal product. One of that team develops a condition. Because the product is inaccessible that person can no longer do their job which could lead to a variety of legal and other outcomes.</p>
<h3 id="deferring-responsibility">Deferring responsibility</h3>
<p>It is tempting to say that your team does not have the expertise to make a product accessible (we will get to this shortly) and pass all responsibility to the other teams, whether that is the team producing library code or a specialist accessibility team.</p>
<p>Just as with security the specialist teams can help with specific issues or provide the building blocks for good practice, but it is the responsibility of the product team to undertake accessibility as part of the job.</p>
<p>With accessibility there are both long and short term aims, but if no-one is taking responsibility for keeping up momentum then it is possible for the team to fall back into old habits. So it is essential that the delivery leads are keeping an eye on this at least until it becomes embedded in the team.</p>
<p>It is necessary for the whole team to be on board for an effective accessibility strategy and accessibility needs to be incorporated into all the team processes to avoid it being forgotten about.</p>
<p><a href="/posts/team-process-and-role-based-responsibility/">Read more about team processes and responsibility</a></p>
<h4>Deferring to a code library</h4>
<p>It might be that you are using a design system or code library. This can lead to assumptions that if the team uses that, then accessibility will be “inherited” from this. This can be true to an extent.</p>
<p>A design system <em>should</em> be robustly tested for accessibility, but in practice this is usually only done when the components are initially developed. Time, browsers and assistive technology support moves on and unless the design system has a regular testing regime in place, things can slip through.</p>
<p>These components will likely come with some accessibility features, but the team implementing them needs to understand how they help the user. Misunderstanding how a component presents information to a user of assistive technology can lead to those features being misused. For example, a component allows an <code>aria-label</code> to be added, but it is clearly up to the development team to use this correctly and ensure the attribute is actually needed and that content provided is appropriate.</p>
<p>Component libraries also by design need to allow for a degree of flexibiity in how the components are utilised. This flexibility can allow accessibility issues to creep in when implemented in the real world.</p>
<p>Design systems often only have a dozen or so components. Often teams may find they need to build something custom for their project. At this point the team needs to understand how to build that in an accessible way.</p>
<p>A well-built design system component can give you an amount of assurance that what the team is building is accessible. However the structural component is only part of the story. The content used in those components, how multiple components are composed together, the wider page and even wider user journey are all part of the accessibility story and also need to be considered from an accessibility viewpoint by the team implementing it.</p>
<h4>Deferring to an accessibility audit</h4>
<p>Some companies (and especially government departments) undertake accessibility audits or reviews prior to launching a product. It can be tempting to see this as an opportunity for someone else to do the hard work of finding the project's accessibility issues so the team can fix them, without it getting in the way of day-to-day delivery.</p>
<p>This approach will always lead to either missed deadlines or products launching with multiple accessibility barriers, which will most likely then languish in the backlog. It also misses a valuable learning opportunity for teams to pick up skills (without the looming deadline) during the product development.</p>
<p>A pre-launch review can only be used as part of a wider accessibility testing strategy. By itself it is unlikely to achieve the desired outcome as it sits too close to the launch date and is rarely able to prevent a launch if it finds issues.</p>
<p><a href="/posts/testing-strategies-and-accessibility/">Read more about accessibility testing strategies</a></p>
<h3 id="assumed-cost-of-implementation">Assumed cost of implementation</h3>
<p>It's interesting that accessibility is one of the few practices which we seem to have to barter for time and budget on. There are so many sites which have had no accessibility process prior to launch and which are now having to face costly remediation.</p>
<p>If accessibility is included in all stages of a project then the actual cost is much lower than what will be seen on a remediation project. It won’t be zero as there is additional time, testing and research required, but the figure is much lower than only tackling it at the end.</p>
<p>It has been estimated that having to <a href="https://yatil.net/blog/the-infuriating-inefficiency-of-accessibility-audits#the-cost-of-fixing-accessibility-bugs">fix issues after release can increase cost by 30 times</a> against finding that issue during the design phase. By including accessibility during all stages this rework can be avoided and costs minimised.</p>
<p>What really costs when it comes to accessibility remediation is where the fundamental page design or user journey is found to be flawed. This requires major rework and is not something you want to be doing as a product flies towards a deadline.</p>
<p>Something to bear in mind is that considering accessibility during design and development generally results in a better product. Clearer signposting, more understandable content and other benefits often come out of such accessibility work.</p>
<p>The question then is really can you afford not to consider accessibility?</p>
<h3 id="assumed-impact-on-deadlines">Assumed impact on deadlines</h3>
<p>Just as with the monetary cost, there of course is some additional cost to making a better, more robust, more usable product. Because that is what we are talking about - making the product usable by more people.</p>
<p>Yes the team may take a little extra time to learn new skills, but we need to allow teams to upskill in accessibility just as we might for security, testing or performance. Accessibility is a part of every role's responsibility, not an addition which can be opted out of.</p>
<figure>
<blockquote>
<p>Accessibility isn’t more work, you were just cutting corners before. The work was incomplete.</p>
</blockquote>
<figcaption>@McgarrDana, Twitter</figcaption>
</figure>
<p>This may sound harsh but it is true - accessibility is not a nice-to-have for those affected by it, it is essential to being able to use your product.</p>
<p>However, just as with the monetary cost there is a benefit in less rework later on. If accessibility is not tackled as part of the initial development process it becomes harder to prioritise later on as feature releases take precedence.</p>
<p>The more usable product which comes out of accessible design will mean less support tickets from users having trouble with the product. Often the product which results is less complex and so easier to maintain.</p>
<figure>
   <blockquote>
      <p>In 2016 Slack was using over 130 different colours (including 32 shades of blue).</p>
      <p>When an accessibility issue was raised this was reviewed and reduced to just 18 total, making it much easier and more efficient for designers and developers.</p>
   </blockquote>
   <figcaption>
      <a href="https://slack.design/articles/accessibility-a-powerful-design-tool/">Accessibility, a powerful design tool - Slack Design</a>
   </figcaption>
</figure>
<h4 id="the-mvp-paradox">The Minimum Viable Product (MVP) paradox</h4>
<p>Accessibility is often the first thing sacrificed to deadlines. Too often I've heard “this is an MVP, we'll add accessibility in later”.</p>
<p>Minimum Viable Product. That means a product which has the smallest amount of functionality to perform its required role. It doesn’t mean that you can cut out a whole group of potential users from using that functionality.</p>
<p>What if we left off any cross-browser testing from our MVP? Lets exclude any users of non-Chrome browsers. We wouldn’t do that because cross-browser testing is one of the core tenants of web development (although it seems not always). In the same way accessibility should be part of the core delivery.</p>
<p>Not including accessibilty in an MVP shows that something is lacking in the design and development process. As outlined above accessibility needs to be part of every step. It isn’t something you de-prioritise.</p>
<p>By dropping accessibility to your backlog you are just creating a design and technical debt mountain which in my experience never gets tackled.</p>
<p>If an MVP doesn’t include accessibility then I'm afraid you don’t have an MVP.</p>
<p>With good planning the additional time required for an accessible product delivery should not mean a deadline needs to shift to accommodate the extra work. It will however likely lead to less work later down the line. Remember accessibility work in a project starts before development beings.</p>
<h3 id="accessibility-as-a-checkbox-item">Accessibility as a checkbox item</h3>
<p>There is a lot of noise around compliance, especially in the public sector. <a href="/posts/guidelines-and-legalities/">Read more about the legalities of accessibility.</a> This can lead to accessibility and compliance being seen as the same thing. This can further lead accessibility to be seen as a checkbox item - “once compliance has been confirmed we can forget about accessibility”.</p>
<p>This is both incorrect and damaging to ongoing efforts to improve accessibility.</p>
<p>Compliance only measures a site against a predefined set of criteria at a specific point in time. Whilst these criteria are well-meaning they are not comprehensive, nor do they guarantee that a site built to them will be accessible, merely that you have done the <strong>least</strong> you can do to prevent the worst issues from appearing on your site.</p>
<p>Even a compliant site can have significant barriers for some users and it is only through rigourous testing, including with users, that we can remove most of them.</p>
<p>The checkbox mentality also suggests that once accessibility has been “done” that it can be forgotten about. But accessibilty requires an ongoing approach to ensure future work, for example new features or maintenance updates, do not introduce issues, but also so changes in the support landscape (such as browsers and assistive technology) are catered for.</p>
<p><a href="/posts/testing-strategies-and-accessibility/">Read more about testing strategies and accessibility</a></p>
<h3 id="reliance-on-out-of-the-box-automation">Reliance on out-of-the-box automation</h3>
<p>When it comes to testing for accessibility we too often rely on one-click solutions to tell us if something is accessible or not. Browser plugins such as axe or Wave certainly have their place in our accessibility toolbox, both they should not be the only items in it.</p>
<p>I have often seen teams run one of these plugins and declare the page or component accessible. Whilst it is true these tools are valuable in finding some issues, they cannot find a whole range of accessibility failures (current thinking is they may find around 40% of issues). It is similar to running a code linter and then not doing any unit, integration or end-to-end testing because the linter said it was ok.</p>
<p>We need to utilise a range of different testing methodologies to help us discover accessibility issues.</p>
<p><a href="/posts/automated-testing/">Read more about improving automated testing</a></p>
<h4>Overlays</h4>
<p>There is another aspect of automation and accessibility - the accessibility overlay. This takes the form of a javascript widget which is installed on an already launched site and promises to fix all of its accessibility failings by automatically fixing issues or offering the disabled user different options.</p>
<blockquote>
<p>“We’ll use one of those accessibility overlays, they’ll fix everything for us“</p>
</blockquote>
<p>Seems a smart choice - bypass all the expense and time by taking out a subscription to an accessibility overlay which will take care of all that accessibility stuff.</p>
<p>Except they don’t work. In fact often they will make things worse for the user.</p>
<p>The European Commission has even weighed in and said they can be harmful:</p>
<figure>
<blockquote>
<p>&quot;... some overlay tools have been reported to interfere with the assistive technologies used by people with disabilities. In other words, overlay tools may make a website less accessible for some users&quot;</p>
</blockquote>
<figcaption>
<p>European Commission (<a href="https://www.accessibility.works/blog/eaa-european-accessibility-act-compliance-standards-requirements/">source</a>)</p>
</figcaption>
</figure>
<p>The European Disability Comission and the International Association of Accessibility Professionals (IAAP) also issued a <a href="https://www.edf-feph.org/publications/joint-statement-on-accessibility-overlays/">joint statement</a> against the use of such overlays.</p>
<p>And think about the use-case. If a user needs these adaptations, they are going to need them everywhere, not just on your site. So if they need text reading to them they will use reader software that works everywhere. The solution is not to present the user with a custom solution, but to make the product work with what the user already uses.</p>
<p>Often the overlay just cannot fix what is broken, whether that is poor font-sizing and colour choice or just poor copy design or page design.</p>
<p>Moreover, why should the user have to try to work out how to use the particular overlay you decide to put on your site (and then a different one on the next site)? All an overlay does is shout to the user (and the product’s competitors) that you don’t really care about accessibility.</p>
<p>They are also an expense which would be much better spent on actually fixing the issues with the product.</p>
<p>For more on this see <a href="https://overlayfactsheet.com/">the overlay factsheet</a>.</p>
<h3 id="lack-of-support-from-processes">Lack of support from processes</h3>
<p>Even if the team is skilled in accessibility, without a process which supports this work it is all too easy for standards to start to slip. This is especially true as team members rotate out and this can result in just one or two people becoming the only ones maintaining accessibility best practice.</p>
<p><a href="/posts/team-process-and-role-based-accessibility/">Read more about team processes.</a></p>
<h3 id="find-out-the-reason-for-any-pushback">Find out the reason for any pushback</h3>
<p>If you come across pushback like the examples above, the first thing to do is to find out the reason for the pushback.</p>
<ul>
<li>are they just unaware of the impact of an inaccessible product?</li>
<li>have they heard accessibility is difficult?</li>
<li>are they worried as accessibility is something they haven’t dealt with before?</li>
<li>does accessibility not feature in a key performance indicator (KPI), so drops down in the levels of importance?</li>
<li>is there a skill gap on the team so no-on knows how to proceed?</li>
</ul>
<p>Theses are just a few reasons why accessibility is getting de-prioritised on a project and all require slightly different approaches.</p>
<h2 id="a-roadmap-for-accessibility">A roadmap for accessibility</h2>
<h3 id="just-complaining-rarely-works">Just complaining rarely works</h3>
<p>Just complaining about lack of movement on accessibility rarely works, but empowering someone to deal with it who was previously had it down as a problem area can lead to them becoming an evangelist as others will then look to them for help in doing the same in their own area.</p>
<p>If your product has accessibility problems sometimes just finding the worst area, fixing it and then demonstrating it and the impact it has to the team and stakeholders can be the first step to getting buy-in. Sometimes a simple before and after showcase is all you need. Even better if you can show a user for whom it caused a barrier which has now been removed.</p>
<h3 id="fixing-a-lack-of-awareness">Fixing a lack of awareness</h3>
<p>There are a lot of assumptions around the whole area of disabilities and accessibility. Sometimes you just need to break a few of these to get traction. There is also a general lack of understanding of the simple issues users might be having because people have difficulty in seeing how something might impact a user with a particular condition.</p>
<div class="note note--insight">
<p>Proctor &amp; Gamble designers were having difficulty getting accessibility taken seriously.</p>
<p>They finally sat stakeholders down with low-vision emulating glasses and asked them to pick which bottle was shampoo and which was conditioner.</p>
<p>When they couldn’t, accessible adaptations to the bottles were finally approved.</p>
<figure>
    <img src="/assets/images/modules/visual-impairment-simulation.png" data-size="implicit" alt="A set of ten glasses with different treatments applied to the lenses to show different types of visual impairment">
    <figcaption>Visual impairment simulation glasses.</figcaption>
</figure>
</div>
<p>Even just taking a screen-recording of how a page sounds to a screen-reader user before and after a fix can be enough to show how important accessibility is. If you have access to UR recordings of users with accessible needs using the product and having difficulties then this is the best thing to show to help unblock accessibility work.</p>
<h3 id="skill-gap">Skill gap</h3>
<p>There is no way around it, accessibility is a complex thing. That is why we cannot expect one person on a team be be responsible for all of it. It has to be a team responsibility.</p>
<p>Be aware that implementing code solutions without proper knowledge of the impacts that code may have can actually make things worse. It is always best to give the team time to learn this properly. This also means it is important to ask for assistance where possible if there is a lack of skills on the team. If there is expertise elsewhere in the company, lean on that to help your team.</p>
<p>Look to work with an accessibility specialist, they can provide insight by working with:</p>
<ul>
<li>the design team to find accessible solutions</li>
<li>delivery and product managers to review ticket requirements</li>
<li>the test team on how best to enforce accessibility requirements</li>
<li>developers to implement designs without excluding users</li>
</ul>
<p>However the team cannot come to rely on an accessibility specialist being available. They need to develop their own skills to find solutions to day-to-day issues, perhaps occasionally utilising the specialist for specific and complex problems.</p>
<p>Encourage the team to take time to learn. Just as with any other skill such as security or performance it will take time and this needs to be accounted for in timescales. Use team meetings such as sprint reviews to highlight accessibility wins and discuss issues.</p>
<p>Of course the team might not be able to upskill in everything right away. Look at staging the training.</p>
<p>If the team lacks skills, also look to increase the amount of user testing you are doing with disabled users to help inform decisions.</p>
<h3 id="present-a-plan">Present a plan</h3>
<p>Sometimes there is an understanding of an issue being present but no understanding of how to go about fixing it. There can be an awareness that there is a large accessibility backlog, but because no-one has taken ownership it is never acted upon. This is a silent backlog - there might not even be tickets created but everyone is aware there is something there which needs to be done.</p>
<p>In this case there is no actual person blocking the progress of accessibility, just a lack of process. There might even be a willingness to get it fixed, but no idea of where to start.</p>
<p>In this case it just needs a plan putting in place to tackle the issue and at least get it on the backlog and in the development cycle.</p>
<h3 id="build-accessibility-into-team-processes">Build accessibility into team processes</h3>
<p>It is important to provide a team with a structured way to help them move toward more accessible practices. Use existing team processes and add accessibility points to each one.</p>
<p>Places where accessibility can be highlighted and potential issues caught:</p>
<ul>
<li>design documents</li>
<li>prototype development</li>
<li>definition of ready</li>
<li>code commits / pull request reviews</li>
<li>testing procedures</li>
<li>defintion of done</li>
</ul>
<p>For more detail on how these can be improved see <a href="/posts/team-process-and-role-based-accessibility/">team processes and role-based accessibility</a>.</p>
<h4>Start with small wins</h4>
<p>Some accessibility improvements require very little in terms of time allocation, for example making sure form fields have accessible names. But these simple fixes can start to drive momentum and provide the team with the morale boost which they might need when facing a new skillset.</p>
<p>Work through the backlog to size issues based on time and complexity as well as severity and pull through groups of the easy wins to keep momentum going.</p>
<h4>Keep accessibility current</h4>
<p>Always talk about accessibility - include it in demos to stakeholders, reports, meetings. Make it a staple of everyday life in the team so it just becomes part of the furniture. Encourage delivery leads and stakeholders to advocate for accessibility and showcase accessibility wins to ther teams.</p>
<p>Find out what other teams are doing around accessibility and bring that back to the team.</p>
<h3 id="measuring-success">Measuring success</h3>
<p>Especially when starting out on an accessibility journey it is important for a team to be able to see progress, especially if they are dealing with a large backlog of remediation issues.</p>
<p>With accessibility being such a diverse and complex subject, how might we go about measuring success? Sure, the number of WCAG issues flagged on a site is one way, but as we have already touched on, compliance is only one aspect.</p>
<p>Here are a list of things we can look at in our backlogs:</p>
<ul>
<li><strong>WCAG A/AA issues outstanding</strong> - the most obvious thing to track but worthwhile nonetheless</li>
<li><strong>WCAG AAA issues</strong> - whilst not required for general compliance they can be a good indicator of the depth of accessibility and are too often overlooked</li>
<li><strong>best practice issues</strong> - these might be raised as non-WCAG issues on an audit or flagged as best practice on automated tool reports</li>
</ul>
<p>But we can also dig a little deeper to help improve processes:</p>
<ul>
<li><strong>time to fix</strong> - keep an eye on the time it takes to get around to fixing any outstanding accessibility issues, perhaps setting an upper limit so items do not fester on the backlog</li>
<li><strong>new issue generation</strong> - we should not be adding issues when we add new features so keep track of why any new accessibility issues are being created and if they could have been caught before shipping</li>
<li><strong>mapping accessibility issues across user journeys</strong> - this can be useful, both to identify problems in processes, but also to identify where a user may be confronted by a series of issues which even if low impact individually can wear the user down to the point they abandon the task</li>
</ul>
<p>Then there are some more general things to keep an eye on:</p>
<ul>
<li><strong>team skills</strong> - do all of the team engage in accessibility
<ul>
<li>by attending training sessions</li>
<li>attending user research observations</li>
<li>being able to showcase work they did to incorporate accessibility</li>
</ul>
</li>
</ul>
<p>And some user-centric metrics:</p>
<ul>
<li><strong>user satisfaction reports</strong> (or Github issues) - how many times are accessibility issues raised by users, but bear in mind they might be framed as a usability issue, so some investigation may be needed as to the true cause</li>
<li><strong>task completion</strong> - whilst we cannot know who is completing or abandoning a task we can continue to perform usability testing with disabled users to catch any regressions</li>
</ul>
<h3 id="legislation">Legislation</h3>
<p>Sometimes it can be necessary to resort to pointing at the <a href="/posts/guidelines-and-legalities/">legalities</a> of a situation to get it resolved.</p>
<p>However this is never the preferred way as it invariably ends up in a word-wrangling exercise where exemptions to the requirements are claimed.</p>
<h2 id="wrap-up">Wrap-up</h2>
<p>One of the hardest parts of accessibility is getting buy-in from stakeholders and the team. However once they are on board there is still work to do to ensure the momentum is kept up and accessibility becomes a natural part of the process.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Accessible names</title>
        <link href="https://liptrot.org/posts/accessible-names/"/>
        <updated>2024-10-09T13:00:00Z</updated>
        <id>https://liptrot.org/posts/accessible-names/</id>
        <content type="html"><![CDATA[
          <h2>Contents</h2>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#aria-and-accessible-names">Aria and accessible names</a></li>
<li><a href="#accessible-name-computation">Accessible name computation</a></li>
<li><a href="#manipulating-accessible-names">Manipulating accessible names</a></li>
<li><a href="#potential-issues">Potential issues</a></li>
<li><a href="#guidelines">Guidelines</a></li>
<li><a href="#wrap-up">Wrap up</a></li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>An accessible name is the name of an element in HTML and is what is exposed to assistive technology. Not to be confused with the <code>name</code> attribute on form fields.</p>
<p>In practical terms, it is what is read out to a screen‐reader when they navigate to the element. If the element is interactive, it is what a speech-recognition user would need to say to click on that element on the page.</p>
<p>An example is the accessible name of a link. This can be, at its simplest, the content enclosed by the link tags. For example, the accessible name of the link below is &quot;Bob&quot;:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Bob<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p>You can see the accessible names of elements in most browser developer tools by inspecting the element and checking the accessibility panel.</p>
<figure>
<img src="/assets/images/modules/accessible-names-chrome.png" alt="Chrome developer tools showing a link inspected. The Accessibility panel is open and the Name is shown as Bob" />
<figcaption>The Chrome browser accessibility panel showing the accessible name for the link. Here you can see it is derived from the <em>contents</em> of the link.</figcaption>
</figure>
<p>Accessible names can also be supplied by some attributes. For example, an <code>alt</code> attribute can provide the accessible name to an image:</p>
<div class="example example--render">
<img src="/assets/images/logo.jpg" data-size="implicit" alt="Adam Liptrot">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/assets/images/logo.jpg<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Adam Liptrot<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
</code></pre>
<img src="/assets/images/modules/accessible-names-image.png" data-size="implicit" alt="Chrome developer tools accessibility panel showing the image's accessible name is derived from the alt text">
</div>
<h3>Derived accessible names</h3>
<p>But that same image's <code>alt</code> text can also supply the accessible name to a link wrapping it, just as the text in our first example did. This is because the link's &quot;contents&quot; include elements inside it and <em>their</em> accessible names.</p>
<div class="example example--render">
<p><a href="/"><img src="/assets/images/logo.jpg" data-size="implicit" alt="Adam Liptrot"></a></p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/assets/images/logo.jpg<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Adam Liptrot<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<img src="/assets/images/modules/accessible-names-image-link.png" data-size="implicit" alt="Chrome developer tools accessibility panel showing the link's accessible name is derived from its contents">
</div>
<h3>Accessible names from relationships</h3>
<p>But an accessible name can also be created from other things, like the relationship generated by a <code>for</code> attribute. The following input's accessible name is generated by the label. The accessible name for the input is &quot;Your name&quot; and this is what will be announced to screen‐reader users when they land on it.</p>
<div class="example example--render">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Your name<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>name<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
</code></pre>
<img src="/assets/images/modules/accessible-names-input.png" data-size="implicit" alt="Chrome developer tools accessibility panel showing the input accessible name is derived from the relationship with the label">
</div>
<h2 id="aria-and-accesible-names">Aria and accessible names</h2>
<p>The <a href="/posts/aria/">ARIA</a> specification also has a couple of attributes which can assign accessible names:</p>
<ul>
<li><code>aria-label</code></li>
<li><code>aria-labelledby</code></li>
</ul>
<h3><code>aria-label</code></h3>
<p>This attribute will override any default accessible name with the contents of the attribute.</p>
<p>For example, we can use an <code>aria-label</code> instead of content to supply the accessible name to a <code>button</code>:</p>
<div class="example example--render">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Search<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<p>This will be announced to a screen-reader as:</p>
<blockquote>
<p>&quot;Search, button&quot;</p>
</blockquote>
</div>
<h3><code>aria-labelledby</code></h3>
<p>The <code>aria-labelledby</code> attribute takes a list of IDs from elements on the page and those element's accessible names will be used to create the accessible name.</p>
<p>Here we are pointing the attribute to the heading, whose accessible name is &quot;Search&quot; (from its contents), and so the accessible name of the button becomes &quot;Search&quot;.</p>
<div class="example example--render">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h2</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>search-copy<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Search<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h2</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">aria-labelledby</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>search-copy<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<p>These will be announced to a screen-reader as:</p>
<blockquote>
<p>&quot;Search, heading, level 2&quot;</p>
</blockquote>
<p>and</p>
<blockquote>
<p>&quot;Search, button&quot;</p>
</blockquote>
<p>And if the <code>h2</code> copy was updated this would also change the accessible name of the <code>button</code>.</p>
</div>
<p>We will look at more complex uses of this attribute shortly.</p>
<h2 id="accessible-name-computation">Accessible name computation</h2>
<p>So we know accessible names can be assigned using a few different methods. Because of this we need some way of deciding which one wins out, especially as we can use several of these on one element.</p>
<p>How an accessible name is computed is subject to a <a href="https://www.w3.org/TR/wai-aria-1.2/#namecalculation">hierarchy of checks</a> against the existence of various attributes, each one potentially overwriting the others. You can even see this order represented in the devTools display as in the examples above (the items appearing in each list vary depending on the element type, for example <code>alt</code> will only be shown for images).</p>
<p>The order is in descending order of priority (so ARIA attributes win over everything else). For example:</p>
<ol>
<li>aria-labelledby</li>
<li>aria-label</li>
<li>contents (not form elements)</li>
<li>derived from the label relationship (only form elements)</li>
<li>placeholder (only form elements)</li>
<li>title</li>
</ol>
<div class="note note--insight">
  <p>I included placeholder and title in there for completeness, but please don't use these. Both <a href="https://www.smashingmagazine.com/2018/06/placeholder-attribute/">placeholder</a> and <a href="https://www.tpgi.com/html5-accessibility-chops-title-attribute-use-and-abuse/">title attributes</a> have usability and accessibility issues.</p>
</div>
<p>So if you take the link from our first example and add an <code>aria-label</code> attribute:</p>
<div class="example example--render">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Tom<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Bob<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<img src="/assets/images/modules/accessible-names-link.png" data-size="implicit" alt="Chrome developer tools accessibility panel showing the link's accessible name is now derived from the aria-label attribute and overrides the visible content.">
</div>
<p>that will overwrite the contents and the accessible name is now “Tom”. Note that the visible text will still be “Bob” as we are only changing the <em>accessible name</em>.</p>
<p>Similarly if you take that link and add an <code>aria-labelledby</code> attribute it will trump all of the others:</p>
<div class="example example--render">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Tom<span class="token punctuation">"</span></span> <span class="token attr-name">aria-labelledby</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Bob<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Kim<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
</code></pre>
<img src="/assets/images/modules/accessible-names-aria.png" data-size="implicit" alt="Chrome developer tools accessibility panel showing the link's accessible name is now derived from the aria-labelledby attribute and overrides the other aria.">
</div>
<p>The link’s accesible name is now “Kim” despite the other changes still being present.</p>
<div class="note note--insight">
<p>You may be thinking, &quot;if I can reference other elements and they use <code>aria-labelledby</code> too, how far will this go?&quot;.</p>
<p>Well, <code>aria-labelledby</code> will only go one level down. If the element you reference also used <code>aria-labelledby</code> then that will be ignored for the purpose of generating the accessible name of the original element.</p>
<p>Let's consider this example:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">aria-labelledby</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>search1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Btn<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>search1<span class="token punctuation">"</span></span> <span class="token attr-name">aria-labelledby</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>search2<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Btn1<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>search2<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Btn2<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<p>You may think that the first button might have the accessible name of &quot;Btn2&quot; as it points to Btn1 which itself gets its accessible name from Btn2.</p>
<p>But whilst Btn1's accessible name is pulled from Btn2, the referencing via <code>aria-labelledby</code> only goes one jump and then further <code>aria-labelledby</code> are ignored, so the content of Btn1 is used instead.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">aria-labelledby</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>search1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Btn<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span> <span class="token comment">&lt;!-- "Btn1" --></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>search1<span class="token punctuation">"</span></span> <span class="token attr-name">aria-labelledby</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>search2<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Btn1<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span> <span class="token comment">&lt;!-- "Btn2" --></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>search2<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Btn2<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span> <span class="token comment">&lt;!-- "Btn2" --></span>
</code></pre>
</div>
<h2 id="manipulating-accessible-names">Manipulating accessible names</h2>
<p>Occasionally it can be useful to have a different accessible name from the visible one.</p>
<p>If you have a number of links which have similar functionality, but where adding unique visible text to each item might make the interface cluttered or confusing for other users, you can use certain techniques to provide different values to different groups of users.</p>
<p>The issue with identical links is that a screen‐reader user would not be able to distinguish the purpose of the links when viewing the links in isolation (this is one way screen‐reader users navigate a page - for more on this <a href="/guides/vo-macos/links/">take a look at my guide on the JAWS screen-reader</a>).</p>
<p>For example, a page where you have lots of editing options, each with a “Change” link.</p>
<img src="/assets/images/modules/accessible-names-change.png" alt="A list showing a name and address. Each item has a change link alongside." data-size="implicit" />
<p>A screen-reader user navigating by links or using an element listing will see a list of &quot;Change&quot; options and will have to go into the content to find out which one they need to follow to get to the article they want:</p>
<pre class="language-html"><code class="language-html">Change
Change
</code></pre>
<p>But making the links more contextual by adding more text to them like “Change your address” would make the interface overloaded and repetitive, helping one group to the detriment of another.</p>
<p>We need a way to satisfy both and one way to do this is with an <code>aria-label</code> to override the content-derived accessible name, like so:</p>
<div class="example example--render">
    <dl>
    <dt>Your name</dt>
    <dd>Bob Hoskins</dd>
    <dd><a href="#" aria-label="Change your name">Change</a></dd>
    <dt>Your address</dt>
    <dd>128 Spring Gardens, London, SW1 8ER</dd>
    <dd><a href="#" aria-label="Change your address">Change</a></dd>
    </dl>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#<span class="token punctuation">"</span></span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Change your name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Change<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#<span class="token punctuation">"</span></span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Change your address<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Change<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
</div>
<p>or we can add copy which is only available to assitive technology which combines with the visual copy to again adjust the accessible name:</p>
<div class="example example--render">
    <dl>
    <dt>Your name</dt>
    <dd>Bob Hoskins</dd>
    <dd><a href="#">Change<span class="visually-hidden"> your name</span></a></dd>
    <dt>Your address</dt>
    <dd>128 Spring Gardens, London, SW1 8ER</dd>
    <dd><a href="#">Change<span class="visually-hidden"> your address</span></a></dd>
    </dl>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    Change
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>visually-hidden<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> your name<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    Change
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>visually-hidden<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> your address<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
</div>
<div class="note note--insight">
<p>Here I am using a CSS <code>visually-hidden</code> class to hide the extra content visually, but still allow it to be picked up as part of the accessible name (and so communicated to the <a href="/posts/accessibility-tree-and-assistive-technology/">accessibility tree</a>).</p>
<p><a href="https://www.tpgi.com/the-anatomy-of-visually-hidden/">Read more about this technique</a></p>
</div>
<p>Either option keeps the visual the same but makes the links make sense to screen‐reader users as they will see a list of links like this:</p>
<pre class="language-html"><code class="language-html">Change your name
Change your address
</code></pre>
<p>As we have kept the visible label at the start of the accessible name, the user can still say &quot;click 'change'&quot; and the software will place a number next to each link to allow them to pick the one they want.</p>
<div class="note note--insight">
<p>This works for (most) speech recognition users. However <a href="/posts/links-hidden-copy-and-voice-recognition/">Voice Control on iOS has issues</a> with the difference between visible and accessible name, so users may find they need to use alternate strategies (such as numbering all controls on the page) to access the links.</p>
<p>For this reason it is always best to avoid having the visual text differ from the accessible name if at all possible.</p>
</div>
<h3>Using multiple sources</h3>
<p>You can reuse existing content to build an accessible name by using <code>aria-labelledby</code>. This takes a list of IDs of elements and constructs an accessible name based on the order of the IDs.</p>
<p>This allows you to re‐use content, which removes some of the hidden aspect of the accessible name. But care must be taken that the content used does not later change and inadvertently mess up the accessible name.</p>
<p>In the example below I'm creating the same accessible name as we have just done (&quot;Change your name&quot;), but using the <code>dt</code> and link content via <code>aria-labelledby</code> to concatenate them into one phrase.</p>
<div class="example example--render">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dt</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>q1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Your name<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dt</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dd</span><span class="token punctuation">></span></span>Bob Hoskins<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dd</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dd</span><span class="token punctuation">></span></span>
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>q1-change<span class="token punctuation">"</span></span> 
        <span class="token attr-name">aria-labelledby</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>q1-change q1<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
        Change
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dd</span><span class="token punctuation">></span></span>
</code></pre>
<img src="/assets/images/modules/accessible-names-compound.png" data-size="implicit" alt="Chrome developer tools accessibility panel showing the link's accessible name is now Change Your Name, derived from concatenating the question and the link's own content using the aria-labelledby attribute.">
</div>
<div class="note note--insight">
  <p>Bear in mind that any use of ARIA requires more testing with screen‐reader and voice-recognition software to ensure it works as expected. If you can get away without using ARIA, that is often the better option.</p>
</div>
<h2 id="potential-issues">Potential issues</h2>
<p>Accessible names pose a number of opportunities for us to break things and introduce barriers for our users.</p>
<h3>Trying to name an unnameable role</h3>
<p>Some roles such as <code>generic</code> cannot have an accessible name assigned. Check out the other <a href="https://www.w3.org/TR/wai-aria-1.2/#namefromprohibited">&quot;roles which must not be named&quot;</a>. The elements <code>span</code> and <code>div</code> are the two most common elements with this role</p>
<p>This means that even if you try to assign an accessible name to something like a plain <code>div</code>, that will not be communicated to assistive technology (or at least not in any sort of robust way).</p>
<h3>Missing accessible names</h3>
<p>Where none of the ways of assigning an accessible name are present, the browser cannot calculate an accessible name and nothing is returned.</p>
<p>This is most commonly found where form inputs are missing the connection with their label, or the one I see most often is on buttons.</p>
<p>The most common example is where a button doesn't have any content because a background image, an icon font, or an image with no <code>alt</code> text is being used to display a visual-only message. You might have seen this yourself in a mobile menu (“hamburger”) icon, or a carousel control like the one below:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>rightArrow.png<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<p>To a screen‐reader user this will just be announced as &quot;Button&quot; so they will have no idea what it does.</p>
<p>For a speech-recognition user they could try a few words based on the visual appearance but will likely give up and resort to other means.</p>
<div class="example example--render">
<p>If you happen to have used an embedded SVG for that image, you might have inadvertantly provided an accessible name (in the SVG <code>title</code> attribute for example), and it could even have the opposite effect to the one you might have wanted, like the example below:</p>
  <figure>
  <img src="/assets/images/posts/autotrader.png" alt="Webpage showing a carousel of car adverts. The right navigation button is inspected in the browser developer tools showing the accessible name is derived from the title of the SVG used for the icon on the button." />
  <figcaption>Autotrader homepage carousel with possibly worse‐than‐none accessible names. <a href="/assets/images/posts/full-size/autotrader.png" target="_blank">See larger image (new tab).</a></figcaption>
  </figure>
<p>On Autotrader’s homepage they had a carousel which uses an SVG icon inside the directional buttons.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>button<span class="token punctuation">"</span></span> <span class="token attr-name">...</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>svg</span> <span class="token attr-name">xmlns</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://www.w3.org/2000/svg<span class="token punctuation">"</span></span> <span class="token attr-name">...</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">></span></span>chevronLeft<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">></span></span>
    ...
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>svg</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<p>Unfortunately on this page an accessible name was not provided for the button. However because the SVG had a title attribute, this is what is exposed as an accessible name (as it counts as <em>Contents</em> as far as accessibility is concerned). The “chevronLeft” title from the SVG whilst meaningful to the designer who exported it, is not of any use to the end-user, not least because it suggests the arrow points in the opposite direction when it has been rotated using CSS for the right-facing button.</p>
<p>For those wondering, yes the left button uses the same SVG and the image rotated for the opposite direction, so both left and right buttons on the carousel had “chevronLeft” as their accessible name.</p>
<p>What they should have done in this case was hide the SVG from assistive technology using aria-hidden and provided a suitable <code>aria-label</code> on the <code>button</code> itself.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Next<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>button<span class="token punctuation">"</span></span> <span class="token attr-name">...</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>svg</span> <span class="token attr-name">aria-hidden</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token attr-name">xmlns</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://www.w3.org/2000/svg<span class="token punctuation">"</span></span> <span class="token attr-name">...</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">></span></span>chevronLeft<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">></span></span>
    ...
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>svg</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<p><strong>Update (July 2025)</strong> : Autotrader have since updated their carousel and now use an <code>aria-label</code> on the <code>button</code>.</p>
</div>
<p>So accessible names are very important for users to understand what the various controls on the page do and having the wrong ones can even cause the user to do something they didn't intend.</p>
<h3>Overriding the visual label</h3>
<p>This does mean that you can do things like override the visible contents of the element with a different accessible name, which can lead to issues.</p>
<div class="example example--render">
<figure>
<img src="/assets/images/posts/bbc-register.png" alt="A website form with a continue button. The developer tools is open showing an aria-label has been applied to the button, but the text differs from the visible." />
<figcaption>The BBC registration journey. The "Continue" button has an accessible name different to the visible text, which is confusing at best and an impediment at worst. <a href="/assets/images/posts/full-size/bbc-register.png" target="_blank">See larger image (new tab).</a></figcaption>
</figure>
<p>The following example is the code for the button from the BBC screenshot above (since I took this screenshot it has been fixed, although it took a redesign for this to happen).</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Next<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Continue<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<p>The visible content is &quot;Continue&quot;, but the accessible name is &quot;Next&quot; as the <code>aria-label</code> has overridden the content‐derived accessible name.</p>
<p>For a screen‐reader user who can see (many screen‐reader users are not fully blind), this can be a bit confusing as the visible and audible messaging is different.</p>
<p>For a speech‐recognition user it is frustrating as they will try to say &quot;Click 'continue'&quot; which will not work because the software has been told the accessible name for this button is &quot;Next&quot;. In this situation the speech-recognition user will (probably after a few tries) resort to asking the software to number all the controls on the page to allow them to select the correct one and continue. This is not good as it is asking the user to do a step which is completely unnecessary and especially so on the first step of a registration process.</p>
</div>
<h3>Undoing good work</h3>
<p>This next example shows how a misunderstanding of how accessible names are computed or how ARIA works can lead to good work being undone.</p>
<p>Below we can see a product card with an image of the product and a button to add it to the basket. The button has had hidden content added to allow screen-reader users to understand which item they are adding to their cart. This was done using the visually-hidden technique outlined above. However an <code>aria-label</code> attribute has also been added to the button to replicate the visible label. This means the hidden copy (and the context it provided) is lost. The accessible name computation states that an <code>aria-label</code> will overwrite the content of the element. The button is no better off than if it had just been coded as a <code>button</code> with &quot;Add to basket&quot; as the contents.</p>
<div class="example example--render">
<img src="/assets/images/modules/accessible-name-overwrite.png" alt="A card component for a lamp, the card contains an image underneath which is an Add to basket button. After the button is the product name." data-size="implicit">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Add to basket<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
  Add to basket
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>visually-hidden<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>, Matthew Williamson Ombre Cone Ceramic Base Table Lamp<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<p>This will be announced as:</p>
<blockquote>
<p>&quot;Add to basket, button&quot;</p>
</blockquote>
<p>So, despite all the good intention, the above code is equivalent to:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span><span class="token punctuation">></span></span>Add to basket<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
</div>
<h3>Visual not matching the name</h3>
<p>The most dangerous issue is where the <em>meaning</em> of the visual label is completely different to the accessible name. For example using an <code>aria-label</code> of “cancel” on a button with the visual text of “continue”.</p>
<pre class="language-html"><code class="language-html">
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Cancel<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Continue<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>

</code></pre>
<p>This obviously could have a major impact on a screen-reader user as they could potentially submit data when they wanted to cancel an application.</p>
<p>This is an extreme example (but one I actually saw in production), but we should always ensure that any visible text is part of the accessible name (ideally at the start).</p>
<p>WCAG even has a criterion to cover this called <a href="https://www.w3.org/WAI/WCAG21/Understanding/label-in-name.html">“Label in name”</a>.</p>
<h3>Overloading an accessible name</h3>
<p>Accessible names are meant to be short - a few words long at most. Remember a screen-reader user will listen to an accessible name to understand what the element's purpose is. A long accessible name can confuse matters and leave a user wondering what the element is.</p>
<p>This is especially something to be aware of when wrapping content with a link (or button). As we have seen, the content inside the link will be used as the link's accessible name.</p>
<p>We can often see this where a card component is used:</p>
<div class="example example--render">
<img src="/assets/images/modules/accessible-name-card.png" alt="A card component for a floor lamp. It comprises an image with text overlaid about how many users have bought it, followed by the product name, a rating component and the price. Below this group are a button for a wishlist and another to add to basket." data-size="implicit">
<p>In the above image the whole card, from image to price, is wrapped in a link, as can be seen in the simplified markup below:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>GoodHome Mulanje Industrial Matt White Wood effect Floor light<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>10 people bought this in 48 hours<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>

  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>GoodHome Mulanje Industrial Matt White Wood effect Floor light<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>sr-only<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>5 stars<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>(3)<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>£48.00<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p>But this has the effect of utilising the entire card as the accessible name for that link, as it constitutes the 'content' of the link.</p>
<p>So the accessible name of the card link becomes:</p>
<blockquote>
<p>GoodHome Mulanje Industrial Matt White Wood effect Floor light 10 people bought this in 48 hours GoodHome Mulanje Industrial Matt White Wood effect Floor light 5 stars (3) £48.00</p>
</blockquote>
<p>This is a lot to digest for a user! This method of card markup should be discouraged in favour of only using the primary name as the link (in this case that's the product, but it could be a blog post title). The card click action could then be added with javascript. <a href="https://inclusive-components.design/cards/">See more information on this approach to cards on the Inclusive Components site</a>.</p>
<p>There are other issues with the card in this example. For example the product is plain text when it could be useful to have it marked up as a heading. The image is also just the product name, which as well as adding repetition does not really describe what the product looks like to the user. <a href="/posts/accessible-content/">See more on writing accessible content, including alt text</a>.</p>
</div>
<h3>Placement of extra copy</h3>
<p>The critical thing with speech recognition users and editing an accessible name to add context is that only added to the <strong>end</strong> of the visible label. Speech recognition software <a href="/posts/links-hidden-copy-and-voice-recognition/">varies in ability to search for content</a> and most do not respond well to the visible content not being the first content in the accessible name.</p>
<p>For example if you have a link like this:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>change name<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p>and you want to add some context, don't do this:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/<span class="token punctuation">"</span></span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Bob change name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>change name<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p>or this</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/<span class="token punctuation">"</span></span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>change Bob's name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>change name<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p>as most speech recognition software won't make the match when a user says <em>“Click ‘change name’”</em>. Remember speech-recognition users cannot see the <code>aria-label</code> content, but the software <strong>can</strong> (it needs to for a variety of reasons).</p>
<p>Instead add the new content to the end of the visible label:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/<span class="token punctuation">"</span></span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>change name for Bob<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>change name<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<h2 id="guidelines">Guidelines</h2>
<p>Here are a few pointers to help reduce the amount of issues you may have with accessible names.</p>
<h3>Prefer visual labels</h3>
<p>Where possible keep accessible names visible, especially where the item is interactive, such as a link, button or form control. This will ensure people who do not use software which exposes hidden accessible names to them will still be able to determine the purpose.</p>
<p>For example if we provided an accessible name to a button with just an <code>aria-label</code> and image:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Open menu<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>svg</span><span class="token punctuation">></span></span>...<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>svg</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<p>then it would be more difficult for anyone not using a screen-reader to determine the purpose of the button than if the button contained visible text:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>svg</span><span class="token punctuation">></span></span>...<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>svg</span><span class="token punctuation">></span></span> Open menu<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<p>The second option makes it much clearer to all what the button does, and also lets speech-recognition users know what they have to say to activate it.</p>
<h3>Follow the ARIA rules</h3>
<p>As some of the techniques we have discussed use ARIA attributes, we should always look to <a href="/posts/aria/#the-rules-of-aria">follow the rules of ARIA</a>.</p>
<p>There are two which particularly apply to accessible name ARIA attributes:</p>
<ol>
<li>If you can achieve the same by using an HTML element rather than aria then do so. For example, do not add <code>aria-label</code> to an <code>input</code> when you can use a <code>label</code> element instead.</li>
<li>All interactive controls need to have an accessible name, whether this is achieved using ARIA or not.</li>
</ol>
<h3>How should this element be named?</h3>
<p>As a general rule assume only landmarks and interactive controls such as links, buttons and form controls can have attributes like <code>aria-label</code> or <code>aria-labelledby</code> applied.</p>
<p>Elements such as <code>span</code>, <code>p</code> and <code>div</code> have what is called a <code>generic</code> role by default and fall into a group which cannot have these attributes applied.</p>
<p>For which aria roles can have accessible name and how they can be set, <a href="https://www.w3.org/WAI/ARIA/apg/practices/names-and-descriptions/#naming_role_guidance_heading">see the W3C naming guidance</a></p>
<h3>Do not overuse aria</h3>
<p>It can be tempting to add accessible names via <code>aria-label</code> attributes to lots of elements, such as <code>sections</code> in a bid to help the user. But this can just add noise for the user and make maintenance more problematic. Instead consider the above guidelines - use HTML elements where possible and visual labels - perhaps using visible headings instead. Only add it where you know it will help - and test it in a screen-reader.</p>
<h2 id="wrap-up">Wrap up</h2>
<p>Accessible names are how you communicate the meaning of the interface to your users and getting it right is really important.</p>
<p>If you have any doubt as to what the accessible name is for an item, most browser developer tools now have an accessibility panel which shows you the computed value. However testing with screen‐readers and speech recognition is still necessary to ensure the correct meaning is conveyed.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Accessible forms</title>
        <link href="https://liptrot.org/posts/accessible-forms/"/>
        <updated>2024-09-26T13:00:00Z</updated>
        <id>https://liptrot.org/posts/accessible-forms/</id>
        <content type="html"><![CDATA[
          <h2>Content</h2>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#considering-users">Considering users</a>
<ul>
<li><a href="#interaction-modes">Interaction modes</a></li>
<li><a href="#reduced-typing">Reduced typing</a></li>
<li><a href="#memory-conditions">Memory conditions</a></li>
<li><a href="#numbers">Numbers</a></li>
<li><a href="#avoid-redundancy">Avoid redundancy</a></li>
<li><a href="#save-progress">Save progress</a></li>
<li><a href="#time-restrictions">Time restrictions</a></li>
<li><a href="#cognitive-load">Cognitive load</a></li>
<li><a href="#inclusion">Inclusion</a></li>
</ul>
</li>
<li><a href="#communication">Communication</a>
<ul>
<li><a href="#styling">Styling</a></li>
<li><a href="#labels">Labels</a></li>
<li><a href="#placeholders">Placeholders</a></li>
<li><a href="#hints">Hints</a></li>
<li><a href="#errors">Errors</a></li>
<li><a href="#grouping-inputs">Grouping inputs</a></li>
</ul>
</li>
<li><a href="#assistance">Assistance</a>
<ul>
<li><a href="#validation">Validation</a></li>
<li><a href="#avoid-select-inputs">Avoid select inputs</a></li>
<li><a href="#avoid-disabled-buttons-or-inputs">Avoid disabled buttons or inputs</a></li>
<li><a href="#avoid-read-only-inputs">Avoid read-only inputs</a></li>
<li><a href="#showing-the-correct-keyboard">Showing the correct keyboard</a></li>
<li><a href="#helping-browsers-autofill-inputs">Helping browsers autofill inputs</a></li>
<li><a href="#focus-indicators">Focus indicators</a></li>
<li><a href="#do-not-disable-copy-and-paste">Do not disable copy &amp; paste</a></li>
<li><a href="#avoid-using-maxlength">Avoid using maxlength</a></li>
<li><a href="#size-fields-to-expected-data">Size fields to expected data</a></li>
<li><a href="#review-before-submission">Review before submission</a></li>
</ul>
</li>
<li><a href="#wrap-up">Wrap-up</a></li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>Forms are a key part of accessibility as they are often the reason a user will interact with a page - whether that is to buy a product, post something on social media, contact a company or communicate with their bank or government.</p>
<p>With so much of the daily interactions moving to digital, having accessible forms is essential for living today. Consequentially having a form which does not account for the needs of users can lead to those users being excluded from crucial services or aspects of daily life.</p>
<p>Whether it is a simple single field newsletter sign-up or a multi-page application form there are things we need to get right to ensure everyone can use it.</p>
<h2 id="considering-users">Considering users</h2>
<p>Before we start to think about designing a form we need to consider our users.</p>
<h3 id="interaction-modes">Interaction modes</h3>
<p>Different users may interact with our form in different ways so we need to be careful that our form design does not get in their way or make it difficult to understand what we are asking for.</p>
<p>For example:</p>
<ul>
<li>Some users cannot use a mouse so more complex input types will need to be checked to ensure they can be used with just a keyboard.</li>
<li>A screen-reader user is going to rely more on programmatic relationships between form fields and content to understand what is being asked.</li>
<li>Speech-recognition users will use visual labels to place their cursor in a field. Labels need to be both visually and programmatically associated with the field.</li>
<li>For screen-magnification users we need to be sure that the form is easy to follow when perhaps only one field can be seen at a time.</li>
</ul>
<h3 id="reduced-typing">Reduced typing</h3>
<p>Some users find it difficult to enter data by typing. Perhaps a physical condition makes it difficult or painful to type; they find thinking about and constructing answers difficult or they are not confident in how their answer may be interpreted. These users may benefit from answering questions with a simple yes or no, instead of having to type an answer in a field.</p>
<h3 id="memory-conditions">Memory conditions</h3>
<p>Users may have conditions which affect memory so designing for recognition rather than recall will help. Reduced typing solutions can help here too. For example picking an option from a list rather than asking for them to type in a field.</p>
<p>Similarly avoid asking the user to remember answers from previous pages. Instead provide the information the user needs on the same page where you are asking the question about it.</p>
<h3 id="numbers">Numbers</h3>
<p>Some users find it difficult to work with numbers. This can be due to low numeracy or conditions such as dycalculia. Where possible we should avoid asking users to make calculations, instead we should be doing this for them.</p>
<p>This can be a particular issue when digitising a paper form as these tend to ask the user to do calculations. If we are not careful we can just duplicate the paper form instead of looking at ways we can make the user's life easier.</p>
<h3 id="avoid-redundancy">Avoid redundancy</h3>
<p>When we are building our form design we want the user to have to do as little work as possible. The easiest way we can do this is by not asking the user questions in the first place.</p>
<p>We should avoid asking the user any questions which we do not need in order for them to complete the given task. For example, don't ask questions which don't provide value for the user (such as demographic information for metrics) or ask questions which you can get the answer to via other means (such as querying your own databases or APIs).</p>
<p>Similarly do not ask the user to enter the same data more than once. If the task requires the user to enter their address for shipping and then they need to enter a billing address, allow them to pick the shipping address if they are the same.</p>
<h3 id="save-progress">Save progress</h3>
<p>Conditions and disabilities can make interacting online very tiring, moreso if it involves having to think about answers or typing. It might be that users are unable to complete multi-page or lengthy forms in one sitting. To help users we want to save progress as they go and give them the option of exiting the form and coming back later.</p>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-save.png" alt="Two buttons, the first is the main button and says save and continue. The second button says save and come back later." data-size="intrinsic">
<figcaption>Giving them the option to save their progress and come back at a later date can be essential for some users.</figcaption>
</figure>
<p>In order for this to be effective the option should be clearly signposted so the user is not uncertain if their data has been saved. When they return they should be able to pick up where they left without having to revisit all the completed pages.</p>
<h3 id="time-restrictions">Time restrictions</h3>
<p>Whether the form allows the user to save and come back or not we also want to avoid setting artifical time limits on the time they take. Again not all users work to the same pace and asking users to complete an application or move to the next section within 15 minutes may be ok for some but difficult to achieve for others.</p>
<p>The way we can manage this is to either not set any limits in the first place or offer a way for the user to extend their session. The most common way is to provide some type of alert or dialog which appears shortly before the session is about to expire offering the user the chance to extend their session.</p>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-timing.png" alt="A dialog sitting over page content. The dialog says for your security we will sign you out in 2 minutes. There are two options, one to stay signed in and one to sign out." data-size="intrinsic">
<figcaption>A dialog allowing users to extend their session is one way to provide users with more time where a session time limit is still needed.</figcaption>
</figure>
<h3 id="cognitive-load">Cognitive load</h3>
<p>Whilst it may be possible to cram all the fields your task needs onto one page it can be better for the user to spread them over several pages.</p>
<p>Having a lot of fields on a single page may feel more efficient, however it has a few downsides.</p>
<ul>
<li>having a lot of questions on one page can be overwhelming</li>
<li>less chance to save progress</li>
<li>more time pressure</li>
<li>more difficult to locate errors</li>
<li>more chance for data loss</li>
<li>branching questions become more technically complex and more difficult to understand</li>
</ul>
<p>We can avoid these issues by placing small groups of related questions on their own pages. This allows the user to just think about that topic, keeping cognitive load as small as possible.</p>
<p>This is a pattern called “<a href="https://www.smashingmagazine.com/2017/05/better-form-design-one-thing-per-page/">one thing per page</a>”. The “one thing” does not mean one field, but one concept per page. For example <strong>“Your contact details”</strong> is one <em>thing</em> but may include fields for your name, email, phone and address.</p>
<p>This may not always be the best solution - for example users who reguarly fill out the same form may prefer to avoid the additional navigation, or users may prefer to see the entire form in one go to better manage expectations and required information. However this pattern is often a good starting point and fields can be grouped onto the same page in response to feedback during testing.</p>
<h3 id="inclusion">Inclusion</h3>
<p>We should also consider if we might be excluding users by the questions we ask. This also crosses into inclusivity and includes examples such as:</p>
<ul>
<li>asking about gender or sex</li>
<li>asking about equality information</li>
<li>cultural biases such as asking for a first and last name rather than a freeform field</li>
<li>only asking for a phone number when users may prefer or need to be contacted in other ways</li>
</ul>
<p>Remember that if you <em>need</em> to gather data around a user's gender or pronouns you should also have a route for them to be able to edit them in the future.</p>
<h2 id="communication">Communication</h2>
<p>Forms are all about communication. Content within a form is really important to get right. We need to avoid any confusion about what the user should enter and in what format. When things go wrong we also need to make sure they know why and how they can fix it.</p>
<p>All the following need to be carefully considered by content designers:</p>
<ul>
<li>content which directs the user to the form</li>
<li>labels and legends</li>
<li>hint copy</li>
<li>error messages</li>
<li>confirmation and “what happens next” content</li>
</ul>
<p>But before we get into these, we also need to think about how our form is communicating with the user visually.</p>
<h3 id="styling">Styling</h3>
<p>When users are entering data into a form their main concerns are going to be about getting the data entered and knowing they have filled in all the required fields. Whilst a set of fields which fit nicely with the site design are pleasant, this should not detract from the functionality of the form or get in the way of the user completing their task.</p>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-inputstyle.png" alt="Three text inputs. The first two only have a thin bottom border. The first has a light grey background, but text indicates this only has a 1.1:1 ratio contrast with the background which means it is just like the background is not there at all. The second input shows the same as the first but with the background removed to show how it may look to users who cannot perceive the light grey. The final input shows the field with a heavy border which is much easier to see as an input." />
<figcaption>These examples show how styled form controls can get in the way of a user easily understanding what is or is not an input. Keeping it clear will improve ease of use.
The use of the floating label pattern on the first two is problematic too, but we will talk about that shortly.</figcaption>
</figure>
<p>Also think about font-sizing. Users are able to adjust their font sizes so ensure that your styles are able to cope with this.</p>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-font.png" alt="A form where the font of the entered data is being obscured by the labels." data-orient="portrait">
<figcaption>On the Mercedes UK site when the font size is increased to 200% the labels and inputs overlap causing issues with readability.</figcaption>
</figure>
<p>If you are going to be doing anything but very simple form styling you need to look to heavily test these components. This includes introducing components from a component library (such as calendar pickers). Even simple CSS can render a form inoperable to a keyboard or screen-reader user. This is even more of a risk when javascript is also introduced. This can mean they will not be able to complete their task - which may be the primary functionality of the site.</p>
<p><a href="/posts/keyboard-accessibility/#how-styling-can-impact-functionality">More about styling impacts in forms</a></p>
<h3 id="labels">Labels</h3>
<p>Labels are a visual instruction for a field, but it is not enough to place text above an input. There are several things to consider when writing and coding a label.</p>
<h4>Larger touch target</h4>
<p>When correctly associated with the field labels provide a larger hit target as clicking the label will place focus within the field. This is especially important for checkboxes and radio buttons due to the smaller size of the input itself.</p>
<h4>Positioning</h4>
<p>Users need to visually associate the label with the field it relates to. This means the label needs to be adjacent to the field. Having a bunch of content between the label and the field makes it more difficult to make this cognitive leap but especially so for screen-magnification users and mobile users.</p>
<p>Take the below for example:</p>
<img loading="lazy" src="/assets/images/modules/forms-labelpos.png" data-orient="portrait" alt="A text input above which are a dozen lines of copy above which sits the label for the input." />
<p>This is not great. If we take this line-by-line we are asking a question, then providing the user with a hefty set of copy around how they should answer and then asking them to tell us the answer (the input). By the time the user has read the guidance copy it is likely they will need to re-read the question. This becomes even more of an issue for screen-magnification users (and mobile users) as they cannot just glance up at the question, instead having to move back up the page to find it.</p>
<p>A better option would be to put that label right next to the input and precede the block of content with a heading:</p>
<img loading="lazy" src="/assets/images/modules/forms-labelpos-after.png" data-orient="portrait" alt="The text input has a label right above it. The content above has a heading as an introduction." />
<p>It would be even better if the block of text could be reworked to make it easier to understand or even broken up a little.</p>
<h4>Accessible name</h4>
<p>Labels most importantly provide the <a href="/posts/accessible-names/">accessible name</a> for the field. This programmatic link means that when a screen-reader user lands on a field the label is read out.</p>
<p>It also allows a speech-recognition user to focus the field by using the label. Labels should be visible text next to the field and easily identifiable to the user as the label to help make the cognitive link but also assist speech-recognition users in understanding what they need to say to select the field.</p>
<p>Let's take a quick look at a poorly constructed field:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">></span></span>
    What is your name?
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token attr-name">...</span> <span class="token punctuation">/></span></span>
</code></pre>
<p>If a screen-reader user jumped directly to the field above, they would hear:</p>
<blockquote>
<p><strong>“Edit text”</strong></p>
</blockquote>
<p>They woud not know what the field was expecting and would have to explore the page to find out and assume text above the field was the label. Having the user make cognitive leaps like this is poor accessibility.</p>
<p>Similarly a speech-recognition user would not be able to easily place their cursor in the field. A speech-recognition user would typically say the label text to focus the input (<em>“Click What is your name”</em>) - here doing that would not do anything because the input does not have the accessible name.</p>
<p>Even if we had used a <code>label</code> instead of the <code>div</code> this would make no difference as without the association with the field the <code>label</code> essentially becomes just plain text.</p>
<p>So how do we make this association?</p>
<p>The <code>label</code> is programmatically associated with the field by using the <code>for</code> attribute to point to an <code>id</code> attribute on the field. This relationship allows the accessible name of the field to be supplied by the <code>label</code> contents.</p>
<div class="example example--render">
<div class="form-group">
<label for="name">What is your name?</label>
<input type="text" id="name" name="name" autocomplete="name" />
</div>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    What is your name?
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>name<span class="token punctuation">"</span></span> <span class="token attr-name">...</span> <span class="token punctuation">/></span></span>
</code></pre>
</div>
<p>Now if a screen-reader user jumped directly to the field above, they would hear:</p>
<blockquote>
<p><strong>“What is your name name, edit text”</strong></p>
</blockquote>
<p>Let's have a look at that on a larger form.</p>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-labels-sr-bad.png" alt="An address form with label text above each field. A system dialog sits to the side with the heading of form controls. Each control is listed in the dialog as edit text." />
<figcaption>Here we can see the screen-reader's element viewer listing all the fields in the form. However as none of the labels are correctly linked to the fields none of the fields have names in the viewer.</figcaption>
</figure>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-labels-sr-good.png" alt="An address form with label text above each field. A system dialog sits to the side with the heading of form controls. Each control is listed in the dialog with the label from above the field." />
<figcaption>With the labels correctly associated with the fields the element viewer now displays the field names, allowing the user to move quickly to the field they want to edit.</figcaption>
</figure>
<div class="note note--insight">
<p>Do not be tempted to just wrap the <code>label</code> around the <code>input</code> to rely on implicit association like this:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span><span class="token punctuation">></span></span>
    What is your name?
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>name<span class="token punctuation">"</span></span> <span class="token attr-name">...</span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">></span></span>
</code></pre>
<p>Whilst this is valid HTML it <a href="https://www.tpgi.com/should-form-labels-be-wrapped-or-separate/">can cause issues</a> for some assistive technology in accessing the field.</p>
<p>If you need to wrap the field for some reason, then you will also need to add in the <code>for</code> attribute to avoid these issues:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    What is your name?
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>name<span class="token punctuation">"</span></span> <span class="token attr-name">...</span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">></span></span>
</code></pre>
</div>
<h3 id="placeholders">Placeholders</h3>
<p>Placeholders are faint copy inside an input and are set using the <code>placeholder</code> attribute. The intent was for them to provide format information. We will see how even this is problematic but their use has been stretched beyond this to include providing labelling.</p>
<h4>Placeholders as labels</h4>
<p>If no other accessible name is provided they can offer an “accessible name of last resort”, but are far from an ideal way of providing one.</p>
<p>It can be tempting, especially when struggling for space or when wanting to “de-clutter” an interface to use a placeholder instead of a label. However using placeholders instead of a label has accessibility knock-on effects.</p>
<p>Increasing font size can lead to placeholder copy being cut off. This can also be an issue where the page is translated into different languages and the content becomes longer than the original.</p>
<p>Once the user starts typing, the placeholder (which remember is taking the functionality of the label), disappears. This can be especially an issue when the browser autofills fields incorrectly.</p>
<p>When you remove a visual label you are also removing the ability of the user to verify that they have added their data in the right place. You are essentially preventing the user from checking their answers before they submit the form.</p>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-placeholders-removed.png" alt="Part of a form. This has 3 fields age, hours worked per week and weeks worked per month. The fields are only identified by the placeholder copy. Once the user has filled in the data they are left with 3 fields each with a number in and no way of knowing which is which." />
<figcaption>On the cycle scheme site the placeholders act as labels which mean they disappear once the user has filled in the information. This makes it difficult for some users to identify or select the fields as the accessible name is no longer visible.</figcaption>
</figure>
<p>Any format information has to be included in the placeholder, so we are unlikely to be able to provide a meaningful hint. Remember we need to be careful of increased font sizes and translations.</p>
<p>Placeholder contrast is normally low in order to prevent it being registered as actual data entry. However this also means that it often falls below the required contrast ratio so can be difficult to read.</p>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-placeholder-contrast.png" alt="A sign-up form using placeholders instead of labels. The labels are a light grey colour on a white background." />
<figcaption>The Vue Cinema form has placeholder copy which falls far below the required contrast for text. This means it can be difficult for some users to know what data they are meant to enter as there is no high contrast label.</figcaption>
</figure>
<p>“We'll just increase the contrast so people can read the placeholder then” you might say. When contrast is increased the placeholder copy can sometimes make it look like the input has already been filled in which can lead to more confusion.</p>
<figure>
<img loading="lazy" data-orient="portrait" src="/assets/images/modules/forms-placeholder-contrast-data.png" alt="A registration form with multiple fields. Placeholders are present in all fields but one. The placeholder copy is dark grey and looks the same as the one field which has been filled by the user." />
<figcaption>The Harbor Freight registration form. It is difficult to quickly identify if you have left any fields blank by mistake as the placeholder copy looks exactly like a filled input. Did you spot that we had only filled in the first field?</figcaption>
</figure>
<p>Some of the examples above use what is known as the “floating label pattern”. This is where the label sits over the input (so it looks like a placeholder) and then is animated to sit above the input once the user places focus in the field. This is better than just using the placeholder as a label, but issues remain:</p>
<ul>
<li>the label has to take on many characteristics of the placeholder (for example low contrast) to avoid looking like the input has been pre-filled</li>
<li>the label text ends up being overly small to avoid an odd layout shift when it is placed above the field as the inputs are typically closer together</li>
</ul>
<p>If the labels are going to float, why not just have them in that position in the first place?</p>
<h4>Placeholders for format information</h4>
<p>Even using placeholders for format information (what we will call hint copy) is problematic. Many of the reasons outlined above also apply, such as contrast issues.</p>
<p>Just as with labels, by removing the format information as the user starts typing you are preventing the user from checking their answer is correct before submitting the form. It also means you will need to be more verbose with any error messaging to make up for that loss of reference.</p>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-placeholder-format.png" alt="A registration form. The fields all use placeholders to provide the labels. The password field placeholder includes the format requirement of minimum of 5 characters. When the user types less than 5 characters and triggers an error, the format information is no longer visible. The error message tells the user the password is too short but omits the actual length needed.">
<figcaption>This registration form (from Ocado) uses placeholders to provide labels and format information (again below the minimum contrast requirement). The format information is lost as soon as the user starts typing. The error message does not include the format requirement so the user will need to guess how long the password needs to be.</figcaption>
</figure>
<h4>Repetition</h4>
<p>What often happens is placeholder information is added without considering the other options. With some thoughtful reworking we can remove the need for placeholders entirely.</p>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-placeholder-goodreads.png" alt="The Goodreads sign up form which asks for name, email and password. The name field has a label of your name and placeholder copy of first and last name. The password placeholder copy repeats the hint copy for that field which sites below it. Both these cause repetition of information. A revised design shows the name label has changed to first and last name and both placeholders have been removed.">
<figcaption>This signup form on GoodReads has a couple of places where information is being repeated. By revisiting the label copy for the name field we can dispense with the placeholder copy. The password field hint copy is already correctly marked up with ARIA so would repeat the placeholder copy. Again to avoid repetition we can simply remove the placeholder. The result is a less cluttered form with no repetition.</figcaption>
</figure>
<h4>Placeholder wrap-up</h4>
<p>Any situation where you end up removing visual information just as the user starts interacting sounds like a terrible idea. But this is exactly what we are doing with placeholders, however they are used. And if the removal of that information does not impact the user then you need to consider if it was really earning its spot on the page in the first place.</p>
<p><a href="https://www.smashingmagazine.com/2018/06/placeholder-attribute/">This is a great write-up</a> of some of the issues with placeholders.</p>
<p>In short, avoid placeholders entirely. Instead use well-sized labels and leave format information or examples to separate hint copy.</p>
<h3 id="hints">Hints</h3>
<p>We don't want to overload a label with too much information. However we still want users to understand if there are particular format requirements or help them understand waht they are being asked to enter a little better. The aim of the hint is to reduce cognitive load and prevent errors.</p>
<p>Good examples of a hint might be:</p>
<blockquote>
<p>“For example GB123456”</p>
</blockquote>
<p>when asking for some sort of reference number, or</p>
<blockquote>
<p>“You do not need to include any middle names”</p>
</blockquote>
<p>when asking for someone's name.</p>
<p>Because we do not want to include the hint in the label tag (labels should be short), we need to programmatically tie it to the input somehow so it will be noticed by screen-readers. The way we do this is by using ARIA.</p>
<div class="note note--activity">
<p>Here is an example of this in practice:</p>
<div class="example example--render">
<div class="form-group">
<label for="yourname">What is your name?</label>
<div id="name--hint" class="hint">You do not need to include any middle names.</div>
<input type="text" id="yourname" name="name" aria-describedby="name--hint" autocomplete="name" />
</div>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>yourname<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    What is your name?
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>name--hint<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    You do not need to include any middle names.
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> 
    <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> 
    <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>yourname<span class="token punctuation">"</span></span> 
    <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>name<span class="token punctuation">"</span></span> 
    <span class="token attr-name">aria-describedby</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>name--hint<span class="token punctuation">"</span></span>
    <span class="token attr-name">autocomplete</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>name<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
</code></pre>
</div>
<p>Here we have given the hint an <code>id</code> attribute which we then use in an <code>aria-describedby</code> attribute on the <code>input</code> itself.</p>
<p>The hint is now assigned as the “accessible description” for the input. Accessible descriptions are read out by screen-readers after the accessible name and a slight pause:</p>
<blockquote>
<p><strong>“What is your name?, edit text [pause] You do not need to include any middle names”</strong></p>
</blockquote>
</div>
<p>One thing to be aware of is that content which is announced using <code>aria-describedby</code> is stripped of all semantics. So it is best to keep this content as plain text.</p>
<p>For example, avoid adding a link to a hint such as below:</p>
<img loading="lazy" src="/assets/images/modules/forms-hint.png" alt="A text input with some hint text above it. The hint text has a link as part of the copy." />
<p>When a screen-reader lands on the input the hint will be read out as:</p>
<blockquote>
<p><strong>“This is 6 digits. Find your account number in your profile”</strong></p>
</blockquote>
<p>We can see immediately that the link is not announced, so the user is likely to miss that there is a handy link there.</p>
<p>Similarly some screen-readers (MacOS VoiceOver) will stop announcing <code>aria-describedby</code> copy when it encounters markup such as lists, so it is best to keep hint copy simple.</p>
<p>One final thing to be wary of with hints is colour contrast. It is often desirable to make the hints visually distinct from the adjacent labels. It can be tempting to reduced the contrast a little to achieve this. But be aware that all copy needs to be of sufficient contrast for all users to see it (at least 4.5:1 but in practice above this).</p>
<h3 id="errors">Errors</h3>
<p>If the data the user submits does generate an error we need to tell the user three things:</p>
<ol>
<li>that there was an issue with their submission</li>
<li>which field had the problem</li>
<li>how they can fix the issue</li>
</ol>
<h4>Tell the user there was an issue</h4>
<p>What a user is going to expect when they hit submit on a form is that they will get some sort of “success” message. So when they don't and instead find they are still where they were, we need to tell them why as soon as possible to prevent confusion.</p>
<p>This means we also need to think about managing the user's focus. If we don't manage focus, the user is going to be dropped back at the top of the page (assuming a page refresh happened) or stay on the submit button (with a javascript handled form). This can mean the user does not realise there was an error as the form and error message may be off-screen. Keyboard and screen-reader users would also need to navigate back down to the form.</p>
<p>If we are dealing with a multi-field form it can be best to present an error summary at the top of the page where it will be very visible when the page loads and we can also place focus on this. But if it is just a single field then placing focus on the field may be sufficient.</p>
<p>An error summary is a section above the form which lists all of the errors. This can be helpful as it makes it very obvious that something has gone wrong and we can even tell the user that in the error summary heading. The errors listed in the summary should be the same content and in the same order as those in the form it relates to. Ideally the errors in the summary should link to the field they relate to, enabling the user to quickly jump to the field to fix it.</p>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-error-summary.png" alt="An error summary with a red border and a list of error messages." />
<figcaption>An error summary can be helpful to alert the user that something has gone wrong.</figcaption>
</figure>
<p>It can also be helpful to add the word “Error” in front of the page title (in the tab bar) as this will mean a screen-reader user will hear that when accessing the page. This can be helpful if either the user switched tabs by mistake or moving focus failed.</p>
<h4>Which field had the issue</h4>
<p>We also want to make it clear which field or fields had the issue. We do this by displaying an error message next to the field (even if we are showing an error summary) and also adding some sort of visual treatment to make it easy to see the problem fields. The visual treatment should ideally be not just a colour change.</p>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-error.png" alt="An error message displayed below an input. The input's label has been changed to red and the error message has an error icon alongside." />
<figcaption>This field includes a clear visual indication that an error has occurred.</figcaption>
</figure>
<p>It is also important that the error message remains visible until the user submits the form again. This allows the user to refer to the error for help on fixing the issue.</p>
<p>The error message should be associated programmatically with the field just like we did with the hint, using <code>aria-describedby</code>. If we are also showing a hint for the field then the ids of the hint and error should be added to the <code>aria-describedby</code> in the order they appear on the screen so they are announced in the same order.</p>
<h4>How they can fix the issue</h4>
<p>Whilst just adding a message like “Invalid” next to a field may tell the user there is an error, it doesn't tell them how to fix it. Our error message should give the user specific information on how they can fix the issue they have.</p>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-error-message.png" alt="An input with an error. The error states the entered data is too long - the user has entered 8 digits instead of the 6 shown in the hint copy.">
<figcaption>This error message tells the user what is wrong and so helps them fix it. The hint shows an example of a correct format so the error does not need to repeat this.</figcaption>
</figure>
<p>We also want to make sure we are replaying the data they entered in the field when we show them the error. This means the user can see what in that field caused the error they are now seeing and helps them edit the answer to fix it.</p>
<p>If we don't do this it makes it more difficult to understand the error (as they may have just mis-typed something and be unaware they did) and it allows them to edit it to fix it.</p>
<h3 id="grouping-inputs">Grouping inputs</h3>
<p>For checkboxes and radio buttons which are in a set of options such as below, it is important to provide screen-readers with some way of understanding that they are part of a group beyond the shared <code>name</code> attribute.</p>
<img loading="lazy" src="/assets/images/modules/forms-radio.png" data-orient="portrait" alt="Four radio buttons showing choices for countries. Text above the group asks where do you live?">
<p>We can do this by using a <code>fieldset</code> and <code>legend</code>. As checkboxes and radio buttons have labels which indicate the value of each option we typically want to have some sort of question or name for the group.</p>
<p>The <code>fieldset</code> provides this grouping mechanism (if you are curious this actually has an ARIA <code>role</code> of <code>group</code>). The <code>legend</code> needs to be the first element inside the <code>fieldset</code> and this provides the accessible name for the group. Without the accessible name the group will not be announced.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>fieldset</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>legend</span><span class="token punctuation">></span></span>Where do you live?<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>legend</span><span class="token punctuation">></span></span>

    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>radio<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>eng<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>eng<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>country<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>eng<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>England<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">></span></span>

    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>radio<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>scot<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>scot<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>country<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>scot<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Scotland<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">></span></span>
    
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>radio<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>wales<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>wales<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>country<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>wales<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Wales<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">></span></span>
    
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>radio<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>nire<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>nire<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>country<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>nire<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Northern Ireland<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>fieldset</span><span class="token punctuation">></span></span>
</code></pre>
<p>The <code>fieldset</code> also means we have a nice grouping which allows us to assign an error message or hint to the contained fields as a set which is necessary as we will be validating these fields as a set.</p>
<p>We can assign a hint and / or error by using <code>aria-describedby</code> on the <code>fieldset</code>:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>fieldset</span> <span class="token attr-name">aria-describedby</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>country--hint country--error<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>legend</span><span class="token punctuation">></span></span>Where do you live?<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>legend</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>country--hint<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>This is your main residence.<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>country--error<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Error: select where you live.<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
    ...
</code></pre>
<p>Beyond checkboxes and radio buttons, fieldsets can also be useful if you are asking similar questions on the same page. Having the <code>legend</code> allows the fields to be named the same, but the <code>legend</code> and <code>fieldset</code> provide the differentiation - for example asking for shipping and billing addresses.</p>
<p>They can also be used to group other inputs which need to be seen by the user as related - for example a date group consisting of three text inputs for day, month and year.</p>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-dob.png" alt="A form asking for a date of birth. There are 3 inputs in a row labelled day, month and year. Above the inputs is text asking for the date of birth.">
<figcaption>As we would typically validate all three together a fieldset is a good fit and the legend will provide a meaningful name - here it is asking the question to which the 3 fields will together provide the answer.</figcaption>
</figure>
<p>What we don't want to do is apply fieldsets where we don't need them. This is because screen-readers will announce the <code>fieldset</code> as a “group” with the <code>legend</code> as the accessible name. We only want to be providing information like this where it will be useful, this keeps noise to a minimum.</p>
<h2 id="assistance">Assistance</h2>
<h3 id="validation">Validation</h3>
<h4>HTML5 Validation</h4>
<p>We need to talk about HTML5 validation at this point. When you use certain attributes such as <code>required</code>, <code>maxlength</code> and <code>pattern</code>, or certain input type attributes like <code>email</code>, this triggers HTML5 validation (also known as native browser validation or constraint validation). This is <a href="https://adrianroselli.com/2019/02/avoid-default-field-validation.html">not very good from a usability or accessibility point-of-view</a> - for example the messsages do not persist, have issues with zoom and the user only gets one error message at a time.</p>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-html5.png" alt="A form asking for their name and email which are both marked as required. A sequence shows the user having submitted the form blank and getting only one error message asking them to fill in the first field. They do this leaving the second field blank and submit again only to receive a new error message about the second field.">
<figcaption>An example of HTML5 validation in action showing one of the issues - the user needs to submit the form multiple times to see all the error messages.</figcaption>
</figure>
<p>Whilst it can be improved, it is a lot of work and just adds complexity. The recommendation is to disable HTML5 validation and handle error messages ourselves. Adding a <code>novalidate</code> attribute to our <code>form</code> tag will prevent this validation from ever appearing.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>form</span> <span class="token attr-name">action</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/<span class="token punctuation">"</span></span> <span class="token attr-name">method</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>post<span class="token punctuation">"</span></span> <span class="token attr-name">novalidate</span><span class="token punctuation">></span></span>
</code></pre>
<h5>Dynamic error handling</h5>
<p>Dynamic error handling, also referred to as client-side validation, is where fields are checked to see if the data is valid using javascript. This is best done when the user submits the form, rather than firing off errors whenever a user enters invalid data (what we will call inline validation).</p>
<p>The issue with inline validation is - when do you tell the user?</p>
<p>Often you will see websites trigger an error message as soon as you place your cursor in the field and it only clears when a valid entry is added. This is clearly problematic and not desirable.</p>
<p>How about validating after each character or word? Well consider how this might sound to a screen-reader user who is trying to check that they pressed the correct key. Each validation check would trigger an announcement which could prevent them from hearing information they need to fill in the field. Remember we</p>
<p>So how about validating when the user exits the field? The problem here is that the user has most likely moved to another field and will be on that field when the validation announcement is played. At best it is going to distract them from their current task of filling in the field, at worst depending on the error message they could think the error relates to the field they are on right now.</p>
<p>So validation is best left to when the user expects it - on form submission.</p>
<h4>Be forgiving</h4>
<p>We should also think about the validation we are carrying out. Our aim is to prevent the user from seeing any error messages. The best way we can do this is by using helpful labels and hints with examples of the data expected so the user is more confident about their submission. But where there is some format required it might be that by being just a little bit forgiving with our validation we can avoid the error in the first place.</p>
<p>Let's look at a couple of examples.</p>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-spaces.png" alt="A field asking for a tracking reference. The format required is shown as two letters followed by 8 numbers and an example is given. The user has entered their reference using lowercase letters and with spaces between some of the numbers. An error message is shown asking the user to use the given format.">
<figcaption>This is an example of a validation error the user did not need to see.</figcaption>
</figure>
<p>Here we have a tracking ID field which is asking for a 2-letter prefix followed by 8 digits. We have a hint with the format in to help the user. However this does not mean we have to be really strict with what we will validate. We can see the user has input lowercase letters (well we didn't say about it being case-sensitive) and the numbers have spaces every couple of digits.</p>
<p>There are a few reasons why a user may enter the reference in this way, for example:</p>
<ul>
<li>simply not understanding the format is strict with casing and spaces</li>
<li>when using speech-recognition or by using the voice-entry option on a mobile virtual keyboard. As the user reads out the reference, each time they take a breath the software will add a space, especially if the user groups numbers. For example the user may enter this by saying <em>“gee bee twelve thirty-four fifty-six seventy-eight”</em>.</li>
<li>users with low numeracy or dyscalculia may prefer to enter numbers with spaces to aid reading</li>
<li>users with poor motor skills may have difficulty changing case</li>
<li>screen-reader users will hear the hint but may not pick up on the casing</li>
<li>by copying and pasting from elsewhere - this can also introduce leading or trailing spaces</li>
</ul>
<p>Instead of failing this on validation we can be a bit smarter - and more helpful to the user. We can simply uppercase and strip out spaces from the user's entry and transform this into our desired format. We can see what they mean and are not changing any of the actual meaning of the data. But we will prevent the user from seeing an error.</p>
<p>In the next example (below) we have a field with a unit of measurement as part of it. The unit is displayed visually but it is hidden from assistive technology, instead the unit is mentioned in the label. However as screen-reader users cannot see the unit placed after the input, suggesting that the user does not need to add it, we should allow the unit as part of the entry and strip it out. Care should be taken to allow different versions of the unit which users may enter, such as different casing.</p>
<figure>
<img loading="lazy" data-orient="portrait" src="/assets/images/modules/forms-units.png" alt="A field asking for a weight in kilograms. A visual kg suffix has been added to the input but the user has entered a value including the kg unit.">
<figcaption>Here we should allow the unit despite it being provided and the server only expecting numbers in the submission.</figcaption>
</figure>
<p>The only place you may not be able to be as forgiving is if the data is case-sensitive or where spaces have meaning. But where possible we should be avoiding this being a requirement in content like reference numbers. By thinking about accessibility from the start we can look to design out stumbling blocks like this before the user is affected. This both helps speed up form completion and means less errors are seen which then reduces the overall cognitive load of the form.</p>
<h4>Optional or required</h4>
<p>It can be helpful to indicate in the label if the field is optional or not, the actual implementation will depend on your use-case. One thing to bear in mind is that the <code>required</code> attribute is to trigger HTML5 validation and prevent submission of empty fields. As we want to avoid HTML5 validation this is something we also want to avoid.</p>
<p>There is an <code>aria-required</code> attribute which purely signals to assistive technology that the field is required, but does not do anything beyond that - so does not trigger validation but also does not tell any other user that the field is required. Also bear in mind that if all your fields are required, having this attribute announced on every field can become intrusive for screen-reader users.</p>
<p>A better option is sometimes to just indicate the optional (or required) field status within the label. This way everyone gets the information.</p>
<h3 id="avoid-select-inputs">Avoid select inputs</h3>
<p>Whilst select inputs can offer an easy way to display a lot of potential answers, it has been shown that using them presents challenges to some users. This can be problems in trying to recognise which answer should be chosen (especially if the list is long), or difficulty in scrolling or picking from the list.</p>
<p>A better solution might be using a set of radio options, using a type-ahead or even reworking the design to avoid the need for the select input.</p>
<h3 id="avoid-disabled-buttons-or-inputs">Avoid disabled buttons or inputs</h3>
<p>A not-uncommon pattern is to disable a submit button until all fields in a form are filled in or valid. Disabling controls (inputs and buttons) is an issue for users for several reasons:</p>
<ul>
<li>to distinguish from non-disabled controls they often have reduced contrast making them difficult to read</li>
<li>users may not understand why a control is disabled and become frustrated</li>
<li>disabled controls are not included in the native tab order for keyboards</li>
</ul>
<h4>Disabled buttons</h4>
<p>The last point brings us onto another variation of this pattern which is <strong>hiding</strong> a button until certain prerequisites are fulfilled. Whether hiding or disabling the submit button, the user may not understand how they can proceed - they may not realise they have missed one of the requirements.</p>
<p>Instead keep it simple - present the button and allow the user to submit the page. Then explain why they cannot continue. If it is an issue with a field on the current page then display an error as normal. If it is more complex such as a section has not been completed then take the user to an explainer page where the issue can be detailed and the user directed where to go to fix it.</p>
<p>Here is an example of a button being disabled until inputs have been filled:</p>
<figure>
<img loading="lazy" data-size="implicit" src="/assets/images/modules/forms-disabled-input.png" alt="An address form. A field asking for the town is left blank and the submit button is a faint red." />
<figcaption>This form is waiting for the user to fill in all the fields (specifically the “Town or city” one) before the submit button has the disabled attribute removed. However it can be difficult for the user to perceive that the button is inactive and they are not being given any help to identify how to proceed.</figcaption>
</figure>
<p>The issue here is the user may be trying to click the button but nothing happens - and no error message is shown. It is not clear that the button is in fact disabled. This means the page is asking the user to problem-solve why they cannot submit the form. The user may work it out or they may abandon the task.</p>
<p>A better solution would be to allow the user to submit the form and then provide error messaging for the missing field information. This requires more work and thought from the team, but will result in a better outcome for the user and likely less abandoned forms.</p>
<h4>Disabled inputs</h4>
<p>Similarly disabled inputs can be an issue. The contrast has to change to indicate the difference to normal inputs, but this is either so slight as to be hardly percievable (causing users to click on the input thinking it is an active input) or so different as to make the text in the input unreadable. They are also not included in the natural tab order.</p>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-disabled.png" alt="A login form with fields for email and password. Both are filled. The email field has a button labelled change on the far right.">
<figcaption>Here the email field has been marked as `disabled` but is not styled any differently to the active password field. The password field appears after the email field has been submitted but the email field remains styled as when the user entered data. The presence of the 'change' option on the far right is likely to be missed by users (especially those using screen-magnification) whose attention is going to be trying to click on the field to focus it.</figcaption>
</figure>
<h3 id="avoid-read-only-inputs">Avoid read-only inputs</h3>
<p>As with disabled controls, read-only inputs tend to cause confusion. Whereas a disabled control is removed from the tab order, a read-only one remains in place but cannot be edited. This duality can be confusing, especially as the read-only state is not visually communicated.</p>
<p>This is often done to save development time - it is easier to just switch out the <code>readonly</code> attribute than do the work needed to use static text instead and the potential styling and routing for edit option requirements. But by doing this work we can make a more understandable interface.</p>
<p>Instead make it clear what the user is looking at and how to proceed. If the data is not in an editable state then display it as text and have an “edit” button alongside if needed. This way the user can see what they can edit.</p>
<h3 id="showing-the-correct-keyboard">Showing the correct keyboard</h3>
<p>Most of the time when entering data in a field on a touch-screen device you will be using the standard virtual keyboard which shows the QWERTY key layout.</p>
<p>But sometimes we might want to alter which keyboard is shown. For example if the user is entering a phone number then having to switch to the number keyboard will take time and effort and even then it may not be easy to use.</p>
<p>For this reason we are able to give the user's device hints as to which keyboard should be shown for a given input. For example for a field asking for an email address we can present a specific virtual keyboard which includes email-specific keys such as <kbd>@</kbd>. This saves the user having to switch keyboards part-way through their entry to find that symbol.</p>
<p>We can do this by using either specific <code>type</code> values (which have an implicit <code>inputmode</code>) or by using the <code>inputmode</code> attribute directly. Some of the more useful <code>inputmode</code> values:</p>
<ul>
<li><code>inputmode=&quot;tel&quot;</code> (or <code>type=&quot;tel&quot;</code>) will present a phone keypad making it much easier to add a phone number</li>
<li><code>inputmode=&quot;email&quot;</code> (or <code>type=&quot;email&quot;</code>) will add specific email address characters like <kbd>@</kbd> and <kbd>.</kbd></li>
<li><code>inputmode=&quot;numeric&quot;</code> will display numbers but should only be used for whole numbers as the keyboard may not include a decimal point</li>
</ul>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-inputmode.png" alt="Two virtual keyboards. One is labelled email and is a standard qwerty keyboard but with the addition of an @ symbol which is highlighted here. The second shows a keyboard labelled as tel and has a phone keypad.">
<figcaption>Two examples of the different keyboards which can be provided to users using these attributes. These are Android examples, iOS ones will differ. The telephone one especially makes it much easier to enter phone numbers due to the larger size of the keys compared to a standard keyboard.</figcaption>
</figure>
<h4>Things to avoid with <code>inputmode</code> and <code>type</code> attributes</h4>
<p>The actual keyboards presented will depend on the operating system so it best to conduct testing if exploring other options.</p>
<p>There is an issue with some system's handling of <code>inputmode=&quot;decimal&quot;</code>. Whilst this should display a number keyboard (as <code>numeric</code> does) but with the addition of a decimal and/or comma, some systems omit to include the decimal. As such it is best to avoid this value or do comprehensive testing.</p>
<p>Be aware that the <code>type=&quot;numeric&quot;</code> should be avoided. This has also had a troublesome past with some browsers allowing the user to enter non-numeric values but then stripping them out of the data actually sent to the server. It even caused issues with numbers entered with decimal points as they aren't whole numbers. Instead stick to the <code>inputmode=&quot;numeric&quot;</code> attribute to provide assistance without the validation issues.</p>
<h3 id="helping-browsers-autofill-inputs">Helping browsers autofill inputs</h3>
<p>It can be annoying to have to keep typing your name, contact information and payment information into forms all the time. Browsers can now store this data for you and when they see a form which is asking for it prompt you to autofill it from this stored data.</p>
<p>This can be very useful for people who have cognitive conditions which affect their memory for example or those who find typing difficult or tiring. Whilst browsers can try to work out which fields to suggest autofilling they can sometimes get it wrong. This can end up with the browser not prompting the user, leaving some fields blank or in some cases adding the data to the wrong field. As such it is always best to help the browser out by telling it what data (if it has it) it should add to which field.</p>
<p>This is done by using an <code>autocomplete</code> attribute with a set value. For example here is how we would mark up a field which is asking for someone's full name:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>fullname<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Full name<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>fullname<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>fullname<span class="token punctuation">"</span></span> <span class="token attr-name">autocomplete</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>name<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
</code></pre>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-autocomplete.png" alt="An input asking for the user's full name has focus. A pop-up shows names which the browser has stored which the user can pick from to fill this field.">
<figcaption>Here is the above code as it might look in the browser. Here I have been shown a list of 3 possible names to pick from with which to fill the field. These are all names the browser has stored from previous form-filling.</figcaption>
</figure>
<p>This has some obvious benefits:</p>
<ul>
<li>reduced typing for the user</li>
<li>allows the user to use recognition rather than recall</li>
<li>avoids introduction of spelling mistakes</li>
<li>speeds up form filling, especially for addresses</li>
</ul>
<p>Note we should normally only add autocomplete attributes to fields where we are asking for data which we can anticipate they have the data for. This is normally their own personal data. So if the above field was asking for someone else's name we would not add the attribute.</p>
<p>For some data we can add more than one value to be specific, such as here where we are asking for the person's work phone number (as distinct from their home phone):</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>phone<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>What is your work phone number?<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>tel<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>phone<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>phone<span class="token punctuation">"</span></span> <span class="token attr-name">autocomplete</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>work tel<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
</code></pre>
<h3 id="focus-indicators">Focus indicators</h3>
<p>Just as with other controls, form inputs and buttons should have very visible focus indicators. For text inputs, strictly speaking the cursor flashing is counted as enough of a focus indicator to pass <a href="/posts/guidelines-and-legalities/#wcag">WCAG compliance</a>, but some users may modify their cursor not to flash and besides we want to go <a href="/posts/guidelines-and-legalities/#standards-and-legislation-are-the-baseline-not-the-target">way beyond just compliance</a>.</p>
<p>Ensure that at least some of your error styles are not obscured when the field is focussed.</p>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-focus.png" alt="Two text inputs. The first has the cusor active and is visually different from the second as it has a more prominent border treatment." />
<figcaption>The Marks & Spencer registration form shows a good focus indicator. It adds an extra outline around the input which visually alters the dimensions and makes it immediately obvious which field has focus. Unfortunately this is also another example of the use of placeholders only providing repetition rather than any value to the user.</figcaption>
</figure>
<p>Whilst browser default styling is enough to pass compliance for radio button and checkbox indicators, in reality they are very poor. So we would want to also provide good focus indicators to the non-text inputs too.</p>
<p>Providing custom focus indicators for form controls can really help users find their place in the heavily interactive landscape of a form. Be careful not to cause <a href="/posts/keyboard-accessibility/#how-styling-can-impact-functionality">additional accessibility issues</a> when adding styling.</p>
<h3 id="do-not-disable-copy-and-paste">Do not disable copy &amp; paste</h3>
<p>Sometimes there is a requirement to disable copy &amp; paste in a form. Requirements like this should be scrutinised to see if a different approach could be used instead. Removing the user's ability to copy &amp; paste is going to disadvantage users who may rely on this - for example speech-recognition users often work within a sandbox area to generate responses which they copy &amp; paste into a field.</p>
<p>Look for alternatives. For example, you are asking for an email address twice to prevent errors and are disabling copy &amp; paste to force the user to type it in twice. Instead add an autocomplete attribute to an email field potentially avoids the user typing at all, and then you could replay the entered email before submission, or send a confirmation email.</p>
<h3 id="avoid-using-maxlength">Avoid using maxlength</h3>
<p>The <code>maxlength</code> attribute is often used when asking for data which we expect to be a certain length and no more. For example reference numbers or dates. The issue with this is that users are not told when the limit is reached, often browsers will just stop responding to data entry. Even if we tell the user in a hint how many characters the answer should be it can still cause issues.</p>
<p>We have already discussed not disabling copy &amp; pasting. Users may need to paste in a larger answer before editing it down. Similarly for longer answers (such as in a <code>textarea</code>) it is best to allow the user to go beyond the allowed limit within the field to finish a train of thought and then they can reduce their answer by editing it down.</p>
<p>We have also seen how speech-recognition can add spaces to data entry and how we should be forgiving of this in our validation. If we physically restrict the data length we can end up with some very unsatisfactrory outcomes.</p>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-maxlength-bad.png" alt="A field asking for a tracking reference. The format required is shown as two letters followed by 8 numbers and an example is given. The user has entered their reference using lowercase letters and with spaces between some of the numbers. Six characters and two spaces of the user's entry are showing in the input." />
<figcaption>This is our tracking reference from earlier. If we had applied a maxlength attribute limiting the input to the expected data (8 characters) then our users would run into issues when entering the data with spaces as the input would stop accepting any more characters after the first 8. The user would then receive an error stating that the data was not valid.</figcaption>
</figure>
<p>The best approach is to let the user know of the required format but allow them to exceed it in their submission and if necessary display an error message to allow them to edit their answer down to the correct length.</p>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-maxlength-good.png" alt="A field is asking for a last name. The user has entered Harrington-Stanley which is 18 characters and an error has been returned telling the user that the last name casn be a maximum of 17 characters. The user's data is retained in the field in full." />
<figcaption>The Oakley registration form only allows for 17 characters for last names. Whilst this is not helpful (especially for those with 18-character double-barrelled names as above) they at least allow the user to enter what they want in full and then present the issue. This allows the user to see the issue and potentially edit their answer (or in this case likely go elsewhere).</figcaption>
</figure>
<p>Something to bear in mind with this example is that the user was not notified of the restriction ahead of entering their information. It is always a good idea to make the user aware of format requirements so they can adjust their answer accordingly and avoid the error in the first place. In this case the limit is really too restrictive for the required data and we'd want to set a limit which the user would be very unlikely to hit (such as 50 characters) - if we did this we would not need to make the user aware as no-one should hit the limit.</p>
<p>For larger blocks of text where the user is being asked to submit several sentences of copy, we can look at using dynamic messaging. This can indicate how many characters they have left and even more usefully how many they are over the limit by. This can make use of an <code>aria-live</code> region to ensure screen-reader users are updated too.</p>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-charactercount.png" alt="A sequence showing the three different states of a textarea character counter. The first shows a textarea with content and no additional messages beyond the label. The second shows more content has been added and now a hint has appeared indicating how many characters the user can still enter. The third shows the user has entered more content and now the message is displayed in an error style telling the user they have used 4 characters too many.">
<figcaption>The GOVUK character counter tells users when they are getting close to the maximum allowed characters and when they have exceeded the allowance. This allows the user to edit down their response without having their ability to finish their thought (or copy & paste) being restricted.</figcaption>
</figure>
<h3 id="size-fields-to-expected-data">Size fields to expected data</h3>
<p>For visual users it can be a help to size text fields to give an indication of the amount of data required. For example the field for a post code should be shorter than that for an email address.</p>
<p>Having a field which is too large or too small can make the user wonder if they are entering the correct data. A field which is too small can also make it difficult to read the content and even more difficult to edit it confidently. Always ensure the field is large enough to accomodate the longest answer you might expect.</p>
<h3 id="review-before-submission">Review before submission</h3>
<p>It is good practice to allow users to review the data they have entered before they finally submit it, particualry if there are more than a few questions. This should also provide an opportunity for them to change any of their answers. This is especially important when the thing the user is submitting is to do with official documents - such as a government application, legal or financial processes.</p>
<figure>
<img loading="lazy" src="/assets/images/modules/forms-edit.png" alt="A user's answers are replayed to them. Alongside each answer is a link to allow them to edit that answer.">
<figcaption>Have a step at the end of a form submission where the user can review their answers and correct any mistakes.</figcaption>
</figure>
<p>When a user goes to edit one of their responses we should where possible take them to the same page where they entered the data, with their data pre-populated. This should provide the same labels, hints and guidance material they had first time around as well as letting them re-read their answer and edit it if needed. By replaying their answer we allow them to simply correct a spelling issue without having to re-enter the whole thing.</p>
<p>Once the user has finished editing their answer we should return them directly back to the review screen - not require them to resubmit each subsequent page after the one they just edited. There may be some additional work involved if the form included branching questions to clean up redundant answers or present additional questions where necessary, but the user should be returned to the review screen as soon as possible.</p>
<h2 id="wrap-up">Wrap-up</h2>
<p>Forms are a complex thing and offer many places where we can inadvertently place barriers in the way of users accomplishing the task they are set on.</p>
<p>By considering how we can reduce the friction users have with forms we can make this potentially stressful part of digital interaction less daunting.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Accessible content</title>
        <link href="https://liptrot.org/posts/accessible-content/"/>
        <updated>2024-09-18T13:00:00Z</updated>
        <id>https://liptrot.org/posts/accessible-content/</id>
        <content type="html"><![CDATA[
          <h2>Contents</h2>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#inclusive-content">Inclusive content</a></li>
<li><a href="#plain-language">Plain language</a></li>
<li><a href="#colours">Colours</a></li>
<li><a href="#directional-content">Directional content</a></li>
<li><a href="#headings">Headings</a></li>
<li><a href="#links-and-buttons">Links and buttons</a></li>
<li><a href="#image-alt-text">Image alt text</a></li>
<li><a href="#charts-and-graphs">Charts and graphs</a></li>
<li><a href="#transcriptions-captions-audio-description">Transcriptions, captions and audio description</a></li>
<li><a href="#adjusting-content-for-screen-readers">Adjusting content for screen-readers</a></li>
<li><a href="#form-content">Form content</a></li>
<li><a href="#wrap-up">Wrap up</a></li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>Content is the first building block of a website, so it is crucial to how accessible the final product will be. If a user is unable to access or understand the content the rest of the page will fail along with it.</p>
<p>When writing accessible content we should favour clear messaging and understanding over anything else.</p>
<h2 id="inclusive-content">Inclusive content</h2>
<p>One of the important aspects of accessibility is making all our users feel considered and welcome in the end result. Writing inclusive content is a large part of this. Content should be free of bias and exclusionary or discriminatory language. This is especially important when it comes to asking users for personal information.</p>
<p>Think about how we talk about age, disabilities, ethnicity, religion, gender and sexuality. But this also means thinking about the way we ask questions to allow a wider accepted answer. For example rather than asking for “First name” and “Last name” simply asking for ”Full name” can make entering this information easier and less of a barrier.</p>
<h3>A wide audience</h3>
<p>Writing accessible content is not just writing alt text for images and copy for screen-readers. It is making content easy to understand for as many people as possible.</p>
<p>For example, short-term memory conditions (such as dementia) might mean the user loses their place when reading a page. In these cases reducing the cognitive load can help. A well written page broken up into sections reduces the cognitive load and helps the user find their place again. This <a href="http://www.innovationsindementia.org.uk/wp-content/uploads/2023/01/accessible-writing-guide.pdf">guide to writing better for those with dementia (PDF)</a> also includes some very good general accessibility content guidance.</p>
<h3>More reading on inclusive content</h3>
<ul>
<li><a href="https://service-manual.nhs.uk/content/inclusive-content">NHS Inclusive Content guidance</a></li>
<li><a href="https://www.gov.uk/government/publications/inclusive-communication/inclusive-language-words-to-use-and-avoid-when-writing-about-disability">Inclusive language: words to avoid when writing about disability - Gov.UK</a></li>
<li><a href="https://atlassian.design/content/inclusive-writing">Inclusive Language guidance - Atlassian</a></li>
</ul>
<h2 id="plain-language">Plain language</h2>
<p>Content construction is at the core of writing accessible content.</p>
<p>As well as being easier to digest for all users, plain language can be essential for some groups such as</p>
<ul>
<li>those for whom English is not their first language (including some British Sign Language users)</li>
<li>those with cognitive conditions such as dyslexia which make reading more difficult</li>
</ul>
<p>Especially for online content, we should be looking at a reading age of around 9 years old. Lengthy sentences should be avoided where possible. Long sentences can slow down reading speed and make it more difficult to understand what is being said.</p>
<p>Other things to avoid are:</p>
<ul>
<li>acromyns - if needed then they should be written out in full with the acromyn alongside when first used on a page (for example &quot;Pay As You Earn (PAYE)...&quot;)</li>
<li>jargon - even when writing for a professional audience, using simple terms rather than jargon can make things easier to understand</li>
<li>slang, metaphors and similies - these can be confusing for people with certain cognitive conditions and for those for whom English is not their first language</li>
</ul>
<p>Tools such as <a href="https://readable.com/">Readable</a> and <a href="https://www.grammarly.com/">Grammarly</a> can be used to test our content for any potential issues and help aim for the right reading age level.</p>
<h3>Plain numbers</h3>
<p>If the content deals with numbers in any way we should look at how to support users who have may have difficulty with them. This includes conditions such as dyscalculia (which is a difficulty in dealing with or understanding numbers) and low numeracy skills in general.</p>
<p>Simplifying and explaining numbers and calculations can help. We should also avoid asking users to do calculations themselves (including things such as rounding up a figure).</p>
<figure>
    <img src="/assets/images/modules/content-numbers.png" data-size="implicit" alt="Two screenshots of an energy usage summary. One shows the before and is a table of numbers. The second shows after and is worded more conversationally. The second screenshot highlights how numbers have been rounded to decrease complexity whilst the narrative form helps with understanding.">
    <figcaption>Octopus Energy worked to improve their customer understanding of energy consumption numbers. They found an increase in comprehension of the various data in the summary of between 9% and 25%. <a href="https://static1.squarespace.com/static/5f7f7734f7e47f08bc961018/t/60dcd93f4e4c433c2bb05da5/1625086280079/Plain_Numbers_Research_Report.pdf" target="_blank">Source (PDF, opens new tab)</a></figcaption>
</figure>
<h4>More reading on writing with numbers</h4>
<ul>
<li><a href="https://accessiblenumbers.com/">Accessible Numbers</a></li>
<li><a href="https://designnotes.blog.gov.uk/2022/11/28/designing-for-people-with-dyscalculia-and-low-numeracy/">Designing for people with dyscalculia and low numeracy - Gov.UK</a></li>
</ul>
<h2 id="colours">Colours</h2>
<p>We should not rely on colour alone to convey information. For example using green to signify success and red to indicate an error, or phrases like “<em>pending applications are shown in blue</em>”.</p>
<p>Users with visual conditions such as colour-blindness as well as screen-reader users will be unable to perceive the connection. We should ensure that the information is communicated in an alternate way such as a text label. Other visual differentiators such as a shape or pattern can be used, although we should ensure the same information can also be perceived by screen-reader users.</p>
<p>Tools like <a href="https://www.colororacle.org/">Color Oracle</a> can be used to simulate how colour-blind users might see a page.</p>
<h2 id="directional-content">Directional content</h2>
<p>Screen-readers consume content in source-code order which may be different from the visual layout. Bear this in mind when assuming a user has seen or read content from elsewhere on the page.</p>
<p>As screen-readers linearise the page for the user (as they read the source code), we should not use language which refers to a &quot;left&quot; or &quot;right&quot; direction when referencing other content. For example avoid saying <em>&quot;the image on the left shows ...&quot;</em>. Using &quot;above&quot; or &quot;below&quot; is ok, but make sure to check that the visual position also matches the source code order and that the visual layout doesn't change depending if the page is viewed on mobile or desktop.</p>
<h2 id="headings">Headings</h2>
<p>Breaking up content with section headings as already mentioned goes a long way to improving accessibility for many users.</p>
<p>Screen-reader users employ similar scanning techniques to how visual users do, just using elements instead. For example they may read all the headings first to determine if any of the sections might contain the information they need. Headings are one of the main ways screen-reader users navigate around busy pages.</p>
<p>The hierarchy of the content should be reflected in the headings used. Heading hierarchy moves down from <code>h1</code> (level 1) to <code>h6</code> (level 6). A page should only have one <code>h1</code> which should be the principle headline or purpose for the page. Other headings normally follow the <code>h1</code> and it is important that they are marked-up correctly as these are announced by screen-readers to help users understand how content is related.</p>
<figure>
    <img src="/assets/images/modules/content-hierarchy.png" data-size="implicit" alt="A screenshot of a component on the Forumula E website. It has a large overall title and 4 cards each with its own title. All titles are marked up as h2 elements.">
    <figcaption>Here sub-headings have been set at the same level as their parent. Both have been set as <code>h2</code> despite the ones below the images being sub-sections of the main heading. Not presenting a clear hierarchy in the code means it is much more difficult for non-visual users to find information. The sub-headings should be <code>h3</code> so they sit under the <code>h2</code> in the hierarchy and reflect the relationship between content.</figcaption>
</figure>
<p>Providing an annotated screenshot with each heading level indicated is one way to communicate the hierarchy to developers. This can be especially useful where areas of a page use different font sizes for the same heading level.</p>
<h2 id="links-and-buttons">Links and buttons</h2>
<p>It is useful for all users that links and buttons are descriptive of the thing they link to or the action they will perform.</p>
<h3>Magnification users</h3>
<p>When using high magnification a user might not have clear view of the surrounding context for a link or button. Making them descriptive can add confidence and avoid the user having to go back through the preceeding copy to confirm.</p>
<h3>Screen-reader users</h3>
<p>Screen-reader users can extract lists of elements from the page to examine in isolation from the rest of the page copy. This includes links. Because of this all link copy should be both unique and give some indication of the destination, ideally even when taken out of the context of the page. It might be that adding this kind of information might make the page overly cluttered. In this case we can add additional copy which won't be visible but which screen-readers will still pick up.</p>
<p>For example we can use a <a href="https://gist.github.com/adamliptrot-oc/8ab7a5daca427592271a8201b6374c51"><code>visually-hidden</code> CSS class</a> to hide the additional content but which still allows it to be picked up by a screen-reader. To a visual user both links below will read “Change”, but to a screen-reader user they will be announced as “Change your name” and “Change your address”. The same effect could also be achieved using <code>aria-label</code> - <a href="/posts/aria/">read more about ARIA</a>.</p>
<div class="example example--render">
    <dl>
    <dt>Your name</dt>
    <dd>Bob Hoskins</dd>
    <dd><a href="#">Change<span class="visually-hidden"> your name</span></a></dd>
    <dt>Your address</dt>
    <dd>128 Spring Gardens, London, SW1 8ER</dd>
    <dd><a href="#">Change<span class="visually-hidden"> your address</span></a></dd>
    </dl>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    Change
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>visually-hidden<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> your name<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    Change
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>visually-hidden<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> your address<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
</div>
<h3>Speech-recognition users</h3>
<p>Speech-recognition users use their voice to click buttons, links and inputs and need to know what they need to say to perform that action. So if a button contains the text &quot;Send&quot;, then they would expect to be able to say &quot;Click send&quot; to action it. This is why having a visible label for each is important.</p>
<p>Speech-recognition software is also affected by hidden copy like we used in the example above, just like screen-readers, but users of it can only see the <strong>visible</strong> copy.</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Change<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>visually-hidden<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> your address<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<figcaption>Whilst a screen-reader user will get "Change your address" announced, a speech-recognition user is going to see "Change" so will say "Click change" to try to action the link.</figcaption>
</figure>
<p>In our example above, the user might say “<em>Click Change</em>”. In this case, even though this is not a full match, the software should do a partial match on that phrase to both links and the user will be able to choose from either.</p>
<p>It is important that any visually-hidden content such as on links this is added <strong>to the end</strong> of the visual copy. As speech-recognition software pattern-matches the spoken word to elements on the screen, adding copy before or between it can interfere with this.</p>
<p>However, if we add the hidden copy <strong>before</strong> or <strong>inbetween</strong> the visual copy (as below) it might make it much more difficult for them to trigger that link. This is because the user will say “<em>Click Edit account</em>”, but the software will not find a match to the spoken phrase.</p>
<div class="example example--render">
    <p><a href="#">
    Edit 
    <span class="visually-hidden">Bob's</span> 
    account
</a></p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    Edit 
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>visually-hidden<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Bob's<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span> 
    account
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
</div>
<p><a href="/posts/links-hidden-copy-and-voice-recognition/">Speech-recognition software varies in their pattern-matching skills</a>, so results can vary. The aim is always to make it as easy as possible for users to trigger the command they want.</p>
<h3>Telling a user about context-change</h3>
<p>Finally, if opening links in a new tab it is advisable to tell users this as part of the link copy. Studies have shown opening a link in a new tab without warning can disorientate users. We add the text to the link to be sure screen-reader users get this information too. For example:</p>
<div class="example example--render">
<a href="#" target="_blank">View our guidance (opens in new tab)</a>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span> <span class="token attr-name">target</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>_blank<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    View our guidance (opens in new tab)
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
</div>
<h2 id="image-alt-text">Image alt text</h2>
<p>Some users cannot see the images we use and so it is down to us to make sure they are not missing out. This means being thoughtful about what alt text we use on those images. Because alt text is literally out of sight it is often thrown in just as a filler without much thought to what the user might need.</p>
<h3>Types of image</h3>
<p>There are several types of images when it comes to alt text:</p>
<h4>Utilitatian</h4>
<p>For these the alt text may often not be a description of the image, but an indication of its function.</p>
<p>For example, icons which need to communicate functional meaning like a &quot;menu&quot;.</p>
<figure>
    <img src="/assets/images/modules/accessible-content-menu.png" alt="Menu" data-size="implicit">
    <figcaption>An image such as a 'hamburger' menu would not make sense if we described the image itself - "three horizontal lines placed vertically above each other". Instead describing the function is more useful - "Menu".</figcaption>
</figure>
<p>Of course where these functional images are used we need to ensure that the words we use are going to be the words the users would use. After all a speech-recognition user is going to need to use these words to activate it. If in doubt it can be best to add visible text to the control and leave the alt text blank:</p>
<div class="example example--render">
<img src="/assets/images/modules/content-my-account.png" alt="Screenshot of an icon in the shape of a person next to the text My account." data-size="implicit">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/i/my-account.png<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span> My Account<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
</div>
<p>Note we don‘t start alt text with <em>“image of”</em> as screen-readers will already get this information from the element.</p>
<h4>Informational</h4>
<p>This is the typical image you might think of when adding alt text. They are images which add information to the wider content, perhaps to illustrate a point or give further clarity. The idea here is to describe the image to support the surrounding content. Care should be taken not to add information which is not available in the image as users who cannot see the alt text will not have access to it.</p>
<div class="example example--render">
<img src="/assets/images/modules/content-informative.png" alt="A classic 2-door yellow sports car with a roof-rack. On the roof rack is a christmas tree." data-size="implicit">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>..<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>A classic 2-door yellow sports car with a roof-rack. On the roof rack is a christmas tree tied down with bright green straps.<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
</code></pre>
</div>
<h4>Emotional</h4>
<p>These are images which can sometimes be thought of as decorative. Occasionally an image may be added to a page to impart a certain feeling. Screen-reader users should also benefit from this as it may change how they read surrounding copy. Try to put across a sense of this emotion in the alt text as you describe the image.</p>
<h4>Decorative images</h4>
<p>There are cases where an image should not have any alt text (although they should <em>always</em> have an alt attribute). For example it could be that the image is purely decorative. In these cases it might be that not adding alt text is the right thing to do.</p>
<h3>Consider context</h3>
<p>The important thing to consider when adding alt text is the context. The image is often trying to put across a specific message to support the surrounding content rather than just being placed there in isolation. This could mean that the same image used in several places across a site may have different alt text in each use-case. It may also mean that you need to take the audience and their level of knowledge into account.</p>
<h3>What is the important information?</h3>
<p>A screen-reader can only do one of two things with alt text. Listen to the whole thing or stop listening part-way through. There is no way for them to skip through, so if you put important information at the end one of two things can happen - they will have to listen to the whole thing each time, or they might even miss it, moving on once they think they have got the gist.</p>
<p>For this reason look to front-load alt text where possible by giving the important information at the start.</p>
<h3>Avoid repetition</h3>
<p>There is a reason we might want to use an empty alt attribute on what would otherwise be thought of as an informational or utilitatian image. This is where adding alt text would cause immediate repetition for a screen-reader. This can also make a link more difficult for speech-recognition users.</p>
<figure>
    <video src="/assets/images/modules/content-alt-repetition.mp4" data-size="implicit" controls="show"></video>
    <figcaption>A group table from the Euro 2024 site. The country names in the first column each have a flag alongside with alt text set to the country name. This causes a screen-reader to read each country out twice.</figcaption>
</figure>
<h3>Alt text vs image captions</h3>
<p>Alt text is very different to a figure caption and the two are not mutually exclusive. Alt text as has been discussed is about describing the image for those who cannot see it and it does not add any more information than what is in the image. A caption can add more context to the image.</p>
<figure>
    <img src="/assets/images/modules/content-captions.png" data-size="implicit" alt="an image of a horse outside a polling station. The caption underneath reads ‘Ace waits for his owner outside Sandbach rugby club in Cheshire’.">
    <figcaption>The alt text for the image in this screenshot reads “<i>A horse tied to a railing outside a polling station.</i>” which just describes the image. The caption adds more context for all users such as the horse's name and town.</figcaption>
</figure>
<h3>More reading for alt text</h3>
<p>Alt text seems simple but is deceptively difficult to write well. Here is some more reading to help:</p>
<ul>
<li><a href="https://ericwbailey.website/published/dungeons-and-dragons-taught-me-how-to-write-alt-text/">Dungeons &amp; Dragons taught me how to write alt text - Eric Bailey</a></li>
<li><a href="https://www.smashingmagazine.com/2021/06/img-alt-attribute-alternate-description-decorative/">Your Image Is Probably Not Decorative - Eric Bailey</a></li>
<li><a href="https://jakearchibald.com/2021/great-alt-text/">Writing great alt text: Emotion matters - Jake Archibald</a></li>
<li><a href="https://tink.uk/text-descriptions-emotion-rich-images/">Text descriptions and emotion rich images -  Léonie Watson</a></li>
<li><a href="https://adrianroselli.com/2024/05/my-approach-to-alt-text.html">My Approach to Alt Text - Adrian Roselli</a></li>
</ul>
<h2 id="charts-and-graphs">Charts and graphs</h2>
<p>These can be tricky as some of the content may be available to screen-readers, but because graph and chart output can vary so much depending on the technology used it needs to be tested properly by the team. If we cannot make the output accessible to all, then we need to consider alternates which could convey the same information.</p>
<p>A <a href="https://accessibility.blog.gov.uk/2023/04/13/text-descriptions-for-data-visualisations/">written version of the data</a> can help the all users understand the visual whether they can see it or not, especially if they find working with numbers difficult. We might add a curated summary of the content if the data is static or easily adapted. If the data is more dynamic and precludes a summary written in advance, one option is to look at <a href="https://chartdescriptions.com/">using AI to provide one</a>, using a well-crafted prompt, to highlight trends in the data.</p>
<p>If the data is more complicated and the user might want to look at all the data points then offering a tabular version means a screen-reader can access the data on-screen. An optional downloadable version (for example as a spreadsheet file) would mean any user could open the data in their accessible app of choice.</p>
<h2 id="transcriptions-captions-audio-description">Transcriptions, captions and audio description</h2>
<p>Just as with images, not all users can watch video content or listen to audio. The difference with audio and video is that the audience is even wider. They allow users who cannot consume the original to follow along but also help users who may have trouble understanding the original for whatever reason.</p>
<h3>Transcriptions</h3>
<p>Transcriptions are a written version of the audio which can optionally be synchronised to the original. As well as making the content available to those who would otherwise miss out, it makes that content more easily consumable and findable. They enable users to skim, search or review the transcript to see if it contains the information they are looking for without having to sit through the entire original. In addition to this it can make the content easier to follow for someone who has difficulty keeping up with captions. Transcriptions should be placed alongside the player so they are easy to find and can be followed as the video plays.</p>
<h3>Captions</h3>
<p>Captions are placed over the video and allow the user to follow along without the audio. They include any dialog but also noises and other audible information. In this regard they differ from subtitles which are intended to be consumed by those who can hear the audio and which contain purely the voice content - for example they are used where languages are being translated. Ideally videos should use a platform which allows captions to be adjusted to a size and colour which suits the user.</p>
<h3>Audio description</h3>
<p>Audio description is an additional audio track laid over a video describing what is happening on-screen for those who cannot see it. At its most complex this can be found on tv shows and movies. But even short videos for the web can benefit from an audio description if there is on-screen information which is not verbalised in the video.</p>
<h2 id="adjusting-content-for-screen-readers">Adjusting content for screen-readers</h2>
<p>It can be tempting once we hear content read out by a screen-reader want to change how some of it sounds.</p>
<p>For example a reference number might be read out differently to how we might expect or desire:</p>
<blockquote>
<p>&quot;QQ123456C&quot;</p>
</blockquote>
<p>might be read out as</p>
<blockquote>
<p>&quot;Q Q one hundred and twenty-three thousand four hundred and fifty-six C&quot;</p>
</blockquote>
<p>Resist the urge to ask developers to change how this sounds by manipulating screen-reader copy or adding various attributes to it. Screen-reader users are listening to content all day and know how things sound. They can also adjust how their screen-reader reads out this kind of content and if they want can also read it out character-by-character.</p>
<p>Trying to adjust content purely for a screen-reader can also have knock-on effects for other users such as braille and speech-recognition users.</p>
<p>However, sometimes it might be that changing how our content is written <strong>can improve understanding</strong>.</p>
<p>This could be removing some repetition, such as we have already discussed around image alt text. But it could also be about making our content more understandable when removed from the visual context. By listening to the content in isolation we can sometimes find improvements because our brain is not visually filling in missing words or fixing spelling errors.</p>
<h3>What screen-readers don't announce</h3>
<h4>Styling</h4>
<p>Screen-readers do not generally announce formatting. For example, if some content is using a larger font size than other content, this is not conveyed to the user. Some screen-readers can provide some styling information to the user, but the user needs to request this specifically each time and would need a reason to.</p>
<p>This is why using the correct semantic HTML elements and using the correct heading hierarchy is important. If we just made the text <strong>look</strong> like a heading by making it larger this information does not make it to the user (and <a href="/posts/microsoft_homepage/">it's so Microsoft circa 2006</a>).</p>
<pre class="language-html"><code class="language-html">
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>heading-xl<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Heading<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span> /* do not do this */

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h2</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>heading-xl<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Heading<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h2</span><span class="token punctuation">></span></span> /* do this instead */

</code></pre>
<p>This obviously also means screen-readers do not pick up on colours, so where colour is used to convey information it needs to be supported by some sort of text labelling.</p>
<h4>Some formatting elements</h4>
<p>Formatting such as <strong>bold</strong> or <em>italics</em> is <a href="https://www.tpgi.com/screen-readers-support-for-text-level-html-semantics/">not announced by default by screen-readers</a>. Whilst users can enable this in some screen-readers, as it is not on by default it is not something we can expect to be available. This means that we should be careful that content which uses this type of formatting should not be reliant on it to highlight content. That is not to say we should not use it as visual readers will find it beneficial.</p>
<h2 id="form-content">Form content</h2>
<p>An accessible form makes entering the correct data as easy as possible for the user. We want the user to understand exactly what they need to enter and avoid having to revisit the data due to errors.</p>
<h3>Clear labels</h3>
<p>Make it easy for the user to understand what they are supposed to be entering in a field, or which option they should choose if using checkboxes, radios or a select input. Use a label which is succinct but explains clearly what information is required.</p>
<figure>
    <img src="/assets/images/modules/content-labels.png" data-size="implicit" alt="Before and after screenshots of Amazon's registration form. The before has more fields with labels alongside the inputs, but the label content is also longer. The after version has less inputs with the labels positioned above them. The label content in this version is also much simpler, for example ‘Your name’ instead of ‘My name is’.">
    <figcaption>Amazon redesigned their registration form and in doing so greatly simplified the labels, making them more succinct.</figcaption>
</figure>
<p>Making the desired data clear it means the user can complete the task quicker, thanks to less cognitive load, and is less likely to result in an error. For some users this can mean the difference between finishing a task and not. When an error does occur we want to make sure the user understands what went wrong and what they need to do to fix it.</p>
<h3>Placeholders</h3>
<p>Placeholders are a light grey text which sits inside a form field. They were intended as a way of indicating to the user an example. However they have always been a poor solution.</p>
<p>Mobile viewports, the user zooming the interface or increasing the font-size will all mean the placeholder runs the risk of getting cut off.</p>
<figure>
    <img src="/assets/images/modules/content-placeholder2.png" data-size="implicit" alt="Screenshot of a search field. The placeholder text reads Find a dentist by typing a postcode or. The text is cut off and sits under a geolocation button set in the field.">
    <figcaption>Placeholder copy can easily be cut off when the page is zoomed or on mobile. Here the words "or a location" are cut off and the text interferes with the geolocation button set within the field.</figcaption>
</figure>
<p>This can also cause issues when content is auto-translated into a language which results in longer wording than the original.</p>
<figure>
    <img src="/assets/images/modules/content-placeholders.png" data-size="implicit" alt="Screenshots of an input asking for a phone number. The placeholder text in the input states Please enter a UK phone number. A second screenshot shows the same input translated to French. The placeholder copy has been translated but no longer fits inside the input. The important information that it must be a UK number has been lost.">
    <figcaption>Placeholder copy can easily be cut off when content is translated.</figcaption>
</figure>
<p>As the placeholder disappears when the field receives focus, the information it provides also disappears. If this was formatting information then it means the user does not have it to reference as they type.</p>
<p>Placeholders are sometimes used as a replacement for a visual label element to save space, but this only makes the issues worse.</p>
<p>There are <a href="https://www.smashingmagazine.com/2018/06/placeholder-attribute/">other issues with placeholders too</a>. Some user interface libraries use the placeholder location for the label and then animate it to above the field. These so-called floating labels has also been <a href="https://medium.com/simple-human/floating-labels-are-a-bad-idea-82edb64220f6">shown to be an anti-pattern</a>.</p>
<h3>Hints</h3>
<p>Hints can also be used to help remove any ambiguity about how the user should answer a question.</p>
<p>Where the form field is asking for a specific format it is worth telling the user upfront, usually in the form of some text between the label and input. This can include a general format such as “10 digits” or an actual example such as “12 34 56 78 90”.</p>
<figure>
    <img src="/assets/images/modules/content-hint.png" data-size="implicit" alt="Screenshot of an input asking for a National Insurance Number. Text below the label states - It’s on your National Insurance card, benefit letter, payslip or P60. For example, ‘QQ 12 34 56 C’.">
    <figcaption>A good example in the hint can provide additional clarity. <a href="https://design-system.service.gov.uk/patterns/national-insurance-numbers/">(GOV.UK Design System)</a></figcaption>
</figure>
<p>Hints are, when coded correctly, programmatically associated with the input they relate  (typically <a href="/posts/accessible-forms/#hints">using ARIA</a>). This means that they will be read out after the label. Avoid putting anything in a hint more complex than a plain sentence as semantics are removed when using <code>aria-describedby</code>. This means a link in a hint will only be heard as plain content - the fact that it is a link will not be announced.</p>
<h3>Error messages</h3>
<p>When it comes to writing accessible forms, having well-written error content can make all the difference. Error messages should be as specific as possible - one field can have multiple error messages written for it and the relevant one shown based on what caused the error. They should also be straight to the point and avoid blaming the user.</p>
<figure>
    <img src="/assets/images/modules/content-error.png" data-size="implicit" alt="Screenshot of an input asking for an email address. The input has a malformed address entered. An error message below reads Sorry that email doesn't look right, please check it's a proper email.">
    <figcaption>Good error messages tell the user what the problem is and how to fix it.</figcaption>
</figure>
<p>Just as with hints, error messages should be <a href="/posts/accessible-forms/#errors">programmatically associated with the input</a> they relate to. And as with hints any semantics will not be announced when read out, so avoid adding links and similar to error messages.</p>
<p>It can also be useful to present an error summary at the top of the page, especially where more than one field may have an error message.</p>
<h3>Other content in forms</h3>
<p>Avoid adding any non-form content between form inputs. Effectively, from the first form element to the last there should only be content which is directly associated with the fields - that is labels, hints and error messages. These three types of content, coded correctly, should all be exposed to a screen-reader when the user lands on the input.</p>
<p>Because screen-reader users are likely to jump directly from input to input, any other content is in danger of being missed. This behaviour can also be seen on mobile devices which have a &quot;next field&quot; button on the virtual keyboard, and with screen-magnification users who use the tab key to move from field to field. In both these cases the user may skip past additional content between the fields.</p>
<figure>
    <img src="/assets/images/modules/content-form.png" data-size="implicit" alt="A diagram of a form with two form fields before a paragraph of content and two fields and the submit after the content. Arrows show the path from field to field which jumps over the content. The diagram states screen-readers can miss this content.">
    <figcaption>Screen-reader and other users often move directly from one form control to the next, so any intervening content which is not associated with one of the inputs can be missed.</figcaption>
</figure>
<h2 id="wrap-up">Wrap up</h2>
<p>Writing accessible content is complex, but by considering the users at each step we can ensure the content can be understood by as many people as possible.</p>

        ]]></content>
      </entry>
    
	
    
	
    
      
      <entry>
        <title>Testing strategies and accessibility</title>
        <link href="https://liptrot.org/posts/testing-strategies-and-accessibility/"/>
        <updated>2024-08-14T13:00:00Z</updated>
        <id>https://liptrot.org/posts/testing-strategies-and-accessibility/</id>
        <content type="html"><![CDATA[
          <h2>Contents</h2>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#why-we-test">Why we test</a></li>
<li><a href="#when-to-test">When to test</a></li>
<li><a href="#in-team-testing-responsibilities">In-team testing responsibilities</a></li>
<li><a href="#the-aim-of-testing">The aim of testing</a></li>
<li><a href="#how-to-test">How to test</a></li>
<li><a href="#wrap-up">Wrap up</a></li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>An important part of making sure a site or component is accessible is testing. Just like any other aspect of coding, mistakes can be made, regressions introduced and so on, but accessibility issues can often be overlooked. Whilst some accessibiilty issues can be obvious or caught by automated tools, many need manual testing and an understanding of the potential issues to surface them.</p>
<p>For these reasons it is important that accessibility features as part of an overall testing strategy to ensure it is not overlooked or insufficiently tested.</p>
<p>It is the responsibility for the whole team to test their own work. Whilst the test team has an important role, leaving accessibility to just one or two people on the team is a guaranteed way to end up with a flawed end product which will cost time and money to remediate.</p>
<h2 id="why-we-test">Why we test</h2>
<p>Just as with general functional testing we need to verify that our users can complete tasks with the product we are building. Accessibility testing can be seen as a super-intense version of what might be being undertaken right now.</p>
<p>Typically a test process may look like something similar to this:</p>
<ul>
<li>user interviews</li>
<li>prototypes</li>
<li>user testing</li>
<li>build with unit and automated end-to-end testing</li>
<li>browser and device testing</li>
<li>manual or exploratory testing</li>
<li>further user testing</li>
</ul>
<p>But at each of those points, unless we make a concious effort, we will end up just testing the product with people in mind who, from an accessibility point of view, are just like the team which built the product.</p>
<h3>We are not our user</h3>
<p>There are a large group of users who do not interact with the online world in the same way as the people on our teams. Users who benefit from accessibiilty testing are not a minority, <a href="/posts/introduction/#how-many-people-are-we-talking-about">they may form a significant part of our user-base</a> and so we need to take this aspect of testing seriously.</p>
<p>It is all too easy to forget the diverse range of our user base when designing and building resulting in a product which unintentionally leaves out these users by baking in these biases. Poor accessibility can mean a component or page is left difficult to use or understand at best and completely broken, or potentially even make the user ill at worst.</p>
<p>By creating testing processes and strategies which ensure we consider and include all types of users we can start to approach a product built for all, instead of for a narrow section of the population.</p>
<h3>The added complexity of assistive technology</h3>
<p>With accessistive technology in particular, there are a lot of variables at work. This means even coding to a published specification might introduce issues.</p>
<p>If we take screen-readers as an example, here are some of the factors which can influence the viability of a solution:</p>
<ul>
<li>different screen-readers (and versions within the same screen-reader) might support different aspects of the specification, or not support it at all</li>
<li>different browsers might interact with the same screen-reader in different ways</li>
<li>even with the same screen-reader on the same browser, there are different navigation methods a user may employ which can introduce variations in support</li>
<li>regression issues from browsers or screen-readers themselves</li>
<li>different screen-readers may add their own heuristics to make interactions more usable, but which adds in further variations in how code may be interpreted</li>
</ul>
<p>Add into this complexity, the fact that accessibility is always a balancing act between the needs of different users. Enhancing the accessibility for one group may adversley impact the accessibility of another, so testing helps expose this too.</p>
<p>This might seem like a lot to consider, but by putting in place some robust testing policies we should be able to affirm the products we build are as accessible as possible.</p>
<h2 id="when-to-test">When to test</h2>
<p>Testing should be a continuous procedure and something which is handled by the team doing the design and build work.  Accessibility testing needs to be considered as soon as an idea for a component or feature is raised.</p>
<p>Whenever possible testing should include real users with a variety of disabilities and conditions. However realistically most of the testing will be done by team members with occasional valuable insight from users.</p>
<h3>Why not leave it to a pre-launch audit?</h3>
<p>A “strategy” I have often seen is for a product team to only start looking at accessibility a few weeks before launch, normally because there is a requirement for some sort of sign-off of the product for accessibility legislation or company policy. This can mean the actual accessibility testing work ends up with the team doing the accessibility review rather than with the product team. This approach will always lead to either missed deadlines or products launching with multiple accessibility barriers, which will most likely then languish in the backlog.</p>
<p>This approach also means the product team will never upskill in accessibility as it will always be deferred to another team. The product team will likely make fixes in a rush to meet the launch deadline and so not truly understand what they are doing and why it matters. This is doing the team a disservice.</p>
<p>We should see accessibility issues in a similar way as technical debt in the way the issues increase in quantity the longer the project goes on. Even with the best intentions a team will generate accessibility issues in the code they produce. As time goes on these issues begin to overlap, perhaps becoming more complex, and are copied into new code deepening the accessibility debt. What might have been a simple fix if found at the time of writing may result in a product-wide bug hunt when left.</p>
<p>The increased time it takes to retrospectively fix accessibility issues means that <a href="https://yatil.net/blog/the-infuriating-inefficiency-of-accessibility-audits#the-cost-of-fixing-accessibility-bugs">it can cost up to 30 times as much</a> compared to catching that issue at the point it was created.</p>
<p>But these issues may not be limited to only the code. By far the most difficult issues to fix are ones which are fundamental to either how the wider page or journey is designed. By the time we get close to product launch finding out you need to redesign whole pages or components or even whole journeys can be devastating to a deadline and team morale. Typically the product gets released with major accessibility flaws which then persist as new features take priority. This is often related to <a href="/posts/prioritising-accessibility/#the-mvp-paradox">the MVP paradox</a>.</p>
<p>A pre-launch review can only be used as part of a wider accessibility testing strategy. By itself it is unlikely to achieve the desired outcome as it sits too close to the launch date and is rarely able to prevent a launch if it finds issues.</p>
<h3>Design system and coding libraries</h3>
<p>Ideally a project will be using a pre-existing design system which has already has been robustly tested. A design system should indicate where accessibility has been understaken, how and which assistive technology was used (including version numbers of that technology and browsers). Without this information it is unwise to assume the testing has been done and is being kept up-to-date so we need to include additional testing in our build.</p>
<p>If evidence of testing is present, then it is a responsiblity of each team to both keep their project up-to-date with the latest releases and have a maintenance plan for this going forward. If any issues are surfaced with library components or pattern library components are surfaced during testing, this should be raised with the appropriate team to assist them in keeping the libraries as accessible as possible.</p>
<figure>
    <img src="/assets/images/modules/audit-library.png" data-size="implicit" alt="Screenshot of documentation asking for feedback on a component. There are options to take part in a discussion, propose a change or take part in a usage survey.">
    <figcaption>The GOV.UK Design System offers teams a variety of ways to give feedback on components they publish.</figcaption>
</figure>
<h3>Discovery stage</h3>
<p>Testing of assumptions and hypotheses is normally done with users in the discovery phase, but this too should involve a diverse range of users with disabilities and different conditions. This can be especially valuable if there is an existing system which is being replaced or similar services already exist which they are able to give insight to.</p>
<h3>Design and prototype stage</h3>
<p>A prototype, whether that is in something like Figma or actually working in HTML, is the best place to get detailed feedback on potential accessibilty pitfalls in a design.</p>
<p>Any kind of high fidelity prototype will allow you to spot issues with content, layout, colours, and page and journey flow. Components which have different states (such as focus styles on buttons) can also be included and checked.</p>
<p>Catching issues in components, page layout or journeys at this point will greatly reduce cost and time spent versus ironing these out after they have made into code.</p>
<p>If using flat prototypes, go the extra distance in the mockup to annotate the different states, how focus moves through the page and semantic markup. This will save time later as developers will not have to surface these questions when they come to build it.</p>
<p>When building an HTML prototype, you can use browser tools to help you check for simple accessibility issues. Some of the most popular ones are:</p>
<ul>
<li><a href="https://www.deque.com/axe/">axe</a></li>
<li><a href="https://wave.webaim.org/extension/">Wave</a></li>
<li><a href="https://www.tpgi.com/arc-platform/arc-toolkit/">ARC Toolkit</a></li>
</ul>
<p>An HTML prototype will also be able to be easily tested with screen-magnification users. A <em>well-coded</em> HTML prototype will also allow you to see how a design scales and even how assistive technology works with it.</p>
<p>However you want to be sure the prototype has been well tested before putting it in front of assistive technology users. This is because it is possible to have a lot of minor accessiblity issues prevent the user from providing true insights into more complex problems. Some testing and remediation in advance of the user testing could remove these obstacles and make the user testing less frustrating for the user and more valuable to the team. You need to know how this will be coded for production so the effort at this point is worth it.</p>
<p>Don't consider leaving testing with disabled users until the production version launches. At that point it becomes more difficult to argue for accessibility changes and it might be that the changes needed to make it accessible require wider rework than stakeholders will be comfortable with.</p>
<h3>Build</h3>
<p>The build stage is where the most intensive testing work will take place in terms of code and getting it production-ready. Team and user testing should continue throughout the build phase.</p>
<p>Even if using a component library of previously tested code the output should be tested. This is because support landscapes shift as browsers and assistive technology release new versions, but also the context and parameters for how those components are used are often unique to the current build. As mentioned, component libraries also depend on a community effort in feeding back improvements and both in-team testing and user-testing can greatly contribute to this.</p>
<p>During build there are several other testing mechanisms which can be added to help support writing accessible code.</p>
<ul>
<li>using linting on IDE to catch issues as you code</li>
<li>adding accessibility checks into unit/component tests</li>
<li>adding automated library checks (such as axe) to build pipelines</li>
<li>adding specific scripted checks into end-to-end testing</li>
</ul>
<p>See more on <a href="/posts/automated-testing/">automated testing</a>.</p>
<h3>Maintenance</h3>
<p>After launch testing should not stop. Sites rarely stay in their launch configuration as more features, improvements and bug-fixes are added.</p>
<p>Whenever the interface code is changed the accessibility testing should be re-run, both for the new code but also taking care to include any potential side-effects elsewhere in the site.</p>
<p>Even in periods of stagnation it is advisable to factor in regular accessibility sweeps due to the release timelines of browsers and assistive technology (especially screen-readers).</p>
<h2 id="in-team-testing-responsibilities">In-team testing responsibilities</h2>
<p>As we have already explored, testing should not be the sole responsibility of one or two people in the team.</p>
<p>Let's examine the responsibilities for ensuring a new feature is accessible:</p>
<ul>
<li><strong>discovery phase:</strong> user researcher, designer, content design</li>
<li><strong>prototype phase:</strong> designer, content design, developer</li>
<li><strong>build phase:</strong> designer, content design, developer, QA</li>
<li><strong>maintenance phase:</strong> QA, developer, user researcher</li>
</ul>
<p>You can see design, content and developer are heavily involved. This is because good accessibility is often an ongoing conversation between team members due to the direct interaction you are having with the end-user. When one group makes all the decisions it can lead to an inferior product.</p>
<p>Even the project manager and business analyst need to be involved to ensure accessibility is treated as a priority and the team is given enough time to produce a quality and effective result.</p>
<p><a href="/posts/team-process-and-role-based-accessibility/">See more about team processes and responsibilities</a></p>
<h2 id="the-aim-of-testing">The aim of testing</h2>
<p>The aim of testing is to <strong>not add issues to the backlog</strong>.</p>
<p>Whilst user testing will invariably result in tickets being generated, this should ideally be limited to insights from lived experience which the team could not be expected to add themselves.</p>
<p>Testing is there for 3 reasons:</p>
<ol>
<li>help designers provide the development team with an accessible solution</li>
<li>assist the development team in creating accessible code</li>
<li>providing regression assurance</li>
</ol>
<p>With user testing and interviews in advance of code being written, the aim is to have a design which is generally accessible before any of it is coded.</p>
<p>Complex components which have the potential for accessibility issues should be tested in isolation using HTML prototypes before being signed off for development.</p>
<p>Code should be robustly tested <em>as it is developed</em>, so that inaccessible code is not merged and certainly not released.</p>
<p>The combination of</p>
<ul>
<li>an accessible design solution which has been tested with users</li>
<li>Test-Driven-Development (using tests which enforce accessible best practices)</li>
<li>code linting</li>
<li>developers running checks (including manual assistive technology tests) before committing code</li>
<li>pull request reviews which look at accessibility</li>
</ul>
<p>should result in fairly robust code and minimal need for rework.</p>
<p>By testing before merging code it reduces the number of resultant bugs which then need to be prioritised and fixed. By fixing issues before they are merged we avoid accessibility being de-prioritised on the backlog.</p>
<p>Finally pipeline testing provides assurance that we haven't missed any side effects.</p>
<h2 id="how-to-test">How to test</h2>
<p>Testing for accessibility can be broken down into three main areas:</p>
<ul>
<li>automated tests</li>
<li>non-assistive technology tests</li>
<li>assistive technology tests</li>
</ul>
<h3>Automated testing</h3>
<p>Automated testing is done most often in the browser on either a local branch or on the live site, but can also be done as part of a build process.</p>
<p>Note that whilst automated testing is easy to do, it will only find 30-40% of accessibility issues out-of-the-box. Even custom test scripts written specifically to target accessibility cannot account for everything, so manual testing is still essential.</p>
<p>When done in the browser automated testing will use one of the many available browser plugins. This will provide you with a list of potential issues on the current page only and <strong>only in the state the page was in when the test was run</strong>. Different plugins will run different tests so it can be useful to run a couple of different ones from time-to-time, but find a plugin which you like to work with and use that.</p>
<p>The advantage of doing it locally does mean you have a clearer view on what is happening on the page, but also that you can test code before committing it.</p>
<p>When done as part of a build process it will normally be using an API from one of the browser plugins. The advantage of this is that it can piggyback on your end-to-end journey tests and check each page in turn, providing a report at the end.</p>
<p><a href="/posts/automated-testing/">See more about automated testing</a></p>
<h3>Non-assistive technology testing</h3>
<p>We can do a lot of accessibility testing even without learning how to use a screen-reader or other assistive technology.</p>
<p>You can check for a lot of accessibility problems by just using your standard keyboard. If you also learn how to use your browser developer tools and a couple of (non-automated) browser plugins, you can then cover a lot more potential issues too.</p>
<p>See more about <a href="/posts/keyboard-accessibility/">keyboard testing</a>.</p>
<h3>Assistive technology testing</h3>
<p>This is the part where a lot of people stop because they think using a screen-reader is really difficult and it costs money to buy any assistive technology.</p>
<p>But screen-readers are genuinely simple to use as you only need a few commands to get started. Speech-recognition is even easier and again only a handul of verbal commands will get you by.</p>
<p>The only tricky part might be understanding <strong>why</strong> there is an issue when you come across one and <strong>how</strong> to fix it.</p>
<p>Each OS also has a screen-reader and speech-recognition which ships with it or is installable for free, so chances are you already have the tools to get started.</p>
<p><a href="/guides/">Learn how to use screen-readers.</a></p>
<h3>What a test strategy should include</h3>
<p>A robust testing strategy should include the following:</p>
<ul>
<li><a href="/posts/automated-testing/">automated testing</a></li>
<li><a href="/posts/keyboard-accessibility/">keyboard testing</a> on mobile and desktop</li>
<li>visual checks - including reflow, zoom, font-size, high contrast, reduced motion</li>
<li>screen-readers</li>
<li>speech-recognition</li>
<li><a href="/posts/accessible-content/">content</a></li>
</ul>
<p>You could expand this to include:</p>
<ul>
<li>text-to-speech (which reads the visible text only)</li>
<li>user style overrides (how easy or difficult it is for a user to customise the look of your product to their needs)</li>
<li>performance (how the product works with lower-powered devices on slower networks as disabled users are less likely to have disposable income for top-of-the-line or dedicated internet devices)</li>
</ul>
<h2>Accessibility audits</h2>
<p>Accessibility testing should be done all through development of a site and when doing that you should follow the steps outlined above.</p>
<p>But it might be that you will need to perform a wider accessibility review. This could be because you have inherited a project and want to gauge how accessible it is before you start working with it, or you might be doing a full review of a site you have just built as an assurance step. This kind of in-depth review is often referred to as an accessibility audit. These are often carried out by specialists but there is no reason for a development team to not do this themselves.</p>
<h3>Deciding what to review</h3>
<p>How an audit is run depends on the type of site:</p>
<ul>
<li>a large freely-explorable website might benefit from a sampling technique, perhaps concentrating on large-traffic areas</li>
<li>if components can be identified, these can be targeted along with some more general full-page sample testing</li>
<li>a transactional site or one which has well-defined user journeys can have the journeys mapped out and each step tested as full pages</li>
</ul>
<p>It is important that whatever technique is used is recorded so it can be repeated. This is essential both for the development team to be able to replicate the issue and for the tester to be able to verify any fixes (which may be some time after the original report).</p>
<p>Whilst the product itself may be the focus of the review, it is worthwhile looking at the wider landscape too. Ask the following questions:</p>
<ul>
<li>how do users find the product - if social media is used are the posts accessible?</li>
<li>what are their entry points - are people signposted from other parts of the company digital estate?</li>
<li>how do they get in touch if they have a question or need help - are there options for all users?</li>
<li>does the product generate artifacts such as emails or letters - are these accessible?</li>
</ul>
<h3>Testing for compliance vs testing for user impact</h3>
<p>It can be tempting to take a list of the WCAG criteria and review each page or component for failures against each item. However WCAG has well-known areas where it does not meet the needs of all users, especially in areas such as cognitive function. By only reviewing a site against WCAG issues, many impactful problems may be left unreported. Remember WCAG guidelines are just a way to ensure you have done the bare minimum to make a site accessible - we should be going beyond this.</p>
<p>Whilst a WCAG checklist can be a useful tool, it should not be the only method of assessment used as it can be easy to miss issues.</p>
<p>Here are some sample checklists - note that none of these have been updated to the current version of WCAG.</p>
<ul>
<li><a href="https://www.magentaa11y.com/">Accessibility checklist - MagentaA11y</a></li>
<li><a href="https://www.a11yproject.com/checklist/">Checklist - The A11Y Project</a></li>
</ul>
<h3>How to report an issue</h3>
<p>First, make sure that you have actually found an issue. Especially if it concerns assistive technology (like a screen-reader), make sure you haven't made an error in testing (like using the wrong key combo or being in a different navigation mode).</p>
<p>Then check to see if there is a bug which is causing the issue. It might be that making a reduced example of the component causing an issue might help work out if it is an issue with the browser or assistive technology rather than the component. If it turns out to be a bug with the browser or assistive technology, look to add to or create a bug report on the relevant issue tracker so it can be fixed.</p>
<p>It is important as much information as possible about the issue is recorded in order for someone with no context of the location or issue to be able to understand and replicate the finding.</p>
<p>If you have determined it is a problem with the component then you will need to raise an issue for the team to look at it. This is my <a href="/demos/an-audit-template/">accessibility audit issue reporting template</a> which helps produce a detailed issue.</p>
<h3>Severity vs priority</h3>
<p>Severity and priority might not always coincide. The severity of an issue is how much of a barrier it causes for the user.</p>
<p>However how this is then prioritised depends on what this barrier is preventing - for example is it a core journey step or a minor feature?</p>
<p>It can also be very tempting to find an issue and then try and make one of the WCAG Success Criteria fit in some convoluted way to ensure it gets fixed. This is often a result of the stakeholders refusal to fix anything not identified as a WCAG failure. Don’t do this.</p>
<p>You should always be able to defend your assignment of an issue against a WCAG criterion, citing the guidance when asked to. Always assume the person you are reporting issues to has a good grasp of the WCAG guidelines and will call you out on any misrepresentation. To do otherwise risks all of your issue reporting being brought into question.</p>
<p>If you find an issue which is a borderline WCAG issue, but you can’t make it stick, then report it as a high-priority ‘other’ issue and flag your concerns in the issue itself. A good prioritisation process will ensure issues are reviewed in accordance with user impact.</p>
<p>Reocurrence is also a factor in prioritising. A lower severity issue which is happening on every single page can form more of a barrier than a single more severe issue which only happens in one place. This is because a repeated barrier can be exhausting to have to by-pass on every page and the resulting compound effect can be higher than the single issue.</p>
<p><a href="/posts/prioritising-accessibility/">Read more about prioritising accessibility.</a></p>
<h2 id="wrap-up">Wrap up</h2>
<p>Testing for accessibility is a complex thing. It covers a lot of things which cannot be automated which itself can be present a barrier to implementing a robust testing strategy. But with a series of testing processes in place, across all team roles issues can be addressed long before they become problems for users.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Keyboard accessibility</title>
        <link href="https://liptrot.org/posts/keyboard-accessibility/"/>
        <updated>2024-07-25T13:00:00Z</updated>
        <id>https://liptrot.org/posts/keyboard-accessibility/</id>
        <content type="html"><![CDATA[
          <h2>Contents</h2>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#why-test-for-keyboards">Why test for keyboards?</a></li>
<li><a href="#can-we-automate-keyboard-testing">Can we automate keyboard testing?</a></li>
<li><a href="#set-up-for-testing-on-macs">Set-up for testing on Macs</a></li>
<li><a href="#what-are-we-testing">What are we testing?</a></li>
<li><a href="#a-quick-look-at-navigating-by-keyboard">A quick look at navigating by keyboard</a></li>
<li><a href="#tools">Tools</a></li>
<li><a href="#skip-links">Skip links</a></li>
<li><a href="#can-i-see-where-my-focus-is">Can I see where my focus is?</a></li>
<li><a href="#functionality">Functionality</a></li>
<li><a href="#logical-tab-order">Logical tab order</a></li>
<li><a href="#preventing-doubling-up">Preventing doubling up</a></li>
<li><a href="#managing-focus-when-content-updates">Managing focus when content updates</a></li>
<li><a href="#did-we-wcag">Did we WCAG?</a></li>
<li><a href="#wrap-up">Wrap-up</a></li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>There are many types of users for whom the keyboard is the only way they can access their computer. It also forms the basis for how other users, such as screen-reader and speech-recognition users interact.</p>
<p>Keyboard accessibility is both fundamental to wider accessibility and one of the easiest things to test when it comes to accessibility. Because most developers will primarily use a mouse when interacting with the end product they are coding it can be all too easy to make some simple errors which have a major impact on our end users.</p>
<p>By being aware of how excluding keyboard users can happen we can improve our code and testing practices.</p>
<p>Whilst this is a simple check to do, it actually covers several WCAG criteria because is such a core accessibility concern.</p>
<h2 id="why-test-for-keyboards">Why test for keyboards?</h2>
<p>7% of working-age adults have a severe dexterity difficulty or impairment (<a href="https://www.microsoft.com/en-us/download/details.aspx?id=18446">​Microsoft / Forrester report​</a>). In the UK of those who reported an impairment <a href="https://design.education.gov.uk/tools/how-many-users/1000">around 25% had a condition which impacted their dexterity</a>. This can result in users prefering keyboard interaction over mouse or touch as it may be less prone to error, more easy physically or less painful.</p>
<figure>
<img src="/assets/images/modules/keyboard-wand.png" data-size="implicit" alt="A woman sits at a desk. She uses a stick held in her mouth to press keys on a vertical keyboard in front of her. A screen sits to one side of the keyboard." />
<figcaption>A mouth-wand allows users with limb paralysis use a specially adapted keyboard to navigate and enter data.</figcaption>
</figure>
<p>Some users will be physically unable to use a mouse and so will need to use a keyboard to navigate your product.</p>
<figure>
<img src="/assets/images/modules/keyboard-mag.png" data-size="implicit" alt="A small keyboard has sunken keys. A hand holds a pointer with an angled end over one of the holes." />
<figcaption>This small keyboard has a magnetised pointer and sunken keys to assist users who have severe pain when they move their hand any distance. The magnet, sunken keys and small form factor mean movement is kept to a minimum.</figcaption>
</figure>
<p>Alongside dexterity or mobility impairments, the majority of screen-reader users will also use a keyboard. So by testing for keyboard accessibility we are already making headway into more complex accessibility testing requirements.</p>
<h2 id="can-we-automate-keyboard-testing">Can we automate keyboard testing?</h2>
<p>Out-of-the-box automated testing (such as Wave or axe) will only tell you if something is:​</p>
<ul>
<li>focusable and should not be​</li>
<li>focusable and is missing an accessible name​</li>
</ul>
<p>Some automated tools also provide options to visualise focus order (more on that shortly).</p>
<p>But we need to test much more than that.​</p>
<p>Automated tests are effectively linters. ​They catch the simpler issues (although they can be super-useful).​</p>
<p>You would not ship code with the only testing being a linter. In fact with most of the examples we'll be looking at, automated browser plugins did not pick up the issues we will be fixing.</p>
<p>But all is not lost! We can add some checks to our custom scripted tests to help enforce better accessibility at build time. <a href="/posts/automated-testing/#enhancing-automated-tests">Read more about improving tests for accessibility.</a></p>
<h2 id="set-up-for-testing-on-macs">Set-up for testing on Macs</h2>
<p>If you are a Mac user, tabbing to navigate links and form controls in a webpage may be turned off by default. This affects Firefox and Safari. You should check your settings if you are on Mac and using either of these browsers.</p>
<details>
    <summary>How to enable tab navigation on Mac</summary>
    <div id="enable-tab-mac">
<h3>Firefox</h3>
<p>To fix Firefox you need to go make a change in the Mac system settings.</p>
<p>Before OS 13 it is in <code>System Preferences &gt; Keyboard &gt; Shortcuts</code> and check “Use keyboard navigation to move focus between controls”.</p>
<p>For OS 13 on it is in <code>System Preferences &gt; Keyboard</code> and toggle on “Keyboard navigation”.</p>
<img src="/assets/images/posts/mac-keyboard.png" alt="Mac OS Ventura keyboard settings showing the location of the tab navigation option" />
<h3>Safari</h3>
<p>For Safari you need to make a change to Safari's own settings. In <code>Safari &gt; Settings &gt; Advanced</code>, check the option “press Tab to highlight each item on a web page”.</p>
<img src="/assets/images/posts/safari-keyboard.png" alt="Safari settings showing the location of the tab navigation option" />
<p></div></p>
</details>
<h2 id="what-are-we-testing">What are we testing?</h2>
<p>There are a number of things we are going to be looking for during our testing:</p>
<ul>
<li><strong>skip links</strong> - adding these allow keyboard users to jump past the repeated blocks which are present on every page, such as navigation</li>
<li><strong>visible focus</strong> - while we are navigating can we tell exactly where our focus is at any moment - that is to say if we hit the enter key do we know what would happen?</li>
<li><strong>access and operation</strong> - can we get to and then trigger the various controls on the page? Are there things we can reach which we should not be able to?</li>
<li><strong>focus management</strong> - when something is added or removed as a result of user action, are we handling the focus in an appropriate manner so they can continue without interruption?</li>
<li><strong>focus order</strong> - is the order in which focus happens logical based on the position of the elements or are we jumping all over the screen?</li>
</ul>
<h3>Check different states</h3>
<p>Also remember we need to test any different view states. These can be:</p>
<ul>
<li>menus which appear when a button is clicked</li>
<li>dialogs or notifications</li>
<li>different types of content loaded into the same component</li>
</ul>
<h3>Check mobile viewports</h3>
<p>We also need to check the mobile viewport of any page. Sometimes developers assume that a mobile user will be using a pointer (such as a finger or stylus), but external keyboards are a popular addition to mobiles or tablets.</p>
<img src="/assets/images/modules/keyboard-mobile.png" data-size="implicit" alt="An external keyboard being used with a mobile device.">
<p>A desktop browser can also trigger the mobile viewport when zoomed. It is important to also check that any interactions, especially menu and navigation related, are still operable with a keyboard.</p>
<figure>
<img src="/assets/images/modules/keyboard-zoom.png" data-size="implicit" alt="The CNN website showing the mobile layout on a large resolution desktop monitor.">
<figcaption>
This website has triggered the mobile view on a large desktop monitor as the browser page zoom has been used to increase the size of the page by 400%;
</figcaption>
</figure>
<p>Whilst looking at mobile viewports, also check how the page operates in landscape mode. This is often when you may find that a sticky header will overlay content preventing a user from seeing where their focus is.</p>
<h4>Testing on mobile devices</h4>
<p>Whether testing a native app or a website with a keyboard on iOS you will need to turn on “full keyboard access” under Accessibility in Settings. This will allow you to tab through as you might on a laptop.</p>
<p>On iOS you also have the option of using “keyboard gestures” by using the <kbd>Tab + G</kbd> command. This then allows you to make swipe gestures. However bear in mind that not all users will be aware of this and Android phone users (nor laptop users) do not have this option. It is always best to provide keyboard users with buttons to accomplish what other users may do with gestures.</p>
<h2 id="a-quick-look-at-navigating-by-keyboard">A quick look at navigating by keyboard</h2>
<p>When we are using our keyboard, we only want to navigate to things which are interactive. The main way of doing this is by using the <kbd>tab</kbd> key. This will place a focus indicator on the element to show us where our focus is and this indicator will move as you navigate between interactive elements. You can use <kbd>enter</kbd> or <kbd>space</kbd> to activate buttons and <kbd>enter</kbd> to activate links once your focus is on them.</p>
<p>A mistake that some people make when it comes to testing for keyboard use is that they assume that the tab key is all that is used. Some components might require <kbd>arrow</kbd> keys to be used to move around elements within them.</p>
<p>Radio button groups for example show focus on <kbd>tab</kbd> (either on the first or last depending on your direction of navigation) and then you can use <kbd>space</kbd> to select that radio or use <kbd>arrow</kbd> keys to move up and down the list. This behaviour means that long lists of options can be easily skipped over once we have made our choice.</p>
<p>Some library components such as a <a href="https://design-system.service.gov.uk/components/tabs/">tab component</a> may have what is called a <em>roving focus</em> (or <em>roving tabindex</em>) which operates in a similar way to radio buttons - you focus onto the first tab element and then use arrow keys to move from tab element to tab element.</p>
<img src="/assets/images/modules/keyboard-tabs.png" data-size="implicit" alt="Screenshot of a tab component with 4 tabs. The open tab panel shows a link among other content. Notes show how using a tab key will take the user from the current tab to the link in the tab panel, and how when on the active tab using arrow keys will move focus and select the adjacent tab." />
<p>This allows the user to avoid having to navigate through all the tabs of the component to get past it. However this also relies on the user being aware of this pattern so this should be used sparingly, else the user may be confused as to why they cannot tab to an element.</p>
<p>Remember that a user will not need to focus on content to scroll the page - this can be done with other keys (space bar, arrow keys or page up/down keys).</p>
<h2 id="tools">Tools</h2>
<p>Testing for keyboards can raise some difficulties for us just as it might for a user.</p>
<h3>Enhancing focus indicators</h3>
<p>Sometimes the page we are checking may have poor focus indicators which make it difficult to work out where our focus is.</p>
<p>One way around this is to enhance the focus indicators with some css. Usually something like this should be enough:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">*:focus</span> <span class="token punctuation">{</span>
    <span class="token property">outline</span><span class="token punctuation">:</span> 2px solid hotpink<span class="token important">!important</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre>
<p>This will add a pink outline to each focusable element as you move to it.</p>
<div class="note note--insight">
<p>I added this functionality into the <a href="/pattern-checker/">Pattern Checker</a> browser plugin to make it easy to check:</p>
<figure>
<img src="/assets/images/modules/focus-highlight.png" alt="A product page with a review score highlighted by a pink outline. Above it is a panel from the Pattern Checker plugin with settings to show or hide the outline." />
<figcaption>
On this product page the review score had no focus indicator. By using the Pattern Checker plugin we can more easily see that the review score is part of the tab order as we move through the page.</figcaption>
</figure>
</div>
<h3>Viewing the focus order</h3>
<p>Sometimes it can be valuable to be able to see each focusable item on the page or to plot where focus is moving. This is especially true when trying to report an issue. Fortunately there are some browser tools which can help us here.</p>
<p>I'm going to look at 3 tools which show the order in which focus is applied to elements on the page.</p>
<p>All these tools plot focus by adding a numbered tag next to the element to represent the order in which they will be accessed by the user. Some also draw lines to assist you in seeing where the next numbered tag is located.</p>
<figure>
    <img src="/assets/images/modules/focus-plot.png" alt="A page with various buttons and links. An overlay has plotted numbers against each with lines connecting each with the next." data-size="implicit">
    <figcaption>Seeing the focus placement and order can be a valuable test tool. We will use these tools later.</figcaption>
</figure>
<p>However what they see as a focusable element is slightly different.</p>
<p>Firefox's built in &quot;Show tabbing order&quot; in the accessibility panel shows tab stops. These are just the items which are reached by the tab key.</p>
<p>IBM's Accessibility Assessment plugin shows all focusable items. This includes tab stops, but also items which can take focus in other ways.</p>
<p>Microsoft's Accessibility Insights works slightly differently. It doesn't show all the focusable items in one go. Instead it plots the items as you move through the page. Depending on how you navigate will determine how it plots.</p>
<p>The video below shows each of these in action.</p>
<figure>
<video preload="metadata" src="/assets/images/modules/focus-stops.mp4" controls="show"></video>
    <figcaption>Radio button groups are a good way to illustrate how different tools respond. Only the first radio button recieves focus via tabbing. Once in the radio group other radio buttons are accessed using arrow keys.
        <details>
            <summary>Video description</summary>
            <div>
                <p>A page is shown in Firefox with two radio buttons in a group, below which are a link and a button.</p>
                <p>The context menu is brought up and “Inspect Accessibility Properties“ selected. Developer tools opens with the accessibility panel shown.</p>
                <p>At the top of the panel is a checkbox for <strong>“Show tabbing order“</strong> which is then checked and numbered icons appear next to items on the page.</p>
                <p>The icons are numbered next to the following items in this order:</p>
                <ol>
                    <li>The first radio button</li>
                    <li>The link</li>
                    <li>The button</li>
                </ol>
                <p>Firefox is dismissed to show the same page in Chrome.</p>
                <p>Developer tools is opened and the <strong>IBM Accessibility Assessment</strong> panel is selected.</p>
                <p>There is a “Scan“ button in the panel which is clicked, generating a report. This allows the “Keyboard checker mode” to then be clicked.</p>
                <p>Numbered icons with connecting lines appear next to items on the page.</p>
                <p>The icons are numbered next to the following items in this order:</p>
                <ol>
                    <li>The first radio button</li>
                    <li>The second radio button</li>
                    <li>The link</li>
                    <li>The button</li>
                </ol>
                <p>The developer tools is closed and the <strong>MS Accessibility Insights</strong> extension icon is clicked in the toolbar.</p>
                <p>From the extension popup the “Tab stops” option is selected and the popup closes.</p>
                <p>Focus indicators show the elements on the page as the user moves between them. As the focus moves, numbered icons appear next to items on the page with lines connecting each icon to the next.</p>
                <p>The icons are numbered next to the following items in this order:</p>
                <ol>
                    <li>The first radio button</li>
                    <li>The link</li>
                    <li>The button</li>
                </ol>
                <p>The page is reloaded and the MS Accessibility Insights extension rerun and the “Tab stops” option selected again.</p>
                <p>This time the focus does not move from the first radio to the link, instead moving from the first radio to the second.</p>
                <p>As the focus moves, numbered icons appear next to items on the page with lines connecting each icon to the next.</p>
                <p>The icons are numbered next to the following items in this order:</p>
                <ol>
                    <li>The first radio button</li>
                    <li>The second radio button</li>
                    <li>The link</li>
                    <li>The button</li>
                </ol>
            </div>
        </details>
    </figcaption>
</figure>
<p>It is strongly advisable that these tools are only used to support manual testing and not as a replacement. Also remember that these tools, just like other automated browser plugins only work on the current state of the page.</p>
<h2 id="skip-links">Skip links</h2>
<p>These are primarily for keyboard users so are a good place to start.</p>
<h3>The benefit of a skip link</h3>
<p>A lot of sites will employ these but you may not have seen them as they are generally hidden until they recieve focus to avoid making the top of the page cluttered.</p>
<p>A skip link should be the first focusable element on a page, even before the navigation or logo. This is because their function is to allow a keyboard user to jump over the repeated header elements (which tend to be link-heavy with navigation) and allow them to more easily get to the unique content on each page.</p>
<p>If we didn't provide a skip link like this on each page a keyboard user would have to tab perhaps a dozen or more times when they land on each page in order to access the main content links. Remember that keyboard users may have difficulty in activating a key, so asking them to repeatedly do so when we can remove this need is not acceptable.</p>
<h3>How skip links should work</h3>
<p>The skip link is an in-page link and will typically take the user to the <code>main</code> element (usually done by temporaily assigning a <code>tabindex=&quot;-1&quot;</code> to allow it to be programmatically focused). The next use of the tab key will take the user to the first focusable item within or after the <code>main</code> element. Some sites may take the user directly to the first focusable item which is acceptable also.</p>
<figure>
    <img src="/assets/images/modules/key-skip.png" alt="A skip link on the Mercedes UK homepage with arrows showing how the user is taken beyond the 9 navigation links." />
    <figcaption>The Mercedes UK website uses a skip link to take the user to the <code>main</code> element. The next use of the tab key will take the user to the first link inside.</figcaption>
</figure>
<h3>Potential mishaps</h3>
<p>Despite being a simple interaction there is scope for issues with skip links, partly because their default state is to be hidden visually so they can be forgotten about when testing.</p>
<h4>Skip link text</h4>
<p>Because skip links are hidden it is easy for issues with their content to be missed. Check the content makes sense and if offering translations of a page that the skip link translates correctly.</p>
<figure>
    <img src="/assets/images/modules/key-skip-content.png" alt="A skip link on the Mercedes UK homepage with the text Skip to main content Main Navigation: Text label for skip to content button" />
    <figcaption>Here the Mercedes UK skip link has not loaded its content correctly.</figcaption>
</figure>
<h4>Skip link appearance</h4>
<p>We should check that the skip link is actually shown when it gets focus and sits above other content.</p>
<figure>
    <img src="/assets/images/modules/key-skip-bad.png" alt="A skip link on the Ryan Air homepage. The skip link has not become fully visible on focus and is only visible as a horizontal line at the top of the page." />
    <img src="/assets/images/modules/key-skip-bad-fix.png" alt="The Ryan Air skip link as it should look - a yellow button at the top of the screen has focus. The button text is Skip to main content." />
    <figcaption>The Ryan Air homepage skip link has an issue with its styling (a css z-index problem) causing it to be only partially visible. The second image shows how it should look.</figcaption>
</figure>
<h4>Skip link functionality</h4>
<p>Our final check is to make sure that when clicked, the link actually takes the user down the page and focus is moved there.</p>
<p>It might be that the target of the link is missing or has been mis-spelled.</p>
<figure>
    <video preload="metadata" src="/assets/images/modules/skip-links-olympics-sml.mov" controls="show"></video>
    <figcaption>The 2024 Olympics website had a bug where the skip links (there were several) scrolled the page but did not set focus. This meant the skip links were making the situation worse as they just added more tab stops for the user to navigate.
    <details><summary>Video description</summary><div>
        <p>The 2024 Olympics homepage. A "skip to main content" link appears top left.</p>
        <p>The link is clicked and the page scrolls.</p>
        <p>Another skip link appears replacing the first. This one is labelled "Skip to language selection".</p>
        <p>The same happens - the page scrolls but focus does not move from the link.</p>
        <p>Three more skip links appear one after the other as focus moves to each in turn, each with the same effect.</p>
        <p>The focus now moves to the primary navigation links.</p>
    </div></details>
    </figcaption>
</figure>
<h2 id="can-i-see-where-my-focus-is">Can I see where my focus is?</h2>
<p>Keyboard use relies heavily on being able to see where the focus currently is. If this is taken away by css or obscured (or just not added) it can make it very difficult to work out where you are on the page. Making focus states really obvious helps especially when focus can jump across large sections of the page.</p>
<p>As a quick test, go to the page in question and close your eyes. Hit the tab key several times. Can you see immediately where the focus is? If not then the focus indicators need some work.</p>
<h3>Providing good focus indicators</h3>
<p>Not having a focus indicator is like not having a mouse pointer for a mouse-user. It makes it a lottery as to what you will trigger when you click. Good focus indicators make interfaces immesurably more pleasant and less tiring to use.​</p>
<p>A good focus indicator makes it immediately clear that the item has focus. Remember that some keyboard users may also have poor eyesight.</p>
<p>Here is a video of a user navigating a site which has poor focus indicators - the user is pressing the tab key throughout the video. The focus is very difficult to see as it only appears on a few links and not at all on the primary navigation. (Note there are other issues apparant in the video which we will come to shortly.)</p>
<figure>
    <video preload="metadata" src="/assets/images/modules/focus-indicator-bad-sml.mov" controls="show"></video>
    <figcaption>
        <p>The Thomas Cook site has poor focus indicators. Navigating with keyboard many links have no indicators at all and a few have just thin dotted outlines.</p>
    </figcaption>
</figure>
<p>Now let's look at that again, but this time we add some good focus indicators (done using the <a href="/pattern-checker/">Pattern Checker plugin</a>). The focus is now immediately visible as the user tabs through the links.</p>
<figure>
    <video preload="metadata" src="/assets/images/modules/focus-indicator-show-sml.mov" controls="show"></video>
    <figcaption>
        <p>This video shows the same but with forced focus highlights.</p>
    </figcaption>
</figure>
<p>If you can't see where the focus went on a page then you need to check if this is just down to a poor focus state or because the focus has gone to content which has been hidden from view. Disappearing focus indicators is something you will often find when content has been hidden off-screen until triggered (like a menu) - we will look at this in a moment.</p>
<h3>Potential mishaps</h3>
<h4>Visual appearance</h4>
<p>The most obvious issue with focus indicators is their lack of visibility. As we have already mentioned a good focus indicator is very clearly different from the non-focused state.</p>
<figure>
    <img data-size="implicit" src="/assets/images/modules/key-focus-bad.png" alt="A green button with white text and the word unfocused above alongside an idential one with the word focused above" />
    <img data-size="implicit" src="/assets/images/modules/key-focus-poor.png" alt="A green button with white text and the word unfocused above alongside an identical one with a faint dotted outline and the word focused above" />
    <img data-size="implicit" src="/assets/images/modules/key-focus-good.png" alt="A green button with white text and the word unfocused above alongside a yellow button with black text and a thicker border and the word focused above" />
    <figcaption>From left to right: a button with no focus indicator; a button with a poor focus indicator; a button with a good focus indicator.</figcaption>
</figure>
<p>Focus indicator clarity can be provided in several ways - via the addition of a border or a background color change for example. However it is applied there should be a good colour contrast between the two states so users with vision impairments can easily percieve the difference.</p>
<p>Finally check your design in Windows High Contrast (WHC) to ensure that focus is still visible where expected. Note that <a href="/posts/whc_aria/">WHC exposes native HTML buttons and links differently to ARIA-based ones</a>, including focus states. So it is generally wise to use native HTML where possible.</p>
<h4>Focus obscured</h4>
<p>Focus indicators should not be hidden from the user by other content sitting over it. If other content is obscuring the focus indicator then the user will not be able to see either see that content or where their focus is. There are a few instances where this can happen.</p>
<h5>Focus obscured by non-modal overlays</h5>
<p>A non-modal overlay is one where the rest of the page can still be accessed without having to dismiss the overlay first.</p>
<p>A common use of these is in site menus. However drop-down or fly-out menus can become a hinderance to users when they allow the user to tab through them and onto content which sits behind them without the menu being removed.</p>
<p>Where a menu allows the user to interact with the rest of the page when it is open, the menu should either:</p>
<ul>
<li>be closable via the <kbd>Esc</kbd> key <em>when focus is outside the menu</em> so the user can dismiss it without having to backtrack to the close trigger​</li>
<li>be auto-closing once focus exits the overlay​ - for example by moving to an adjacent link outside the menu</li>
</ul>
<figure>
    <video preload="metadata" src="/assets/images/modules/focus-obscured-menu.mov" controls="show"></video>
    <figcaption>
        <p>The Tesco main navigation has drop-down menus which cannot be dismissed with the Esc key and persist when focus moves off them, resulting in the user's focus being hidden from view. Due to the poor focus indicators on the site I had to force focus indicators to show this issue in practice.</p>
    </figcaption>
</figure>
<p>Without these considerations a user will be forced to try to go back to what triggered the menu in an attempt to dismiss it.</p>
<h5>Focus obscured by modal overlays</h5>
<p>Modal overlays are different from non-modal ones in that they need to be closed before the user can interact with the page which launched it. This might be through choosing from a set of options or by using a close button.</p>
<p>These type of overlays communicate this by either taking over the entire viewport (in a lightbox type pattern) or by adding a semi-transparent backdrop between the modal and the page, effectively focusing the user attention on the modal.</p>
<p>Just as with non-modal overlays the issue with modal overlays can be poor coding which allows the user to access content sitting behind them and then be unable to see where their focus is.</p>
<figure>
    <img alt="Two images of an ecommerce product page. The first shows the prodcut images in a dialog, the dialog background is slightly transparent and a pink focus indicator can be seen on the page behind the dialog. The second image shows the page behind with the focus indicator clearly visible on a button. Text states as the user tabs their focus moves out of dialog and onto items behind it." src="/assets/images/modules/focus-modal.png">
    <figcaption>
    This modal overlay (made slightly transparent here to help illustrate the issue) allows the user to tab to content behind it. As the modal cannot be dismissed with the Esc key, the user will have to tab until they find the close button (difficult as the user will not be able to see their focus indicator behind the modal) or reload the page.
    </figcaption>
</figure>
<p>With a modal dialog the expected behaviour is that focus is restricted to the dialog in the same way as a mouse user cannot access the content behind it. For a keyboard user this would prevent a user from tabbing out of the modal and onto the rest of the page.</p>
<div class="note note--insight">
<p>The <code>dialog</code> element will do a lot of this for you. It will:</p>
<ul>
<li>make the page behind the overlay inert (so the user cannot interact with it)</li>
<li>add the <kbd>Esc</kbd> key functionality</li>
<li>add a backdrop</li>
<li>place focus on the first focusable item in the dialog</li>
</ul>
<p>All with minimal effort for the developer.</p>
</div>
<h4>Focus disappearing</h4>
<p>As well as focus disappearing due to other elements appearing in front of them, a common occurence is for focus to drop out of view entirely. This is most often the result of focusable elements which have been visually hidden still being reachable by keyboard.</p>
<p>A keyboard user will only ever want to access controls which they can see. A simple rule-of-thumb is if the user cannot see it when it has focus, then it should not have received focus.</p>
<p>Let's look at an example. This is part of a main navigation for a site. There is a drop-down for a language selector.</p>
<img src="/assets/images/modules/focus-offscreen.png" alt="A set of links presented horizontally as a site navigation. The first link has the text English and has a downward-facing arrow next to it." data-size="implicit">
<p>However for keyboard users, instead of being able to tab from the current selection to the next link in the navigation, their focus indicator disappears for half-a-dozen hits of the tab key before re-emerging on the register link.</p>
<figure>
<img src="/assets/images/modules/focus-offscreen-tabbed.png" alt="The same links but with an overlay shoing the focus order. The first link, English with the arrow, is labelled 6. The second link is labelled 13. The intervening numbers are arranged vertically under the English link, but no associated elements are visible." data-size="implicit">
<figcaption>Showing focus order with the IBM Equal Access Accessibilty Checker browser plugin.</figcaption>
</figure>
<p>This is because the method of hiding the collapsed menu options was incorrectly applied making the options available all the time.</p>
<img src="/assets/images/modules/focus-offscreen-open.png" alt="The same links, but this time the English link has been clicked to reveal a list of different language options in the same location as the numbered overlays from the previous image." data-size="implicit">
<p>This type of issue is especially harmful because putting content into collapsable components (or hiding off-screen behind a hamburger menu) is often used to hide large sets of options. The worst example I found of this was a filter component which was visually hidden but available to keyboard and screen-reader users and contained over 80 tab stops!</p>
<p>When hiding content from view, whether that is for a mobile-style menu, a set of filters or a drop-down like this, always check that the content inside cannot be tabbed to by keyboard users (or seen by screen-readers).</p>
<p><a href="https://www.scottohara.me/blog/2017/04/14/inclusively-hidden.html">Scott O'Hara</a> and <a href="https://css-tricks.com/inclusively-hidden/">CSS Tricks</a> both have articles on how to hide content in an accessible way.</p>
<h3>Focus wrap-up</h3>
<p>If the user cannot see where they are on the page then it becomes very difficult to interact with the content and mistakes will be very likely, leading to further issues.</p>
<ul>
<li>check focused items can be easily differentiated from unfocused ones</li>
<li>check the focused item is not obscured by other content, especially components like menus and dialogs</li>
</ul>
<h2 id="functionality">Functionality</h2>
<p>There are two main questions we need to ask when looking at keyboard functionality.</p>
<ul>
<li>can the user reach the control with the keyboard?</li>
<li>can the control be activated with the keyboard?</li>
</ul>
<p>Check to see the user can reach any element on the page which they should be able to interact with. Pay particular attention to more complex components and navigation sections. Any component which utlises javascript is especially prone to omitting keyboard functionality.</p>
<h3>Using the correct element</h3>
<p>The easiest way to ensure a keyboard user can move focus to a control is to use the correct element. This most often means using <code>input</code>, <code>button</code> and <code>a</code> elements.</p>
<p>Whilst in theory a <code>span</code> or <code>div</code> can be made to act like one of the above, it requires a lot of consideration and additional technical complexity. This is often missed and only mouse users are accounted for, or only partially implemented and a poor experience is the result.</p>
<div class="note note--activity">
<h4>Example</h4>
<p>The navigation on the Thomas Cook website does not allow keyboard users to access the “My Account” item, as shown by the IBM Equal Access tool below - there is not a focus-order marker for it.</p>
<img src="/assets/images/modules/focus-element.png" alt="A site navigation. Number overlays mark each link, but none are shown on the My Account option." data-size="implicit">
<p>Let's take a look at the code for the “My Account” option.</p>
<pre class="language-html"><code class="language-html">/*My Account*/
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>tc-my-account-navigation-open</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>⭐️umd9c1-1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>tc-menu-toggle-icon<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>tc-menu-toggle-name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>My Account<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>tc-my-account-navigation-open</span><span class="token punctuation">></span></span>
</code></pre>
<p>Now let's compare it to the ”Wishlist” one which sits alongside. This one does take focus.</p>
<pre class="language-html"><code class="language-html">/*Wishlist*/
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>tc-my-account-wishlist-icon</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>⭐️umd9c1-1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/my-account/wishlist<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>wishlist-heart<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>heart-love-outline.svg<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Wishlist<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>tc-my-account-wishlist-icon</span><span class="token punctuation">></span></span>
</code></pre>
<p>We can see the “My Account” one is made up only of <a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/generic_role">generic elements</a> (<code>divs</code>), whilst the wishlist is a link (<code>a</code>):</p>
<p>Generic elements (such as <code>span</code> and <code>div</code>) do not take focus, meaning our keyboard user cannot access them. Moreover, whilst a screen-reader user will be able to read the content, they will not know that it is clickable. This is because the elements which have that generic <code>role</code> will be announced purely as text.</p>
<h5>The fix</h5>
<p>We can fix these issues with a two step approach.</p>
<p>The first is to use the correct element for the job at hand. For this example I will use an <code>a</code> which will allow for a fallback in case javascript is not available and take the user to the account page. We can then progressively enhance this link to open the account menu when javascript is available.</p>
<p>Important to note that an <code>a</code> element without an <code>href</code> is not a link and cannot be focused. So if this was not going to be progressively enhanced I'd opt for a <code>button</code> instead.</p>
<p>I have also added two <a href="/posts/aria/">ARIA</a> attributes on the link to tell screen-reader users that this link will trigger a same-page menu. As we wouldn't want these on a link which will cause a page load we should only add these as part of the javascript-applied progressive enhancement which also adds the event handlers.</p>
<p>This is the code as it would be rendered:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>tc-my-account-navigation-open</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>⭐️umd9c1-1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/my-account/<span class="token punctuation">"</span></span> <span class="token attr-name">aria-haspopup</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token attr-name">aria-expanded</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>tc-menu-toggle-icon<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>tc-menu-toggle-name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>My Account<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>tc-my-account-navigation-open</span><span class="token punctuation">></span></span>
</code></pre>
<p>With our change in place the navigation now allows keyboard users to access it:</p>
<img src="/assets/images/modules/focus-element-fix.png" alt="The same navigation now shows the focus overlay indicating that the My Account link is included in the focus order." data-size="implicit">
<p>Our next step would be to ensure that the keyboard user can then trigger the item to open the menu:</p>
<img src="/assets/images/modules/focus-element-fix2.png" alt="The my account link has been actived and a popup menu appears providing options for the user." data-size="implicit">
<p>and make sure that our new <code>aria-expanded</code> attribute is updated to <code>true</code> when the menu is open.</p>
</div>
<p>This issue is more widespread than you might think. Here is another example, this time the Premier Inn main navigation is entirely unavailable to keyboard users.</p>
<img src="/assets/images/modules/focus-element-2.png" alt="A screenshot of the top of a Premier Inn page showing the navigation and and overlay indicating the tab stops. The primary navigation options are not showing as being in the tab order.">
<p>If we take a look at one of those navigation links which does not work for keyboard users we can see a similar story.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>css-1wgzkpb<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>popover-trigger-:r1:<span class="token punctuation">"</span></span> 
        <span class="token attr-name">aria-haspopup</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>dialog<span class="token punctuation">"</span></span> 
        <span class="token attr-name">aria-expanded</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span> 
        <span class="token attr-name">aria-controls</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>popover-content-:r1:<span class="token punctuation">"</span></span> 
        <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>css-jls80j<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>chakra-text css-1tk9twk<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
                Discover Premier Inn
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
</code></pre>
<p>As with the previous example we can see the elements are not focusable. Unfortunately whilst they have added <code>aria</code> attributes, they have omitted the most basic functionality. As these <code>aria</code> attributes are not permitted on generic elements these will not be communicated to a screen-reader.</p>
<p>Again, this is a simple fix and can be done by updating the code to use the correct element.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>css-1wgzkpb<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>popover-trigger-:r1:<span class="token punctuation">"</span></span> 
        <span class="token attr-name">aria-haspopup</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>dialog<span class="token punctuation">"</span></span> 
        <span class="token attr-name">aria-expanded</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span> 
        <span class="token attr-name">aria-controls</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>popover-content-:r1:<span class="token punctuation">"</span></span> 
        <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>css-jls80j<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>chakra-text css-1tk9twk<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
                Discover Premier Inn
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
</code></pre>
<h3>Tabindex</h3>
<p>You may have come across the <code>tabindex</code> attribute. The order in which a user tabs through a page's HTML elements (links, buttons and form controls for example) is called the ”natural tab order”.</p>
<p>Very occasionally you may need to add an element to that tab order which would not normally be there. In this case you can use a zero value in the <code>tabindex</code> attribute to do this.</p>
<div class="note note--takeaway">
<p>Note. Tabindex should only be added to elements which need to be focusable in order for them to be interacted with. You also do not need to add <code>tabindex</code> to an element which can already take focus (such as a <code>button</code>) - this is redundant.</p>
<p><a href="https://tetralogical.com/blog/2024/04/04/when-to-use-tabindex-0/">When to use tabindex 0</a></p>
</div>
<p>For example here we have two buttons with a <code>div</code> element between them. A user would tab from the first button to the second:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span><span class="token punctuation">></span></span>One<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">></span></span>I'm plain text<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span><span class="token punctuation">></span></span>Two<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<p>But if we add a <code>tabindex</code> to the <code>div</code> element:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span><span class="token punctuation">></span></span>One<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">tabindex</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>I'm plain text<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span><span class="token punctuation">></span></span>Two<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<p>The <code>div</code> will now be included in the natural tab order. The user will now tab from the first button, then to the <code>div</code>, then the second button. As it stands this is not useful or accessible but it demonstrates the principal.</p>
<p>This is something you should only very rarely need to do. Whilst the <code>div</code> can now take focus it is neither announcing as a button or link to screen-readers and will not respond to keyboard clicks. You can start to see why it is always a good idea to use the correct element for the job.</p>
<p>But there are occasions where it can be helpful where no existing HTML element is appropriate. For example, creating a scrollable container (such as a <code>div</code>) will necessitate the container to be focusable to allow keyboard users to scroll the contents. Focusable controls should also have an accessible name for assistive technology and as an <code>aria-label</code> can only be applied to certain <code>roles</code> the <code>div</code> will need to be promoted to something like a <code>role=&quot;region&quot;</code>. As you can see this process has several ways of being incorrectly applied and causing more barriers.</p>
<p><code>Tabindex</code> can also take two other types of values. A negative (<code>-1</code>) will allow the element to be programmatically focussed (using javascript) without being added to the natural tab order. This can be occasionally useful, but again rare.</p>
<p>The other value is a positive integer. These should be used even more rarely than our first example as they entirely usurp the natural tab order. This can cause a lot of confusion for users as well as being problematic to maintain in a codebase.</p>
<p><a href="https://www.scottohara.me/blog/2019/05/25/tabindex.html">Tabindex: it rarely pays to be positive</a></p>
<h3 id="how-styling-can-impact-functionality">How styling can impact functionality</h3>
<p>Even when we think we have covered all the bases and have progressively enhanced our interface, it is important to test!</p>
<p>Below we have a product view with various links and buttons. Here I have used the <a href="https://www.tpgi.com/arc-platform/arc-toolkit/">ARC Toolkit's</a> tab order highlight option which works in the same way to the other tools we have used so far.</p>
<img src="/assets/images/modules/focus-css.png" alt="A product view. Links and buttons have numbers assigned by the tab order plugin. The size options which are represented by the size name - XS, S, M, L and XL - in boxes do not have numbers assigned indicating they are not keyboard accessibe." data-size="implicit">
<p>The sizing options are not showing as focusable items (confirmed by actual keyboard usage). Let's take a look at the HTML for them:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span> <span class="token attr-name">title</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>XS<span class="token punctuation">"</span></span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>XS<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>option_field<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>XS<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>radio<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>XS<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>SingleOption<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>list_option<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    XS
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>checkmark<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">></span></span>
</code></pre>
<p>Everything looks ok here as an input has been used which should be focusable. The issue actually lies in the CSS used to hide the radio button:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.option_field input</span> <span class="token punctuation">{</span>
    <span class="token property">display</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre>
<p>The use of <code>display: none</code> is the issue. This will remove the <code>input</code> from the rendered page. This then means there is effectively no <code>input</code> on the page to get focus.</p>
<p>This also has a knock-on effect for screen-reader users. No <code>input</code> in the page here means the <code>label</code> associated with it then becomes plain text. Screen-reader users will not be informed the sizes are selectable or be able to select one (just like the keyboard users).</p>
<p>To a screen-reader user the “XS” option will simply be announced as “XS”. The sold out size “XL” will also be read out just as “XL” - as the strikethough is not picked up by screen-readers and the <code>disabled</code> attribute on the <code>input</code> is unavailable as the <code>input</code> is not rendered.</p>
<p>That's a lot of inaccessible effects from some CSS!</p>
<p>The accessibility fix is simply amending the CSS to keep the <code>input</code> in the render but still hide it from sight:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.option_field input</span> <span class="token punctuation">{</span>
    <span class="token property">position</span><span class="token punctuation">:</span> absolute<span class="token punctuation">;</span>
    <span class="token property">opacity</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre>
<p>Keyboard access is restored without affecting the visual appearance of the component:</p>
<img src="/assets/images/modules/focus-css-fix.png" alt="A product view. Links and buttons have numbers assigned by the tab order plugin. The size options which are represented by the size name in a box now have numbers assigned indicating they are also keyboard accessibe." data-size="implicit">
<p>Now screen-reader information also improves.</p>
<p>The “XS” option is now announced as:</p>
<blockquote>
<p><em>XS, tickbox, unticked, 1 of 5</em></p>
</blockquote>
<p>and the “XL” option is announced as:</p>
<blockquote>
<p><em>XL, dimmed, tickbox, unticked, 5 of 5</em></p>
</blockquote>
<p>A screen-reader user now can tell which sizes are sold out, how many sizes there are and which one they have selected.</p>
<p>We would then need to ensure that focus indicators are being applied and actioning the inputs with keyboard has the desired effect.</p>
<h3>Reachable but not operable</h3>
<p>It is also possible to have a control be reachable via keyboard, but then not be able to action it.</p>
<p>This is normally due to an issue with keyboard events not being handled. When a click handler is added to a link or button element this will include event handlers for keyboard too. However when a click handler is added to a <code>div</code> or <code>span</code> (or other non-native control element) we need to add specific event handlers for keyboard ourselves.</p>
<div class="note note--insight">
<p>One thing to be aware of is the difference between keyboard clicks and screen-reader clicks and why a screen-reader may be able to trigger something which a keyboard user could not.</p>
<p>When you press Enter on an element with a screen-reader, the element receives a (synthetic) click event rather than a keypress event.</p>
<p>So if your element is only listening for an <code>onClick</code> event you may well be able to access it using a screen-reader, but keyboard users will be left with nothing.</p>
</div>
<p>The Asda main navigation has a “More” link which for mouse users opens a drop-down with additional links.</p>
<img src="/assets/images/modules/focus-asda.png" alt="Asda navigation. A link labelled More has opened a drop-down containing nearly a dozen more links to departments and services.">
<p>For keyboard users, whilst they can seemingly reach this, no amount of key pressing will open this menu.</p>
<img src="/assets/images/modules/focus-asda-button.png" alt="The More link with a blue outline focus indicator on the arrow icon which sits to the right of the text." data-size="implicit">
<p>Let's examine how this control is coded:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>sub-nav<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>nav-toggle<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>submenu-hamburger-label<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>More<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>button<span class="token punctuation">"</span></span> 
        <span class="token attr-name">tabindex</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span> 
        <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>More, list 11 items<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>svg</span><span class="token punctuation">></span></span>...<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>svg</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p>We have an <code>a</code> element without an <code>href</code>. Inside this is a <code>span</code> with <code>role=&quot;button&quot;</code> and <code>tabindex=&quot;0&quot;</code> attributes.</p>
<p>So what is happening? Well, as the <code>a</code> element is missing an <code>href</code> it is not classified as a link and nor will it capture focus. This means the keyboard focus skips past that and lands on the internal <code>span</code> thanks to its <code>tabindex</code> attribute having added it to the natural tab order.</p>
<p>The issue for the keyboard users is that the javascript event handlers on the <code>span</code> are only accounting for a <code>click</code> event. As we have already mentioned, on a <code>span</code> (even with a <code>role=&quot;button&quot;</code>) this will not include keyboard events.</p>
<p>The fix for this is to change the focus point from the <code>span</code> to the <code>a</code> element. Alternatively additional keyboard event listeners could be added, but we should always be using the correct element where possible. We also really want to remove the confusion of the nested controls and the repetition of text which that brings.</p>
<p>Let's remove the following attributes from the <code>span</code>:</p>
<ul>
<li><code>role</code> - as we no longer want this to pretend to be a button</li>
<li><code>tabindex</code> - as we no longer want this to get focus (we will be using the link)</li>
<li><code>aria-label</code> - as it was mis-representing this as a list when it had its role set as a button, and we no longer need this with our changes</li>
</ul>
<p>We should also add some ARIA (<code>aria-expanded</code> and <code>aria-haspopup</code>) to help screen-reader users determine how this operates (which will need to be updated when the menu opens).</p>
<p>This results in the following:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>sub-nav<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>nav-toggle<span class="token punctuation">"</span></span> 
    <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#<span class="token punctuation">"</span></span>
    <span class="token attr-name">aria-expanded</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span> 
    <span class="token attr-name">aria-haspopup</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>submenu-hamburger-label<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>More<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>svg</span><span class="token punctuation">></span></span>...<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>svg</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p>We could probably tidy this up some more and ideally I'd want to use a <code>button</code> as it is not really a link, but this is a definite improvement.</p>
<img src="/assets/images/modules/focus-asda-button-fix.png" alt="The More link with a blue outline focus indicator around the text and icon and the menu open below it." data-size="implicit">
<p>Now the focus goes to the link (and is much larger and more visible as a result) and a keyboard user can action it. Additionally a screen-reader user gets the information they should.</p>
<p>Read more about <a href="/posts/aria/">ARIA</a> and <a href="/posts/accessible-names/">accessible names</a>.</p>
<p>Worth noting that although this is a change to markup and that it greatly improves not only keyboard and screen-reader accessibility, there does not need to be any change in how the component looks to the user.</p>
<h3>Functionality wrap-up</h3>
<ul>
<li>use native HTML controls (inputs, links, buttons) as a first choice when you expect a user to click on something</li>
<li>make sure <code>a</code> elements have an <code>href</code> even if you are using javascript to handle clicks</li>
<li>if you need to use javascript make sure you cater for keyboard as well as mouse activation</li>
<li>you don't get keyboard event handlers for free with generic roles (<code>div</code> and <code>span</code>)</li>
<li>do not hide <code>inputs</code> if you expect the user to interact with them</li>
</ul>
<p><a href="/posts/automated-testing/#enforcing-good-keyboard-accessibility">Improving our tests to check for good keyboard accessibility</a></p>
<h2 id="logical-tab-order">Logical tab order</h2>
<p>Typically for a left-to-right language such as English, we expect focus order to follow the natural reading order, that is for it to move from left to right as it progresses down the page. If we deviate from this reading order expectation with our focus order it can be disorientating for the user and they have a larger chance of losing sight of the focus indicator.</p>
<h3>Tabindex</h3>
<p>As we have already touched on, it is possible to manipulate the focus order using the <code>tabindex</code> attribute with a positive number value.</p>
<p>Here is an example of where this can go wrong. On the Tesla Powerwall site, content halfway down the page has been given a positive <code>tabindex</code>.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> 
    <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>tab<span class="token punctuation">"</span></span> 
    <span class="token attr-name">aria-selected</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> 
    <span class="token attr-name">aria-controls</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>energy-carousel-panel-0<span class="token punctuation">"</span></span> 
    <span class="token attr-name">tabindex</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>heading<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
            Store Extra Energy
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>tcl-carousel-v2__toggle-panel-copy<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
            When your solar system ...
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<p>This makes this content the first item which will be focused on the page, even before the logo or primary navigation. But this also means that this section will then be “skipped” as the user moves down the page, making for a confusing experience.</p>
<img src="/assets/images/modules/key-tab-order-2.png" alt="The Tesla Powerwall page with an overlay showing the tab stops. The first 3 tab stops are halfway down the page in a tabbed component, after which the tab order returns to the top of the page." data-size="implicit">
<p>This is likely a mistake rather than a concious decision. The component in question is a <code>tablist</code> which normally has a “<a href="https://www.stefanjudis.com/today-i-learned/roving-tabindex/">roving tabindex</a>”. Rather than using <code>tabindex=&quot;1&quot;</code>, this should have been using <code>tabindex=&quot;0&quot;</code> for the active tab and <code>tabindex=&quot;-1&quot;</code> for the inactive tabs. However it shows the pitfalls accompanying the use of <code>tabindex</code>.</p>
<h3>Source order vs visual order</h3>
<p>There is another way in which we can inadvertently jumble up the focus order for the keyboard user, and that is by manipulating the visual order of our content.</p>
<p>Keyboard focus always follows the order of focusable items as they appear in the source code. When we apply CSS to that code it can visually alter the placement of content (and those focusable items), but this does not change the order in which they receive focus.</p>
<p>Let's look at a very much simplified example.</p>
<figure>
    <video preload="metadata" src="/assets/images/modules/source-order-sml.mov" controls="show"></video>
    <figcaption>
<p>Here we have a HTML list of 5 buttons labelled one to five. When we tab through them the focus order follows the visual order from top to bottom, one to five.</p>
<p>Then we add some CSS, in this case <code>display:grid</code>, to reposition the third button at the top of the list. Now when we perform the same test, the focus still follows the same order, one to five, despite the third button appearing at the top of the list.</p>
<p></figcaption></p>
</figure>
<p>As you can see the focus follows the source order, not the visual order. This also affects screen-reader users in the same way, but not just for focuable items as screen-reader software reads all content.</p>
<h3>Keyboard traps</h3>
<p>These are relatively rare, but when found can be a complete blocker for a user. They occur when a user reaches an element or component and they cannot exit it using keyboard commands. They are often the result of javascript event handlers not accounting for people using keypresses to navigate.</p>
<p>For example, the National Express homepage has a journey planner at the top of the page. Below it there is also a lot of additional content, including timetables, booking management tools and more.</p>
<p>The user focus gets caught by the first input of the journey planner. The user cannot exit the input without entering data due to javascript event listeners which move the focus straight back to the input if no entry has been made. They cannot even use one of the options in the drop-down as they are not reachable via keyboard.</p>
<figure>
    <img src="/assets/images/modules/focus-trap.png" alt="A form field below the title choose your journey. The field has focus and has placeholder text of Travel from. It has a drop-down with 3 options intended to make finding the start point easier.">
    <figcaption>
        This input prevents the user from exiting it in either direction. The helpful options in the drop-down are not accessible to keyboard users.
    </figcaption>
</figure>
<p>Similarly, even if they enter a valid stop they are immediately moved to the &quot;Travel to&quot; field which then prevents the user from moving back to the previous field to make any correction.</p>
<p>This is compounded by the result page where the “Edit journey” option is not reachable by keyboard.</p>
<figure>
    <img src="/assets/images/modules/key-trap-focus.png" alt="A page listing the different options for a journey with a tab order overlay. The edit journey option and option to view earlier journeys are not numbered indicating they cannot be reached with keyboard.">
    <figcaption>
        The “Edit journey” and “Earlier coaches” options (highlighted) are not reachable by keyboard.
    </figcaption>
</figure>
<p>This type of failure is simple to avoid if those designing and building them account for the different ways a user may interact with it.</p>
<h2 id="preventing-doubling-up">Preventing doubling up</h2>
<p>Something which will frustrate a keyboard user is where multiple elments are used to link to the same resource.</p>
<p>Let's take a look at this site navigation.</p>
<img src="/assets/images/modules/focus-double-nav.png" alt="The navigation area for Asda. Two links have been highlighted, help and find a store. Both have icons to the left of the link text.">
<p>Note the “Help” and “Find a store” links which have the icons alongside? For a keyboard user there are two tab stops for each of those:</p>
<img src="/assets/images/modules/focus-double-nav-tabs.png" alt="The Asda help and find a store navigation links in more detail and with a tab stop overlay shown. The icons and links are separate tab stops, so each link has two tab stops.">
<p>This is not ideal as we are asking the user to do twice the work they should. So why is this happening? If we take a look at the code we can see:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://storelocator.asda.com<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>button<span class="token punctuation">"</span></span> <span class="token attr-name">tabindex</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>svg</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>asda-icon<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>...<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>svg</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
    Find a store
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p>Here we have the link, but inside is a <code>span</code> which has been made into a <code>button</code> using ARIA (unfortunately the latter is also missing an accessible name). There is no need for this secondary control, so we can simplify this to the following without loss of functionality:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://storelocator.asda.com<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>svg</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>asda-icon<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>...<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>svg</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
    Find a store
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p>Which when applied to both links give us a much cleaner tab order:</p>
<img src="/assets/images/modules/focus-double-nav-fix.png" alt="The navigation links are now showing just one tab stop each with the tab stop encompassing both the text and icon.">
<p>Another place where doubling up is often seen is in card components. Here is a typical example with the links highlighted:</p>
<img src="/assets/images/modules/focus-double-card.png" alt="A product card showing an outdoor jacket. The overlay shows that the card itself is a link but so is the product name, a wishlist icon and a quick view button." data-size="implicit">
<p>and the (simplified) HTML:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>1827b921f1.jpg<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Carbonite Snow Jacket <span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h2</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>product-link__title<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
            Carbonite Snow Jacket 
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h2</span><span class="token punctuation">></span></span>
    ...
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>product-price-wrapper<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
        €268.99
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span><span class="token punctuation">></span></span>Quick View<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>visually-hidden<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Add to Wishlist<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p>We can see the card has been entirely contained by a link to make the whole card clickable. The issue this creates is adding a repetition of links as this is the same link target as the one which wraps the heading. The other issue with a wrapping link like this is also that its accessible name becomes the link's contents - in this case the entire card contents - and is announced to a screen-reader as:</p>
<blockquote>
<p>&quot;Carbonite Snow Jacket Carbonite Snow Jacket Carbonite Snow Jacket 1 / 5 2 / 5 3 / 5 4 / 5 5 / 5 €169.99 QUICK VIEW Add to Wishlist&quot;</p>
</blockquote>
<p>As the link wrapping the entire card is only meant for mouse users, we can devolve that to a javascript event on the card wrapper instead, triggering the link on the heading. This allows us to then remove that link element. Something like this:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">let</span> cardWrapper <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">".card-wrapper"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> cardLink <span class="token operator">=</span> cardWrapper<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">"h2 > a"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
cardWrapper<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
    cardLink<span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p>The functionality of having the entire card clickable will remain for mouse users, but keyboard and screen-reader users will benefit.</p>
<p>Removing this duplication has the potential to remove a lot of unnecessary keypresses for users as these cards are used to display products in grids.</p>
<h2 id="managing-focus-when-content-updates">Managing focus when content updates</h2>
<p>When content is removed from the page and the user has their focus on one of the elements which is removed it is important that the user's focus is placed elsewhere thoughtfully. If not then it is likely that their focus will drop back to the top of the page. This will be both disorientating but also mean they will need to make their way down to where they were all over again.</p>
<p>This is especially important when we look at things like:</p>
<ul>
<li>closing dialogs</li>
<li>deleting items from a list</li>
<li>adding new content to a section which causes the section to be re-rendered</li>
</ul>
<p>Here is an example of how a dialog can be dismissed leaving the user back at the top of the page:</p>
<figure>
    <video preload="metadata" src="/assets/images/modules/focus-manage-sml.mov" controls="show"></video>
    <figcaption>
<p>Here the user moves through the flight planning form on the RyanAir website. After entering airport and date information, the number of adults and children is entered using a small dialog.</p>
<p>Once the passengers have been added in the dialog the user clicks the done button to close the dialog. Their focus is then dropped back to the top of the page, instead of back on the form input, forcing them to navigate the form again.</p>
<p></figcaption></p>
</figure>
<p>Because the dialog the user's focus was on has been removed from the page (either through CSS or by removing the element itself) the focus drops back to the top of the page. What should happen is the javascript should place the focus back onto the trigger for the dialog, in this case the passenger input. This helps the user orientate themselves and allows them to either edit the data they just entered or proceed to the next control.</p>
<p>Whilst browsers are beginning to assist with focus management, it is essential for us to be mindful of any effects on a user's focus when a page is updated.</p>
<h2 id="did-we-wcag">Did we WCAG?</h2>
<p>Despite this being a very simple accessibility test on the surface, you can see the complexities it can throw up, as well as pointers to how assistive technology such as screen-readers can be impacted.</p>
<p>If we take a look at the <a href="/posts/guidelines-and-legalities/#wcag">WCAG guidelines</a> we can point to a lot of criteria which the issues we have described above could be failed against:</p>
<ul>
<li>1.3.1 Info and relationships</li>
<li>1.3.2 Meaningful sequence</li>
<li>2.1.1 Keyboard</li>
<li>2.1.2 No keyboard trap</li>
<li>2.4.1 Bypass blocks</li>
<li>2.4.3 Focus order</li>
<li>2.4.7 Focus visible</li>
<li>2.4.11 Focus not obscured (minimum)</li>
</ul>
<h2 id="wrap-up">Wrap-up</h2>
<p>As we have seen with our examples keyboard accessibility is something which is frequently overlooked, despite these examples being from sites which you might expect have thorough testing procedures.</p>
<p>Keyboard accessibility is something which is simple to test and requires no specialist software. It is a fundamental part of making a website usable by many groups of users, and even acts as a pointer towards deeper accessibility issues which can affect assistive technology users.</p>
<p>With no need for specialist software and simple testing techniques keyboard accessibility should be embedded into every team's accessibility processes.</p>

        ]]></content>
      </entry>
    
	
    
	
    
      
      <entry>
        <title>Guidelines and legalities</title>
        <link href="https://liptrot.org/posts/guidelines-and-legalities/"/>
        <updated>2024-07-04T13:00:00Z</updated>
        <id>https://liptrot.org/posts/guidelines-and-legalities/</id>
        <content type="html"><![CDATA[
          <h2>Contents</h2>
<ul>
<li><a href="#contents">Contents</a></li>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#standards">Standards</a>
<ul>
<li><a href="#wcag">WCAG</a></li>
<li><a href="#en-301-549">EN 301 549</a></li>
<li><a href="#other-standards">Other standards</a></li>
</ul>
</li>
<li><a href="#all-encompassing-uk-legislation">All-encompassing UK legislation</a>
<ul>
<li><a href="#equality-act-2010">Equality Act (2010)</a></li>
<li><a href="#public-sector-equality-duty">Public Sector Equality Duty</a></li>
</ul>
</li>
<li><a href="#public-sector-legislation">Public Sector legislation</a>
<ul>
<li><a href="#uk-public-sector-bodies-accessibility-regulations">UK: Public Sector Bodies Accessibility Regulations</a></li>
<li><a href="#eu-directive-20162102">Europe: EU Directive 2016/2102</a></li>
<li><a href="#usa-section-508">USA: Section 508</a></li>
</ul>
</li>
<li><a href="#private-sector-legislation">Private Sector legislation</a>
<ul>
<li><a href="#europe-the-european-accessibility-act">Europe: The European Accessibility Act</a>
<ul>
<li><a href="#service-areas-covered">Service areas covered</a></li>
<li><a href="#products-covered">Products covered</a></li>
<li><a href="#conformity">Conformity</a></li>
<li><a href="#current-state-of-european-accessibility">Current state of European accessibility</a></li>
<li><a href="#further-reading">Further reading</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#examples-of-legal-enforcement">Examples of legal enforcement</a>
<ul>
<li><a href="#student-loans-company">Student Loans Company</a></li>
<li><a href="#department-forwork-and-pensions-dwp">Department for Work and Pensions (DWP)</a></li>
</ul>
</li>
<li><a href="#standards-and-legislation-are-the-baseline-not-the-target">Standards and legislation are the baseline, not the target</a></li>
<li><a href="#wrap-up">Wrap-up</a></li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>Accessibility is a large and complex subject, even when narrowed down to one area such as the web. To help those building websites or producing web content make their products as accessible as possible there are a set of standards produced by a central web body.</p>
<p>These standards are then used by law-makers around the world to enforce accessibility best practice.</p>
<p>(Of course we are talking about legal things here so I'm going to issue the standard “I am not a lawyer” statement. Do your own research.)</p>
<h2 id="standards">Standards</h2>
<p>When we talk about accessibility laws, the actual legislation often does not provide details of what you need to do to comply. Instead they reference relevant standards. This allows the legislation to remain current by indicating that the most current version of that standard should be followed.</p>
<p>The two main standards are <strong>WCAG</strong> and <strong>EN 301 549</strong>.</p>
<h3 id="wcag">WCAG</h3>
<p>WCAG stands for Web Content Accessibility Guidelines. They are a set of criteria which encapsulate ways of validating web-based media to check it for accessibility best practice. The <a href="https://www.w3.org/TR/WCAG22/">current version of WCAG is 2.2</a> which was released in October 2023, the previous version was released in June 2018.</p>
<p>They are published by the W3C (World Wide Web Consortium) who are the international body which produces standards and guidelines for the web. They produce standards for many web technologies, from HTML and CSS to Web Augmented Reality and WebDriver.</p>
<p>The criteria are split into 4 main sections:</p>
<ul>
<li>Perceivable - can the user observe the interface they need to interact with?</li>
<li>Operable - can the interface be used?</li>
<li>Understandable - can the user understand what they need to do and how to do it?</li>
<li>Robust - can the interface be interpreted by assistive technologies?</li>
</ul>
<p>The WCAG guidelines are further split into 3 conformance levels:</p>
<ul>
<li>A (25 criteria)</li>
<li>AA (13 criteria)</li>
<li>AAA (23 criteria)</li>
</ul>
<p>If your product undergoes an accessibility audit (a review to determine if there are any accessibility issues), it will normally concentrate on the first two of these as they are what are referred to in the regulations.</p>
<p>You should always tackle Level A issues that have been found first as generally these are more obstructive than Level AA.</p>
<p>Level AAA issues tighten up a lot of the other criteria to be more strict but can be difficult to meet without compromising other aspects of usability and accessibility. However this doesn’t mean these criteria should be ignored.</p>
<p>Each criterion might have normative and non-normative sections:</p>
<ul>
<li>Normative sections are used to measure compliance.</li>
<li>Non-normative sections are examples or used for education purposes and are not used for compliance.</li>
</ul>
<p>WCAG is also an ISO Standard (ISO/IEC 40500:2012 ), however because ISO standards are only reviewed every 5 years it is still only tracking WCAG 2.0 in its ISO form. However having ISO status does mean it can be applied in more countries and situations that it might otherwise.</p>
<p>It's important to note that WCAG does not cover every potential accessibility issue or individual case. This means that a site which conforms to WCAG can still be inaccessible to a user.</p>
<h3 id="en-301-549">EN 301 549</h3>
<p><a href="https://www.etsi.org/deliver/etsi_en/301500_301599/301549/03.02.01_60/en_301549v030201p.pdf">EN 301 549 (PDF)</a> is also known as the “European Harmonised Standard for Accessibility requirements for ICT products and services” and has been around since 2014. It was updated in 2018 to use WCAG as a compliance metric. It sets out a standard for ICT procurement in the EU but has gone on to be adopted by other countries such as Japan, Canada and Australia.</p>
<p>This standard does go beyond WCAG in some cases, such as requiring authoring tools to guide the output of accessible content and provide accessible documentation and support (section 11.8). The W3C (authors of WCAG) defers this to the Authoring Tool Accessibility Guidelines (ATAG) so this would not otherwise be covered by EN 301 549. It also requires support of user preferences (section 11.7).</p>
<h4>User preferences</h4>
<p>One of the areas where EN 301 549 goes beyond WCAG is in support of user preferences.  From the relevant section (11.7) these preferences include:</p>
<blockquote>
<p>&quot;units of measurement, colour, contrast, font type, font size, and focus cursor&quot;</p>
</blockquote>
<p>So where the website or app can get this preference information from the browser or operating system it should use it.</p>
<p>For some of the areas mentioned this is what we would normally be doing anyway. For example allowing the user to adjust font size by adjusting it in their browser settings. It’s worth noting the WCAG criteria for font size does not specify the mechanism of doing this, so page zoom is sufficient. However for the European directive this is not sufficient and so section 11.7 comes in.</p>
<div class="note note--insight">
<p>Some are also looking at whether <a href="https://www.nngroup.com/articles/dark-mode-users-issues/">dark mode</a> is something which would be covered by this. The problem is that the wording is very broad. Here are some links which discuss this aspect further:</p>
<ul>
<li><a href="https://labs.etsi.org/rep/HF/en301549/-/issues/23">Re-examine appropriateness of 11.7 for websites and mobile applications</a>, especially comments <a href="https://labs.etsi.org/rep/HF/en301549/-/issues/23#note_13459">13459</a>, <a href="https://labs.etsi.org/rep/HF/en301549/-/issues/23#note_17823">17823</a> and <a href="https://labs.etsi.org/rep/HF/en301549/-/issues/23#note_18028">18028</a></li>
<li><a href="https://uxpodcast.com/329-dark-mode/">Dark mode - UX Podcast</a></li>
</ul>
<p>There looks like there is consensus that dark mode is not explicity being asked for but could be brought in under wider user preferences and that the wording will be updated.</p>
</div>
<h4>Current state</h4>
<p>EU 301 549 is <a href="https://portal.etsi.org/webapp/workProgram/Report_WorkItem.asp?wki_id=64282">currently being revised</a> (as of July 2025) to further support the EU Accessibility Act (see below) and should see a new version released in 2025.</p>
<h3 id="other-standards">Other standards</h3>
<p>Due to the complex nature of accessibility there are additional standards which the W3C publish to deal with specific cases. Some of the main ones are listed below.</p>
<p><a href="https://www.w3.org/TR/html-aria/">“ARIA in HTML”</a>, and <a href="https://www.w3.org/TR/wai-aria-1.2/">“Accessible Rich Internet Applications (WAI-ARIA)”</a> both which deal with making websites more accessible particuarly to users of assistive technology. <a href="/posts/aria/">Read more about ARIA.</a> ARIA is sometimes mentioned in WCAG criteria as one way of satisfying the requirements.</p>
<p><a href="https://www.w3.org/TR/ATAG20/">“Authoring Tool Accessibility Guidelines (ATAG)”</a> is a standard for making content authoring tools accessible. So if your product has an editorial interface then this standard would apply.</p>
<p><a href="https://www.w3.org/TR/ctaur/">“Collaboration Tools Accessibility User Requirements”</a> is a standard for any tools which allow collaboration ranging from tracking changes to real-time co-editing.</p>
<p>The W3C also publish “notes” which are reference documents rather than standards, but which can contain useful insights, such as:</p>
<ul>
<li><a href="https://www.w3.org/TR/coga-usable/">“Making Content Usable for People with Cognitive and Learning Disabilities”</a></li>
<li><a href="https://www.w3.org/TR/mobile-accessibility-mapping/">“Mobile Accessibility: How WCAG 2.0 and Other W3C/WAI Guidelines Apply to Mobile”</a>. Whilst this uses the older WCAG 2.0 as a base this shows how the web-focused WCAG guidelines can be mapped to mobile apps.</li>
</ul>
<h2 id="all-encompassing-uk-legislation">All-encompassing UK legislation</h2>
<p>There are some fundamental laws which exist which can be cited in discrimination claims. Whilst these do not cover digital aspects specifically, the outcomes of digital discrimination are covered.</p>
<h3 id="equality-act-2010">Equality Act (2010)</h3>
<p>Regardless of whether the site is commercial or public sector, internal or external, they will all be subject to the <a href="https://www.legislation.gov.uk/ukpga/2010/15/contents">Equality Act 2010</a>:</p>
<blockquote>
<p>“all UK service providers must consider ‘reasonable adjustments’ for disabled people”</p>
</blockquote>
<p>The law requires providers to anticipate the needs of disabled customers, not just respond to issues raised by them.</p>
<h3 id="public-sector-equality-duty">Public Sector Equality Duty</h3>
<p>There is also the <a href="https://www.equalityhumanrights.com/guidance/public-sector-equality-duty-psed">Public Sector Equality Duty</a> which puts the onus on those orgnaisations to promote equality, find ways to avoid inequality within their organisations and publish policies which advance these aims.</p>
<h2 id="public-sector-legislation">Public Sector legislation</h2>
<p>To meet accessibility legislation for UK and European public sector services, meeting WCAG A/AA guidelines is the main step to show compliance. However involvement of users with in development of products and services is heavily encouraged.</p>
<h3 id="uk-public-sector-bodies-accessibility-regulations">UK: Public Sector Bodies Accessibility Regulations</h3>
<p>All websites and apps published by the Public Sector in the UK have to conform to the <a href="https://www.legislation.gov.uk/uksi/2018/952/made">Public Sector Bodies Accessibility Regulations 2018 (PSBAR)</a>. This adds more specific markers as to what is expected of providers in ensuring their sites are accessible.</p>
<p>This means that if you are working on a website, app or service which is published for use <em>internally or externally</em> you have to ensure it complies with the regulations.</p>
<p>Where we use ‘website’ from here as shorthand, this covers websites, apps, intranets, internal services etc. For example internal services which are used by internal staff come under this regulation just as much as an external service for the general public.</p>
<p>This also covers any services which have been funded by a public body, even if they are not built, hosted or managed by it. So if a government department procures a company to build a service it must be accessible.</p>
<p>Although we are primarily talking about the newer PSBAR requirements, websites are still subject to other regulations such as the Equality Act.</p>
<p>There have been cases where departments have been referred to the European Commission over failure to meet these regulations, so compliance is important as it can become a legal matter.</p>
<p>Whilst WCAG is often cited as the requirement for PSBAR, the legislation references EN 301 549 which as already mentioned goes beyond WCAG in some places.</p>
<h3 id="eu-directive-20162102">Europe: EU Directive 2016/2102</h3>
<p>The <a href="https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A32016L2102">EU Directive on the accessibility of websites and mobile applications of public sector bodies (2016/2102)</a>, also known as the <strong>European Web Accessibility Directive</strong> are the regulations which the UK’s PSBAR (see above) are harmonised to, so they are effectively the same. Just like PSBAR it is targeted at the public sector.</p>
<p>It references the European standard for digital accessiblity (EN 301 549, see above) which in turn references WCAG A/AA compliance amongst others. Member states undertake their own monitoring and have to submit reports to the European Commission.</p>
<h3 id="usa-section-508">USA: Section 508</h3>
<p><a href="https://www.section508.gov/">Section 508 of the Rehabilitation Act of 1973</a> requires federal agencies to make their electronic and information technology (EIT) accessible to people with disabilities.</p>
<p>It was updated in 2018 to incorporate conformance with WCAG but was written to reference the current version at the time which was WCAG 2.0 and hasn’t been updated since, which means Section 508 lags behind other legislation around the world.</p>
<h2 id="private-sector-legislation">Private Sector legislation</h2>
<p>In the private sector the US and UK rely on the wider discrimination legislation to hold companies to account. In Europe however legislation has been passed which covers specific sectors and brings them more in line with the public sector.</p>
<h3 id="europe-the-european-accessibility-act">Europe: The European Accessibility Act</h3>
<p>The <a href="https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A32019L0882">EU Directive on the accessibility requirements for products and services (2019/882)</a>, also known as the <strong>European Accessibility Act</strong>, is different from the two laws above in that it targets the private sector. Its primary aim is to establish a harmonised system across the trading block to ease trade between countries.</p>
<p>It covers a wide range of products and services and crucially includes both physical and digital aspects.</p>
<p>Just as with the European public sector directive, it also indicates EN 301 549 compliance as one way of meeting the requirements (but remember that the European legislation goes beyond WCAG in its scope):</p>
<blockquote>
<p>“Products and services which are in conformity with harmonised standards […] shall be presumed to be in conformity with the accessibility requirements of this Directive in so far as those standards or parts thereof cover those requirements … (Article 15 para 1)”</p>
</blockquote>
<h4>Service areas covered</h4>
<ul>
<li>electronic communications services</li>
<li>audiovisual media services</li>
<li>air, bus, rail and waterborne passenger transport services:
<ul>
<li>websites and mobile apps</li>
<li>electronic ticketing</li>
<li>transport service information</li>
<li>interactive self-service terminals</li>
</ul>
</li>
<li>consumer banking services</li>
<li>e-books and dedicated software</li>
<li>e-commerce services</li>
</ul>
<p>See Article 2 of the directive for a full list.</p>
<h4>Products covered</h4>
<ul>
<li>computers and operating systems</li>
<li>payment terminals</li>
<li>the following self-service terminals dedicated to the provision of services listed above:
<ul>
<li>ATMs</li>
<li>ticketing machines and check-in machines</li>
<li>interactive self-service terminals providing information</li>
</ul>
</li>
<li>consumer terminal equipment with interactive computing capability, used for electronic communications services (eg modem and router interfaces) or for accessing audiovisual media services</li>
<li>e-readers</li>
</ul>
<h4>Conformity</h4>
<p>Crucially the law requires conformity for all products being imported into the member states (as well as those marketed internally). So non-EU companies wishing to sell products within the EU will need to conform to these regulations.</p>
<blockquote>
<p>“When placing their products on the market, manufacturers shall ensure that the products have been designed and manufactured in accordance with the applicable accessibility requirements of this Directive.”
(Article 7 para 1)</p>
</blockquote>
<blockquote>
<p>“Importers shall place only compliant products on the market.”
(Article 9 para 1)</p>
</blockquote>
<blockquote>
<p>“Service providers shall ensure that they design and provide services in accordance with the accessibility requirements of this Directive.”
(Article 13 para 1)</p>
</blockquote>
<p>In addition to making sure products and services are compliant, manufacurers and suppliers must also document this and provide feedback mechanisms for users.</p>
<p>The member states have had several years in which to adopt and prepare. Member states can begin to apply the directive from <strong>28 June 2025</strong>. All member states must be enforcing the directive by 28 June 2027. There are some transition allowances - service contracts already in place before the 2025 deadline can continue until they expire or for 5 years (whichever is the least) and self-service terminals in use prior to the 2025 deadline can continue in use until they become uneconomical, for a maximum 20-year lifespan (see Article 13).</p>
<p>There are areas where the new legislation does not cover (for example domestic appliances, computers integrated into vehicles), but it is a major step forward.</p>
<h4>Current state of European accessibility</h4>
<p>A <a href="https://www.digitaltrustindex.eu/">2024 survey of 260,000 European website homepages</a> found that 94% fail automated accessibility checks. Most issues were found to be very simple fixes (although the caveat here is that simple issues are the only things that automated checks can find). Examples of issues found included:</p>
<ul>
<li>poor colour contrast</li>
<li>buttons and links missing text</li>
<li>links only identified by colour</li>
<li>missing alt text on images</li>
<li>missing page language definitions</li>
</ul>
<h4>Further reading</h4>
<ul>
<li><a href="https://www.youtube.com/watch?v=mmqWzWmEeR8">What is the European Accessibility Act? - TPGi on YouTube</a></li>
</ul>
<h2 id="examples-of-legal-enforcement">Examples of legal enforcement</h2>
<h3 id="student-loans-company">Student Loans Company</h3>
<p>A blind user was unable to complete an online form, so had to resort to filling it in over the phone. The court ruled in her favour and the Student Loans Company had to pay compensation and fix the issues.</p>
<p><a href="https://www.yorkpress.co.uk/news/19397457.blind-york-student-wins-5k-claim-inaccessible-loan-form/">Blind York student wins £5k claim over 'inaccessible' loan form</a></p>
<h3 id="department-forwork-and-pensions-dwp">Department for Work and Pensions (DWP)</h3>
<p>DWP failed to provide accessible documents to a blind user. The court ruled in his favour and DWP had to pay compensation and fix the issues.</p>
<p><a href="https://www.leighday.co.uk/news/news/2023-news/dwp-in-breach-of-equality-laws-after-failure-to-communicate-accessibly-with-blind-benefits-claimants/">DWP breached equality laws after failure to communicate accessibly with blind benefits claimants</a>  and <a href="https://www.bbc.co.uk/news/uk-england-london-66547199">'I brought a judicial review against the DWP and won £7,000'</a></p>
<h2 id="standards-and-legislation-are-the-baseline-not-the-target">Standards and legislation are the baseline, not the target</h2>
<p>It is important to remember that meeting the legal regulations mean that your product has only met the bare minimum for accessibility.</p>
<p>There is a great deal of difference between accessibility compliance and truly making a product accessible. Legislation needs a black-and-white way to signify compliance and for accessibility WCAG provides a set of criteria to test against. Accessibility release gates are often tied to meeting these legal requirements and so often by default WCAG A/AA compliance.</p>
<p>However even this can leave many users with a problematic experience. As with any specification there are use-cases which were not conceived of when writing, or which could not be transposed to a set of rules which could be robustly tested against.</p>
<p>So rather than use the WCAG guidelines as a target for your accessibility work, instead view it as a baseline and then build upon it.</p>
<h2 id="wrap-up">Wrap-up</h2>
<p>You should strive to go above and beyond the legal requirements, test with users with a wide range of abilities and backgrounds and ensure you are making your product as accessible as possible.</p>
<p>In other words - you met WCAG, well done, you have done the bare minimum for accessibility. Now how are you going to do better?</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Automated testing</title>
        <link href="https://liptrot.org/posts/automated-testing/"/>
        <updated>2024-06-27T13:00:00Z</updated>
        <id>https://liptrot.org/posts/automated-testing/</id>
        <content type="html"><![CDATA[
          <h2>Contents</h2>
<ul>
<li><a href="#contents">Contents</a></li>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#browser-plugins">Browser plugins</a></li>
<li><a href="#linters">Linters</a></li>
<li><a href="#unit-testing">Unit testing</a></li>
<li><a href="#site-wide-journey-testing">Site-wide journey testing</a></li>
<li><a href="#automated-tests-as-a-metric">Automated tests as a metric</a></li>
<li><a href="#the-misconception-about-automated-tests">The misconception about automated tests</a></li>
<li><a href="#enhancing-automated-tests">Enhancing automated tests</a></li>
<li><a href="#automating-screen-readers">Automating screen-readers</a></li>
<li><a href="#incorporating-automated-testing-into-a-workflow">Incorporating automated testing into a workflow</a></li>
<li><a href="#wrap-up">Wrap up</a></li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>Automated testing can be a valuable tool when it comes to testing for accessibility. The flexbility means they can be included in an existing workflow without too much disruption. By making considered adjustments to existing tests we can improve outcomes and provide greater assurance.</p>
<h2 id="browser-plugins">Browser plugins</h2>
<p>The first introduction most people have to automated accessibility tests is one of the many accessibility plugins for browsers.</p>
<p>This list is not exhaustive, but these are the most well-known ones with single-click checks:</p>
<ul>
<li><a href="https://www.deque.com/axe/browser-extensions">axe</a> - one of the most popular accessibility plugins, its axe-core ruleset forms the basis of some others such as Lighthouse. Axe-core also lends itself well to command-line testing as we will see.</li>
<li><a href="https://wave.webaim.org/extension/">Wave</a> - another well-known and possibly more starter-friendly than axe as it overlays the page with icons indicating where issues lie</li>
<li><a href="https://www.tpgi.com/arc-platform/arc-toolkit/">ARC Toolkit</a> - fast and effective, but its simplicity might suit more experienced users - has a good range of manual testing helpers</li>
<li><a href="https://www.ibm.com/able/toolkit/tools#develop">IBM Equal Access Accessibility Checker</a> - similar to axe this also adds some other options for viewing results, such as grouped by element or violation. This is also available as a node package for command-line usage.</li>
<li><a href="https://accessibilityinsights.io/downloads/">Accessibility Insights for Web</a> - primarily a guided test suite but does have a single-click test option  - has a good tab stop visualiser</li>
</ul>
<p>Some of these may have additional tools (often called “guided tests”), but these are normally used in manual testing. Here we are just looking at the part of the plugin where a suite of tests are run against a page with no input from the user.</p>
<h3>Report output</h3>
<p>These plugins all run on a single page and will generate a report detailing the failure, perhaps with a snippet of the offending code and suggestions for how to fix it.</p>
<figure>
    <img src="/assets/images/modules/automated-plugin.png" data-size="implicit" alt="Screenshot of an issue reported by axe. It shows the issue description, a link to more information, a snippet of html showing the issue location, suggestions of how to fix the issue and failure points such as WCAG criteria.">
    <figcaption>An issue reported by the axe plugin. Most plugins follow a similar reporting style.</figcaption>
</figure>
<p>There are differences in what each one reports as they are built on their own set of checks - especially when it comes to colour contrast. For this reason it can be helpful to use two different plugins to check the same subject.</p>
<h3>Are plugins useful?</h3>
<p>These plugins are all very easy to use, they are literally a push-button approach and are very visual. They generally also do a good job of highlighting the issue and providing additional information. As such they can be a good way to learn more about accessibility, especially WCAG.</p>
<p>Their simplicity is also part of the problem. They will only test the page in its current state and at the current viewport. Any interactions or parts of the page only exposed by interactions will not be tested.</p>
<p>They also only test for a small group of issues, primarily ones based on syntax use. Whilst this can be very valuable (as some of these can be difficult to spot otherwise), it does leave a lot of potential issues untested.</p>
<p>For example a plugin could tell you that a heading level has been skipped, but it cannot tell if the correct heading levels are being used to correctly relay content relationships.</p>
<p>Finally, as most plugins utilise their own set of custom rules, there can be variations in reporting.</p>
<p>These one-click reports are effectively linting the interface to find syntax issues (in fact as we'll see the same code is used in some linters). Just as you would not rely purely on a linter to check your application code we should not rely on accessibility linters to check for accessibility. We should always supplement these with additional manual checks.</p>
<p>Closer examination of most plugins will show that these one-click reports are only part of what they offer. Most will also have a suite of additional tools which assist with manual testing such as <a href="/posts/keyboard-accessibility/#logical-tab-order">keyboard tab order</a>.</p>
<h2 id="linters">Linters</h2>
<p>What is better than running some code in the browser only to find issues with a plugin? Finding those issues as you code. This is where linters come in. Some have their own set of rules (such as <a href="https://github.com/jsx-eslint/eslint-plugin-jsx-a11y">eslint-plugin-jsx-a11y</a>) whilst others leverage existing libraries such as <a href="https://github.com/dequelabs/axe-core">axe-core</a>.</p>
<figure>
    <img src="/assets/images/modules/automated-linter.png" data-size="implicit" alt="Screenshot of some rules for a linter, including tests for meaningful alt text, avoiding ambiguous anchor text such as 'click here' and ensuring anchors have accessible content.">
    <figcaption>A few example rules from the ESLint JSX linter.</figcaption>
</figure>
<p>These do have some limitations on what they can test - for example colour checks are often exempted - and depending on how your components are constructed they may have difficulties in making necessary associations.</p>
<h2 id="unit-testing">Unit testing</h2>
<p>We can run command-line compatible rulesets (like <a href="https://github.com/dequelabs/axe-core">axe-core</a> or <a href="https://github.com/IBMa/equal-access">IBM</a>) against individual components.</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// using Jest with axe-core</span>

<span class="token function">test</span><span class="token punctuation">(</span><span class="token string">"component passes automated accessibility checks"</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> <span class="token function-variable function">render</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">
        &lt;label>Name&lt;/label>
        &lt;input type="text" id="name" name="name">
        </span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> html <span class="token operator">=</span> <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// run the checker against our component</span>
    <span class="token comment">// assert that we don't get any violations back</span>
    <span class="token function">expect</span><span class="token punctuation">(</span><span class="token keyword">await</span> <span class="token function">axe</span><span class="token punctuation">(</span>html<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toHaveNoViolations</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p>This opens up the possibility for additional scripting, such as providing optional data or performing interaction before running the accessibility check.</p>
<h2 id="site-wide-journey-testing">Site-wide journey testing</h2>
<p>There are options to be able to run similar checks to the ones from browser plugins across multiple pages or entire sites. As mentioned most common is axe-core which is the rules engine which the axe browser plugin uses, but others such as <a href="https://github.com/pa11y/pa11y">Pa11y</a> are available.</p>
<p>These can be set to run as part of a continuous integration build step to provide some confidence in development.</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// using Playwright with axe-core</span>

<span class="token function">test</span><span class="token punctuation">(</span><span class="token string">"Pass automated tests"</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> page <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">await</span> page<span class="token punctuation">.</span><span class="token function">goto</span><span class="token punctuation">(</span><span class="token string">"http://www.example.com"</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
        <span class="token literal-property property">waitUntil</span><span class="token operator">:</span> <span class="token string">"domcontentloaded"</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// run the checker on the page</span>
    <span class="token keyword">const</span> a11yScan <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token keyword">new</span> <span class="token class-name">AxeBuilder</span><span class="token punctuation">(</span><span class="token punctuation">{</span>page<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">analyze</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// assert that we don't get any violations back</span>
    <span class="token function">expect</span><span class="token punctuation">(</span>a11yScan<span class="token punctuation">.</span>violations<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toEqual</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p>The results are rendered in the console but there is the potential to generate html reports. A similar level of detail to that provided by the browser plugins can be generated as the data is broadly the same.</p>
<figure>
    <img src="/assets/images/modules/automated-results.png" data-size="implicit" alt="Screenshot of a terminal log of issues. It states 6 accessibility violations were detected and then shows a table of issues with the count of issues for each row." />
    <figcaption>An example of results of a failed axe-core test reported by Cypress.</figcaption>
</figure>
<p>Whilst more involved than the browser plugin version to set-up, this is still a relatively simple implementation. As long as it is set up to run site-wide then it also provides a useful baseline asurance that any changes to one page or component have not had unwanted effects elsewhere.</p>
<p>With a little thought, interactions could be triggered in scripts prior to running the checks to provide more in-depth coverage.</p>
<p>However, as with the browser plugins these checks will still only ever find a subset of the issues. As with any automated checks, these are also only truly effective if they are reguarly monitored. Unless a failing test also fails the build or features in a strong definition of done, it is common for these tests to be set up and forgotten about.</p>
<h2 id="automated-tests-as-a-metric">Automated tests as a metric</h2>
<p>One of the most useful things about running automated tests as part of the pipeline is that they provide a measurable metric.</p>
<p>The easily-repeatable nature means they function well as a gauge for progress, especially with a remediation project where retrospective fixes are being addressed.</p>
<h2 id="the-misconception-about-automated-tests">The misconception about automated tests</h2>
<p>There is something of a misconception that if automated tests are run against a site, page or component and a pass is signalled, that this means the item is accessible. This is not the case.</p>
<p>A clear pass only means that the automated checks did not find any failures against the limited set of rules it tests against.</p>
<p><strong>It is not telling you everything is ok.</strong></p>
<p>It is very possible for the subject to pass automated tests whilst still failing the user and being inaccessible. This is why we still need to build manual testing into our test strategies.</p>
<p>With that said, automated tests form an important part of our toolkit and are a useful baseline and warning against potential regression.</p>
<p><a href="/posts/testing-strategies-and-accessibility/">Read more about testing strategies and accessibility</a></p>
<h2 id="enhancing-automated-tests">Enhancing automated tests</h2>
<p>So we know that library-style accessibility checkers are good for capturing some issues, but what are the gaps we need to think about filling when we are adding custom scripts to our tests?</p>
<p>Some areas to consider are:</p>
<ol>
<li>Semantic structures</li>
<li>Keyboard access</li>
<li>Reflow</li>
<li>Interaction and state</li>
</ol>
<h3>Enforcing semantic structures</h3>
<p>Semantics are essential for good accessibility as they form the basis of good screen-reader experiences. However they can often be missed as their lack of presence can be masked by visual styles.</p>
<figure>
    <img src="/assets/images/modules/automated-semantics.png" data-size="implicit" alt="Screenshot of a component showing a category title with 4 articles below. The maicategory title os larger and visually it groups the articles. Another screenshot shows the main title has the same heading level as the articles." />
    <figcaption>Visually a heading can suggest a hierarchy of relationships between items - here shown by the larger text size used for the main heading. But the information provided to screen-reader users does not match this and changes the meaning. Hierarchy displayed using <a href="https://chromewebstore.google.com/detail/headingsmap/flbjommegcjonpdmenkdiocclhjacmbi">HeadingsMap extension</a></figcaption>
</figure>
<p>But we can improve this as part of our tests without often having to generate specific tests by making our selectors do the hard work.</p>
<p>Instead of using ID attributes to locate elements we can look for accessible hooks to assert-as-we-go. These can include element roles, accessible names or state information such as <code>aria-expanded</code>.</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// using Playwright</span>
<span class="token comment">// get button with accessible name of "login" and aria-expanded=false</span>
<span class="token keyword">await</span> page<span class="token punctuation">.</span><span class="token function">getByRole</span><span class="token punctuation">(</span><span class="token string">'button'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">"login"</span><span class="token punctuation">,</span> <span class="token literal-property property">expanded</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<pre class="language-js"><code class="language-js"><span class="token comment">// using Playwright</span>
<span class="token comment">// get h2 with accessible name of "conditions"</span>
<span class="token keyword">await</span> page<span class="token punctuation">.</span><span class="token function">getByRole</span><span class="token punctuation">(</span><span class="token string">'heading'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token literal-property property">level</span><span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">"Conditions"</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p>This type of declarative test makes this a really good fit for TDD (test-driven development) as it enforces good accessiblity practice before any code has been written.</p>
<h3 id="enforcing-good-keyboard-accessibility">Enforcing good keyboard accessibility</h3>
<p>It can be all too easy to test a component as we might access it ourselves and not think about other ways it might need to be accessed. For example keyboard access tends to get ignored as most developers use mouse-based navigation. But making sure our components are actionable with just a keyboard is an essential part of accessibility practice.</p>
<p>Ignoring keyboard accessibility is all too common and is easy to see the evidence when looking at various commerical websites.</p>
<figure>
    <img src="/assets/images/modules/automated-keyboard.png" data-size="implicit" alt="Screenshot of a hotel booking page. A carousel has items inside relating to dates and associated cost for a hotel room for the user to pick from. An overlay shows keyboard focus will skip over the items in the carousel, making them unselectable." />
    <figcaption>Not considering keyboard users, as on this Thomas Cook page, means they can be left without crucial functionality. Here the tab order jumps over the items in the carousel and the user is unable to choose a different date and price for their trip. Keyboard overlay shown is from <a href="https://chromewebstore.google.com/detail/ibm-equal-access-accessib/lkcagbfjnkomcinoddgooolagloogehp">IBM Accessibility Assessment extension</a></figcaption>
</figure>
<p>Most of the action and locator events in test scripts act as mouse users - for example moving directly to a control and clicking it. This will not provide us with any assurance that a keyboard-only user can access the same item.</p>
<p>We need to write tests to check that the keyboard user:</p>
<ol>
<li>can access the control</li>
<li>accesses the control in a logical order (for example the previous focusable element was the one expected)</li>
<li>can action the control</li>
</ol>
<p>Let's write an example test for the above situation.</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// using Playwright</span>

<span class="token function">test</span><span class="token punctuation">(</span><span class="token string">'user can access carousel items'</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> page <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token comment">// use accessible selectors to get the left-hand carousel button</span>
    <span class="token keyword">const</span> carouselPrev <span class="token operator">=</span> page<span class="token punctuation">.</span><span class="token function">getByRole</span><span class="token punctuation">(</span><span class="token string">'button'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'previous'</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    
    <span class="token comment">// grab the first carousel item</span>
    <span class="token comment">// using an ID as the content is dynamic (we could improve this)</span>
    <span class="token keyword">const</span> firstDeal <span class="token operator">=</span> page<span class="token punctuation">.</span><span class="token function">getByTestId</span><span class="token punctuation">(</span><span class="token string">'first-deal-item'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    
    <span class="token comment">// focus on the carousel button</span>
    carouselPrev<span class="token punctuation">.</span><span class="token function">focus</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    
    <span class="token comment">// use the tab key to move</span>
    <span class="token keyword">await</span> page<span class="token punctuation">.</span>keyboard<span class="token punctuation">.</span><span class="token function">press</span><span class="token punctuation">(</span><span class="token string">'Tab'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    
    <span class="token comment">// assert that the first carousel item has gained focus</span>
    <span class="token keyword">await</span> <span class="token function">expect</span><span class="token punctuation">(</span>firstDeal<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toBeFocused</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token comment">// activate the carousel item using a key command</span>
    <span class="token keyword">await</span> page<span class="token punctuation">.</span>keyboard<span class="token punctuation">.</span><span class="token function">press</span><span class="token punctuation">(</span><span class="token string">'Enter'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token comment">//then we can assert that the page has updated as normal</span>
    <span class="token operator">...</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p>Whilst this might not be something which you would probably want to do for normal content, it would be beneficial for any complex components or ones which involve interaction. It is here where mouse event listeners are most often employed at the expense of keyboard users.</p>
<h3>Reflow</h3>
<p>Reflow is not something which it is easy to generate TDD scripts for, but it is something which can have regression tests written to prevent issues appearing.</p>
<p>Reflow issues often occur when the content overflows either the viewport or its parent container. This can be due to:</p>
<ul>
<li>text size increases by the user which haven't been handled</li>
<li>viewport size changes, such as moving from dektop to mobile</li>
<li>changing viewport orientation, such as mobile being viewed in landscape rather than portrait mode</li>
</ul>
<p>In these situations content can either sit off-screen (albeit sometimes readable by scrolling the screen) or can be cut off so it is entirely unreadable.</p>
<figure>
    <img src="/assets/images/modules/automated-reflow.png" alt="Screenshots of a driver page on Forumula E. The first screenshot has the page in mobile portrait mode and shows the driver first name above their second name. The second screenshot has the page in landscape mode and the first name has been entirely cut off." data-size="implicit" />
    <figcaption>Orientation change can often expose weaknesses in how a design has been coded. Often this is caused by hard-coded heights on containers such as in this example which caused content to be cut-off.</figcaption>
</figure>
<p>Reflow really needs to be manually tested as some of the triggers are not available to scripts (such as text-size or spacing increase), but we can add some automated tests to help us catch some regressions once we have a well-tested base.</p>
<p>By using visual regression testing we can take screenshots of each page at different viewport sizes. Then when making updates new screenshots are taken and compared to the 'good' originals. This could help isolate any overflow issues.</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// Using Cypress</span>
<span class="token keyword">const</span> baseUrl <span class="token operator">=</span> <span class="token string">"https://liptrot.org"</span><span class="token punctuation">;</span>
<span class="token comment">// determine screen sizes to test</span>
<span class="token keyword">const</span> sizes <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token number">390</span><span class="token punctuation">,</span> <span class="token number">844</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">1024</span><span class="token punctuation">,</span> <span class="token number">1366</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">1024</span><span class="token punctuation">,</span> <span class="token number">600</span><span class="token punctuation">]</span><span class="token punctuation">]</span>
<span class="token comment">// list of pages to run against</span>
<span class="token keyword">const</span> pages <span class="token operator">=</span> <span class="token punctuation">[</span>
  <span class="token punctuation">{</span><span class="token literal-property property">url</span><span class="token operator">:</span><span class="token string">"/"</span><span class="token punctuation">,</span><span class="token literal-property property">name</span><span class="token operator">:</span><span class="token string">"home"</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">{</span><span class="token literal-property property">url</span><span class="token operator">:</span> <span class="token string">"/guides"</span><span class="token punctuation">,</span> <span class="token literal-property property">name</span><span class="token operator">:</span><span class="token string">"guides"</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">{</span><span class="token literal-property property">url</span><span class="token operator">:</span> <span class="token string">"/posts/accessible-names/"</span><span class="token punctuation">,</span> <span class="token literal-property property">name</span><span class="token operator">:</span><span class="token string">"blog-accessible-names"</span><span class="token punctuation">}</span>
<span class="token punctuation">]</span>
<span class="token comment">// loop through each page and size and take a screenshot</span>
sizes<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">size</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  <span class="token function">describe</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">On </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>size<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> screen</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    pages<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">page</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token function">it</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Render </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>page<span class="token punctuation">.</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>Cypress<span class="token punctuation">.</span>_<span class="token punctuation">.</span><span class="token function">isArray</span><span class="token punctuation">(</span>size<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          cy<span class="token punctuation">.</span><span class="token function">viewport</span><span class="token punctuation">(</span>size<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> size<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
          cy<span class="token punctuation">.</span><span class="token function">viewport</span><span class="token punctuation">(</span>size<span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
        cy<span class="token punctuation">.</span><span class="token function">visit</span><span class="token punctuation">(</span>siteUrl <span class="token operator">+</span> page<span class="token punctuation">.</span>url<span class="token punctuation">)</span>
        <span class="token comment">// compare the new screenshot against the one held as the 'good' version</span>
        cy<span class="token punctuation">.</span><span class="token function">compareSnapshot</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>page<span class="token punctuation">.</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>size<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre>
<figure>
    <img src="/assets/images/modules/automated-diff.png" alt="Three screenshots of the same page. The first and last have slight differences with the image overflowing the viewport on the last. The middle screenshot shows the difference between the two and highlights it in red." data-size="implicit" />
    <figcaption>Visual regression testing can help spot reflow issues, such as an image overflowing the viewport.</figcaption>
</figure>
<h3>State tests</h3>
<p>As we have already seen we can use thoughtful locator queries to assist in enforcing good accessible markup and these included using state information such as <code>aria-expanded</code>.</p>
<p>As these state attributes form the basis of important announcements to screen-readers, we should also check that they are being updated correctly.</p>
<p>We want to be particuarly mindful of attributes or content which get updated as the user interacts. These can include:</p>
<ul>
<li><code>aria-pressed</code></li>
<li><code>aria-expanded</code></li>
<li><code>aria-valid</code></li>
<li><code>aria-live</code> region content</li>
</ul>
<pre class="language-js"><code class="language-js"><span class="token function">test</span><span class="token punctuation">(</span><span class="token string">'open account menu actions'</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> page <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token comment">// get the button - checking the attribute is set to false</span>
    <span class="token keyword">const</span> logInButton <span class="token operator">=</span> page<span class="token punctuation">.</span><span class="token function">getByRole</span><span class="token punctuation">(</span><span class="token string">'button'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'login'</span><span class="token punctuation">,</span> <span class="token literal-property property">expanded</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">await</span> logInButton<span class="token punctuation">.</span><span class="token function">press</span><span class="token punctuation">(</span><span class="token string">'Enter'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">const</span> accountMenu <span class="token operator">=</span> page<span class="token punctuation">.</span><span class="token function">locator</span><span class="token punctuation">(</span><span class="token string">'#account-menu'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> accountMenuClose <span class="token operator">=</span> page<span class="token punctuation">.</span><span class="token function">locator</span><span class="token punctuation">(</span><span class="token string">'#account-menu-close'</span><span class="token punctuation">)</span>

    <span class="token comment">// check menu is visible</span>
    <span class="token keyword">await</span> expect<span class="token punctuation">.</span><span class="token function">soft</span><span class="token punctuation">(</span>accountMenu<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toBeVisible</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>               
    <span class="token comment">// check button aria attribute has updated</span>
    <span class="token keyword">await</span> expect<span class="token punctuation">.</span><span class="token function">soft</span><span class="token punctuation">(</span>logInButton<span class="token punctuation">.</span><span class="token function">toHaveAttribute</span><span class="token punctuation">(</span><span class="token string">'aria-expanded'</span><span class="token punctuation">,</span><span class="token string">'true'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>               
    <span class="token comment">// check close button in dialog is focused</span>
    <span class="token keyword">await</span> expect<span class="token punctuation">.</span><span class="token function">soft</span><span class="token punctuation">(</span>accountMenuClose<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toBeFocused</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<h2 id="automating-screen-readers">Automating screen-readers</h2>
<p>How about automating screen-readers directly? Well this can be done but as you will need a screen-reader installed it is unlikely something which would be achievable on a CI server.</p>
<p>There is a library called <a href="https://github.com/guidepup/guidepup">Guidepup</a> which presents a bridge between Playwright and two screen-readers (NVDA and Voiceover).</p>
<p>I found that there were issues in getting the tests to run quickly and reliably, but it is certainly an area which is interesting and would be ideal for TDD.</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// using Playwright and Guidepup with Voiceover</span>
<span class="token function">test</span><span class="token punctuation">(</span><span class="token string">"I can navigate the tables page"</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> page<span class="token punctuation">,</span> voiceOver <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>

    <span class="token keyword">await</span> page<span class="token punctuation">.</span><span class="token function">goto</span><span class="token punctuation">(</span><span class="token string">"http://liptrot.org/guides/vo-macos/tables/"</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">waitUntil</span><span class="token operator">:</span> <span class="token string">"domcontentloaded"</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">const</span> header <span class="token operator">=</span> <span class="token keyword">await</span> page<span class="token punctuation">.</span><span class="token function">locator</span><span class="token punctuation">(</span><span class="token string">'header'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">await</span> <span class="token function">expect</span><span class="token punctuation">(</span>header<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toBeVisible</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// start interacting with the page</span>
    <span class="token keyword">await</span> voiceOver<span class="token punctuation">.</span><span class="token function">interact</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// jump to the next table (equivalent to VO + t command)</span>
    <span class="token keyword">await</span> voiceOver<span class="token punctuation">.</span><span class="token function">perform</span><span class="token punctuation">(</span>voiceOver<span class="token punctuation">.</span>keyboardCommands<span class="token punctuation">.</span>findNextTable<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">await</span> <span class="token function">delay</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// next table</span>
    <span class="token keyword">await</span> voiceOver<span class="token punctuation">.</span><span class="token function">perform</span><span class="token punctuation">(</span>voiceOver<span class="token punctuation">.</span>keyboardCommands<span class="token punctuation">.</span>findNextTable<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// grab the last spoken announcement from VO</span>
    <span class="token keyword">const</span> tableAnnouncement <span class="token operator">=</span> <span class="token keyword">await</span> voiceOver<span class="token punctuation">.</span><span class="token function">lastSpokenPhrase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// assert it contains the table caption</span>
    <span class="token function">expect</span><span class="token punctuation">(</span>tableAnnouncement<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toContain</span><span class="token punctuation">(</span><span class="token string">'Dates and amounts'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<h3>Automating virtual screen-readers</h3>
<p>An alternative to using real screen-readers is using a set of rules which follows how you would expect a screen-reader to act, by the specifications. For example, if you jump to an input you would expect the input's accessible name (eg the label) and accessible description to be announced.</p>
<p>This has the advantage of not being reliant on a screen-reader being installed and so can be run on a CI server.</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// using Jest and Guidepup</span>
<span class="token function">test</span><span class="token punctuation">(</span><span class="token string">"should navigate to the input and announce the label and hint"</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    document<span class="token punctuation">.</span>body<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">
    &lt;form>
        &lt;label for="ref">What is your reference?&lt;/label>
        &lt;div class="hint" id="ref-hint">This is 10 characters.&lt;/div>
        &lt;input type="text" name="ref" id="ref" aria-describedby="ref-hint" />
        &lt;button>Save&lt;/button>
    &lt;/form>
    </span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>

    <span class="token keyword">await</span> virtual<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token literal-property property">container</span><span class="token operator">:</span> document<span class="token punctuation">.</span>body <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token comment">// Move to form</span>
    <span class="token keyword">await</span> virtual<span class="token punctuation">.</span><span class="token function">perform</span><span class="token punctuation">(</span>virtual<span class="token punctuation">.</span>commands<span class="token punctuation">.</span>moveToNextForm<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// Move to the input</span>
    <span class="token keyword">await</span> virtual<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">await</span> virtual<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">await</span> virtual<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// grab the last spoken announcement</span>
    <span class="token keyword">const</span> lastSpokenPhrase <span class="token operator">=</span> <span class="token keyword">await</span> virtual<span class="token punctuation">.</span><span class="token function">lastSpokenPhrase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// check it contains the accessible name expected ...</span>
    <span class="token function">expect</span><span class="token punctuation">(</span>lastSpokenPhrase<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toContain</span><span class="token punctuation">(</span><span class="token string">"What is your reference?"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// ... and the accessible description expected</span>
    <span class="token function">expect</span><span class="token punctuation">(</span>lastSpokenPhrase<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toContain</span><span class="token punctuation">(</span><span class="token string">"This is 10 characters"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">await</span> virtual<span class="token punctuation">.</span><span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p>Whilst this follows what the specifications say should happen, if you have done any screen-reader testing yourself you will know that screen-reader support often lags behind the specs, or screen-readers diverge from the specs to improve usability for their users.</p>
<p>For example with NVDA, moving through the content it will not announce the hint as above to avoid repetition, but if you jump directly to the input it will (as you have not already heard it).</p>
<p>So as with all our automated tests, this is another tool, but must not replace testing with actual screen-readers.</p>
<h2 id="incorporating-automated-testing-into-a-workflow">Incorporating automated testing into a workflow</h2>
<p>Automated tests at their most basic out-of-the-box are relatively simple to introduce into an existing workflow and can be supplemented with some more thoughtful managed test scripts and practices:</p>
<ul>
<li>use browser plugins to check HTML prototypes for potential issues before writing the development team ticket, use the output to prompt questions</li>
<li>use TDD to enforce accessibility best practice</li>
<li>encourage the use of linters added to code editors to catch issues as the code is written</li>
<li>run a browser plugin against any work which touches the user interface before the code is committed</li>
<li>encourage code reviews to run browser plugins against pull requests</li>
<li>add automated checks to unit tests and journey tests</li>
<li>enhance journey tests with accessibility-focussed checks customised to the interface</li>
</ul>
<p>Each of these can be written into a definition of ready or definition of done to help embed the practice.</p>
<p>Read more about <a href="/posts/team-process-and-role-based-accessibility/">team processes</a> and <a href="/posts/testing-strategies-and-accessibility/">testing strategies</a>.</p>
<p>As with any kind of test, accessibility tests are only effective if the output is monitored, reviewed and acted upon. There is no point adding automated checks to a pipeline if no-one ever looks at the results of each run.</p>
<h2 id="wrap-up">Wrap up</h2>
<p>There are a lot of options we can employ when looking at improving automated accessibility testing, using out-of-the-box solutions is only the first step.</p>
<p>By considering all our users we can put in additional tests to improve the accessibility of our codebase.</p>
<p>Accessibility testing must not stop at automation, no matter how sophisticated it is. Manual testing is essential, but what automation testing does give us is a baseline. This baseline means that manual testing should be more effective and less time-consuming and noisy as a result.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>The accessibilty tree and assistive technology</title>
        <link href="https://liptrot.org/posts/accessibility-tree-and-assistive-technology/"/>
        <updated>2024-06-21T13:00:00Z</updated>
        <id>https://liptrot.org/posts/accessibility-tree-and-assistive-technology/</id>
        <content type="html"><![CDATA[
          <h2>Contents</h2>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#the-document-object-model">The Document Object Model</a></li>
<li><a href="#the-accessibility-tree">The Accessibility Tree</a></li>
<li><a href="#viewing-the-accessibility-tree">Viewing the accessibility tree</a></li>
<li><a href="#what-is-not-included-in-the-tree">What is not included in the tree</a></li>
<li><a href="#the-impact-of-css">The impact of CSS</a></li>
<li><a href="#accessibility-apis">Accessibility APIs</a></li>
<li><a href="#where-differences-start-to-appear">Where differences start to appear</a></li>
<li><a href="#wrap-up">Wrap-up</a></li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>You might have heard a screen-reader reading through a page and providing a lot of extra information to the user, other than what is visible. This information is important to convey information which a user who can see the screen might infer from the visual display, but which a screen-reader user who relies purely on the audible cues might miss - for example “how many items are in this list and which item am I on?”.</p>
<p>So where is it getting this information from?</p>
<h2 id="the-document-object-model">The Document Object Model</h2>
<p>When the browser renders the page it generates the Document Object Model, or DOM.</p>
<p>The DOM is a representation of the page as a set of nodes for each element and you may have seen a visualisation of this in the Elements and Properties panels of your browser developer tools.</p>
<figure>
<img src="/assets/images/modules/api-dom.png" data-size="implicit" alt="A webpage with developer tools open showing the Elements panel with the HTML and the Properties panel with the details of the selected node."/>
<figcaption>Viewing the DOM in the browser</figcaption>
</figure>
<p>So an HTML page with  a button:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">></span></span>DOM<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span><span class="token punctuation">></span></span>Save and continue<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">></span></span>
</code></pre>
<p>Will be represented by this DOM:</p>
<pre class="language-html"><code class="language-html">Document
  HTML
    Head
      Title
        "DOM"
    Body
      Button
        "Save and continue"
</code></pre>
<p>When the browser creates the DOM, it also generates a version of it called the <strong>Accessibility Tree</strong>.</p>
<h2 id="the-accessibility-tree">The Accessibility Tree</h2>
<p>The Accessibility Tree provides specific information which is of use to assistive technology such as screen-readers. The two main pieces of information are the item's <strong>Name</strong> and its <strong>Role</strong>.</p>
<h3>Name</h3>
<p>More accurately &quot;accessible name&quot;, this is way the user will interact with the element. For a screen-reader this is announced; for a speech-recognition user this is the thing they will need to say to interact with the item.</p>
<p>At its simplest it is the text contents of the element. The accessible name of the link below is &quot;Bob&quot;:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>...<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Bob<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p>So this will be announced as <em>&quot;Bob, link&quot;</em> to a screen-reader, and a speech-recognition user may say <em>&quot;Click Bob&quot;</em> to activate the link.</p>
<p>Accessible names can come from sources other than just content. For example:</p>
<ul>
<li>an image's accessible name is generally its <code>alt</code> attribute</li>
<li>a form input's accessible name normally comes from it's associated <code>label</code></li>
</ul>
<p><a href="/posts/accessible-names/">Read more about accessible names</a></p>
<h3>Role</h3>
<p>A role is the function of that element. Many HTML elements have implicit roles, for example an <code>a</code> element has a role of &quot;link&quot; and a <code>nav</code> element has a role of &quot;navigation&quot;. For screen-reader users this is announced along with the accessible name to give the user an idea of what the purpose of the item is and perhaps what interactions may be possible.</p>
<p>For example, if we just created a button with a <code>div</code> and some javascript click handlers:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">></span></span>Continue<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
</code></pre>
<p>This would only be announced to a screen-reader user as plain text:</p>
<blockquote>
<p>“Continue”</p>
</blockquote>
<p>The user has no indication that this is clickable beyond the contained text. But if we use the correct element (and therefore the correct <code>role</code>):</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span><span class="token punctuation">></span></span>Continue<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<p>Then as well as saving ourselves the effort of writing extra javascript, our screen-reader user now knows it is a button which can be clicked:</p>
<blockquote>
<p>“Continue, button”</p>
</blockquote>
<h3>Other properties</h3>
<p>There are other accessibility properties which give more information, such as state - is the button focussed or not, is the drop-down expanded or not, and so on. These are passed along in the accessibility tree.</p>
<p>The presence of these properties will depend on the particular type of element. Some HTML elements have implicit states. For example a checkbox input can have a &quot;selected/checked&quot; state.</p>
<p>ARIA allows us to expand on these implicit states where HTML does not have equivalents:</p>
<ul>
<li><code>aria-posinset</code> - gives the position of an element within a set of elements</li>
<li><code>aria-pressed</code> - lets the user know the element is in a pressed state</li>
<li><code>aria-expanded</code> - lets the user know the element is in an expanded state</li>
<li><code>aria-describedby</code> - creates a relationship with other elements to provide more information</li>
<li><code>aria-autocomplete</code> - on an <code>input</code> this tells the browser it might be able to be filled from stored data</li>
</ul>
<p>This helps ensure a user who cannot see the interface gets the same information which would otherwise only be presented visually.</p>
<p><a href="/posts/aria/">Read more about ARIA</a></p>
<div class="note note--activity">
<h3>Putting it all together</h3>
<p>In the image below we have an <code>h1</code> highlighted. We can see from the developer tools that its accessible name is taken from the the text inside the heading. It also has a role of “heading” and a level of “1” both which come from the element (an <code>h1</code> - an <code>h2</code> heading would present as a &quot;level 2&quot;).</p>
<img src="/assets/images/modules/api-role.png" data-size="intrinsic" alt="A website page h1 shown in Chrome developer tools. The h1 text is shown as the accessible name and the role is shown as heading. There is also a level property which is shown as level 1.">
<p>To a screen-reader this is announced as:</p>
<blockquote>
<p>“Cowell named Aston Martin team principal, heading, level 1”</p>
</blockquote>
<p>As you can see, the name, role and other properties help the screen-reader user build a picture of the structure of the content. This also demonstrates the importance of good semantic HTML.</p>
</div>
<h2 id="viewing-the-accessibility-tree">Viewing the accessibility tree</h2>
<p>So how do we see this accessibility tree? In Chrome and Firefox this is part of the developer tools under the accessibility panel.</p>
<figure>
<img src="/assets/images/modules/api-viewing2.png" data-size="implicit" alt="Chrome developer tools showing only the part of the accessibility tree which relates to the current item in the elements panel"/>
<figcaption>In Chrome developer tools by default the accessibility tree is only shown as a snippet based on the currently selected element in the elements panel.</figcaption>
</figure>
<figure>
<img src="/assets/images/modules/api-viewing.png" data-size="implicit" alt="Chrome developer tools showing the accessibility tree in place of the elements panel"/>
<figcaption>In Chrome developer tools you can also enable a full-page accessibility tree which replaces the normal elements view and allows you to explore the entire page.</figcaption>
</figure>
<p>In both browsers you will see the tree represented as a tree-view of <strong>roles</strong> and <strong>accessible names</strong> (along with some other properties where assigned) like this:</p>
<pre class="language-html"><code class="language-html">main
  heading "Viewing the accessibility tree"
    StaticText "Viewing the accessibility tree"
    paragraph
      StaticText "So how do we see this ..."
    figure
      image "Chrome developer tools ..."

</code></pre>
<p>&quot;StaticText&quot; just refers to plain text. You can see how the text which sits inside the heading provides the accessible name for that heading, as does the <code>alt</code> text for the image. You can also see how a paragraph does not generate an accessible name, but the plain text will still be passed along.</p>
<p>So with this set of data we can begin to build a picture of this element and how it will be communicated.</p>
<h2 id="what-is-not-included-in-the-tree">What is not included in the tree</h2>
<p>When you examine the Accessibility Tree you may notice that when compared to the DOM there is a lot of “structure” missing from the page.</p>
<figure>
<img src="/assets/images/modules/api-dom-tree.png" data-size="implicit" alt="Two developer tool panels open comparing the same section of page in the DOM and the Accessibility Tree. A lot of the structure has been removed, making the Accessibility Tree view much simpler. Some elements are marked as Ignored by the tree."/>
<figcaption>Comparing the same group of elements in the DOM and the Accessibility Tree. You can see a lot of information is discarded before it reaches the assistive technology.</figcaption>
</figure>
<p>A lot of this is attributes which are ignored (unless they affect how the element is exposed), but there are also whole elements which are not included.</p>
<p>You will see these marked as “Ignored” (in Chrome) or just not even represented at all (in Firefox). This is because only those elements which have meaning for assistive technology will be carried over from the DOM to the Accessibility Tree. For example a <code>div</code> has no meaning to a screen-reader so won’t make it, although its contents may.</p>
<figure>
<img src="/assets/images/modules/api-tree.png" data-size="implicit" alt="A web page with developer tools open on the Elements panel. Full Accessibility Tree view has been selected to show the tree representation of the page."/>
<figcaption>Viewing the Accessibility Tree in a browser - you can see "Ignored" and "Generic" (likely a `div`) items which will not be sent along to assistive technology.</figcaption>
</figure>
<p>This is where mis-use of ARIA can be a problem. For example, assigning a <code>role=&quot;presentation&quot;</code> to a <code>button</code> will change how it is exposed to the accessibility tree.</p>
<h2 id="the-impact-of-css">The impact of CSS</h2>
<p>Something else to bear in mind is that CSS can also play a part. If you have an element like a button which would normally be included, but it has CSS applied such as <code>display: none</code>, then that will remove it from the Accessibility Tree, as the CSS makes it invisible to assistive technology.</p>
<h2 id="accessibiliy-apis">Accessibility APIs</h2>
<p>So do assistive technologies like screen-readers just reach into the browser and grab this data? Well, no. Each OS will utilise a particular Accessibility API to act as an interface to the assistive technology.</p>
<p>There are several Accessibility APIs and the particular one will vary based on the operating system being used and even the browser.</p>
<p>These are some of the APIs:</p>
<ul>
<li>MSAA/IAccessible and IAccessible2 on Windows</li>
<li>NSAccessibility on OS X</li>
<li>UIAccessibility on iOS</li>
</ul>
<p>So we can now see how the end-to-end chain of custody of our element’s properties is created. The browser generates the DOM which is used to build the Accessibility Tree, which is used by one of the Accessibility APIs to pass the information onto the assistive technology.</p>
<figure>
<img src="/assets/images/modules/api-flow.png" data-size="implicit" alt="A diagram showing the flow of data from the DOM tree to the Accessibility Tree, to the Accessibility API, to the assistive technology"/>
<figcaption>The flow of information from the browser to the user</figcaption>
</figure>
<h2 id="where-differences-start-to-appear">Where differences start to appear</h2>
<p>These connections all means that there are several places where slight differences in interpretation can start to creep in.</p>
<ol>
<li>The browser engines are making decisions in how they translate the DOM into the Accessibility Tree.</li>
<li>The different APIs may offer varying levels of support for things like ARIA attributes.</li>
<li>Different assistive technology will also have variances in support for features like ARIA.</li>
<li>Different releases of OS, browers and assistive technology can also introduce support for features or in some cases change or break support.</li>
<li>To further complicate matters, browsers or assistive technology may also add in their own heuristics to make things better for their own users.</li>
</ol>
<h3>Screen-reader and browser heuristics</h3>
<p>Sometimes rules are added to help users. Often this is in an effort to fix experiences broken by developers, but this can confuse developers who might not expect certain behaviour and think there is a bug.</p>
<p>Here are a few examples of how these have come about:</p>
<h4>Lists in WebKit</h4>
<p>If you create an unordered list in HTML (using <code>ul</code>), but then remove the visual indicators (the dots or similar next to each list item), then WebKit will no longer see that as a list and so an identification of this as a list will not be passed along to the Accessibility API.</p>
<p>This was done a few years back in response to developers jumping on “semantic markup” and suddenly seeing everything as lists. Got a bunch of navigation links? Must be a list. Got a group of blog posts? Must be a list. Suddenly everything seemed to be a list and this was getting passed along to screen-reader users. If you have ever listened to how a list is communicated to a screen-reader, then you will understand why this massive increase in informational noise led to VoiceOver users bombarding Apple asking them to do something.</p>
<p>The result was that they added a rule that if something doesn’t actually look like a list to a visual user, then there is no reason for a screen-reader user to be told it is a list, even if the developer marked it up as one.</p>
<p>So now if you <em>really</em> want something to be announced as a list (think about this first) and it doesn't look like a list, then you need to add a (redundant) <code>role</code> which will push it through:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ul</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>list<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span>...
</code></pre>
<h4>Tables</h4>
<p>Tables are another place where browser engines have rules to check if they consider the table is being used as a layout tool rather than an actual table, although the rules are far from perfect. But the misuse of tables was so great that they had to try.</p>
<p>WebKit has a set of rules to help it determine if a table is one which should be exposed as such to assistive technology. These checks including looking at the number of rows, if it has cell-spacing, if it has correct markup, even if it has zebra-striping applied.</p>
<h4>Labels and JAWS and VoiceOver</h4>
<p>Screen-readers also exhibit this style of heuristic behaviour. Take the below html as an example:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span><span class="token punctuation">></span></span>Your email<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>email<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>email<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
</code></pre>
<p>The <code>input</code> here has no accessible name - the <code>label</code> is missing a <code>for</code> attribute to connect the two together.</p>
<p>By the spec the <code>input</code> will be announced as &quot;Edit text&quot; to a screen-reader.</p>
<p>However if JAWS or VoiceOver encounters a field like this then it looks to see if there is any text immediately before the input (in the source code order). If there is, then it gambles that this is most likely the intended label text (regardless if it is marked up with a label tag or not, because developers don’t always do good jobs), and assigns it to the input.</p>
<p>If the text doesn’t happen to be the label text (for example there is a hint between the two) then this can be confusing, but it probably helps more users than it confuses.</p>
<p>Note this kind of heuristic can also be misleading when testing - the example above would sound ok with JAWS and VoiceOver because of this behaviour, but would be broken in other screen-readers. This is a reason we need to test with multiple screen-readers as well as checking the code.</p>
<h2 id="wrap-up">Wrap-up</h2>
<p>Getting the information from the browser to the user in an efficient way means it passes through several steps before the user receives it. Whilst this has massive benefits for the user it can mean that there is sometimes inconsistency due to differing levels of support (or even imposed user-protection) in either the browser, API or assistive technology.</p>
<p>However, understanding how changes to the markup affect this chain of custody makes for a better end product.</p>

        ]]></content>
      </entry>
    
	
    
	
    
	
    
	
    
	
    
	
    
	
    
	
    
	
    
	
    
	
    
      
      <entry>
        <title>Windows High Contrast (WHC) and ARIA</title>
        <link href="https://liptrot.org/posts/whc_aria/"/>
        <updated>2024-05-19T12:00:00Z</updated>
        <id>https://liptrot.org/posts/whc_aria/</id>
        <content type="html"><![CDATA[
          <style>
            .link {
                display: inline-block;
                color: blue;
                text-decoration: underline;
            }
            .button {
                display: inline-block;
                border: 2px solid black;
                background: rgb(233, 229, 229);
                color: black;
                font-size: 16px;
                padding: 0.25em 0.5em;
                box-shadow: 1px 1px 2px rgba(0,0,0,0.5);
            }
            figure {
                display: inline-block;
                margin-right: 2em;
            }
</style>
<p>Showing how links and buttons marked up using ARIA differ in presentation from those marked up using native HTML elements.</p>
<h2>Results</h2>
<p>Screenshots of the different default WHC themes in Windows 11 using the test below.</p>
<figure>
    <img src="/assets/images/posts/aquatic.png" alt="Buttons look the same. The native link is blue whilst the aria one is white." />
    <figcaption>Aquatic</figcaption>
</figure>
<figure>
    <img src="/assets/images/posts/desert.png" alt="Buttons look the same. The native link is a grey-blue whilst the aria one is black." />
    <figcaption>Desert</figcaption>
</figure>
<figure>
    <img src="/assets/images/posts/dusk.png" alt="Both native elements are teal and both aria elements are white" />
    <figcaption>Dusk</figcaption>
</figure>
<figure>
    <img src="/assets/images/posts/night-sky.png" alt="The native button is yellow, the native link is purple. Both aria elements are white." />
    <figcaption>Night Sky</figcaption>
</figure>
<h2>Tests</h2>
<p>View this page in Windows High Contrast to see the difference using native elements for links and buttons makes.</p>
<h3>Buttons</h3>
<h4>Native button</h4>
<button class="button">Click me</button>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>button<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Click me<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
</code></pre>
<h4>Aria button</h4>
<div class="button" role="button" tabindex="0">Click me</div>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>button<span class="token punctuation">"</span></span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>button<span class="token punctuation">"</span></span> <span class="token attr-name">tabindex</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Click me<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
</code></pre>
<h3>Links</h3>
<h4>Native link</h4>
<a class="link" href="/">Click me</a>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>link<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Click me<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<h4>Aria link</h4>
<div class="link" role="link" tabindex="0">Click me</div>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>link<span class="token punctuation">"</span></span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>link<span class="token punctuation">"</span></span> <span class="token attr-name">tabindex</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Click me<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
</code></pre>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Links, buttons, roles and behaviours</title>
        <link href="https://liptrot.org/posts/links_buttons_roles_and_behaviours/"/>
        <updated>2023-06-15T13:00:00Z</updated>
        <id>https://liptrot.org/posts/links_buttons_roles_and_behaviours/</id>
        <content type="html"><![CDATA[
          <p>We often see links which have been styled to look like buttons. There is some debate among the accessibility community as to whether it is worthwhile adding a <code>role=&quot;button&quot;</code> to these elements so the semantics match the visuals.</p>
<p>I'm not going to get into that, but what I'm going to tackle is the approach which is taken when that <code>role</code> is added.</p>
<p>Normally when we add a <code>role=&quot;button&quot;</code> to a link we add some simple js handling for the spacebar to allow users to activate the control in the same way they might activate a native button. Without this a user hitting the spacebar on a link which <em>looks</em> like a button would end up scrolling the page.</p>
<p>So we end up with something like this:</p>
<pre class="language-js"><code class="language-js"><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'a[role="button"]'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">el</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  el<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'keypress'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>e<span class="token punctuation">.</span>keyCode <span class="token operator">===</span> <span class="token number">32</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      e<span class="token punctuation">.</span><span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      el<span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p>But that misses some of the nuances of the native control - something which is often missed when trying to replicate a native element. Native HTML buttons also have the feature where a user can <em>cancel</em> a spacebar trigger (just like you might cancel a mouse-click by pulling your mouse away before releasing it), by hitting the tab key whilst the spacebar is still pressed.</p>
<p>What we actually need to do is listen for <em>two</em> events.</p>
<p>First we need to listen for the <code>keypress</code> event on the spacebar as above, as this is what allows us to cancel that native scroll which would happen otherwise.</p>
<p>Then we need to listen for the <code>keyup</code> event on the spacebar. This means that if a user decides to cancel a “click” on our link-styled-as-a-button by using the tab key, we don't trigger it by mistake.</p>
<p>This ends up looking like this:</p>
<pre class="language-js"><code class="language-js"><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'a[role="button"]'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">el</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  el<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'keypress'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>e<span class="token punctuation">.</span>keyCode <span class="token operator">===</span> <span class="token number">32</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      e<span class="token punctuation">.</span><span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
  el<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'keyup'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>e<span class="token punctuation">.</span>keyCode <span class="token operator">===</span> <span class="token number">32</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      e<span class="token punctuation">.</span><span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      el<span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<h2>Results</h2>
<p>See below for the actual tests and detailed breakdown.</p>
<p>So we expected the first set of tests to be equal across the board and that is what we saw. Both handlers displayed the same characteristics as the native button. This proves we have not broken anything with the new handler.</p>
<p>However what we were really testing was if the native tab key interrupt was carried through with the handlers.</p>
<h3>Benefits for keyboard-only users and some screen-reader users</h3>
<p>It's pretty clear that the single event handler doesn't match the native button behaviour for keyboard-only users, whilst the double handler does a much better job of this.</p>
<p>It's also intersting to see that JAWS and NVDA don't allow for this interrupt but Voiceover does.</p>
<p>In conclusion it seems that a double handler like this provides a better solution for providing the correct behaviour for links with a button role.</p>
<h2>The test methods and detailed breakdown</h2>
<p>This is to test the standard practice of adding a single event listener (for the spacebar) against a proposed new double handler which prevents the standard scroll but also allows for the tab-interrupt.</p>
<h3>Test 1 - standard spacebar activation</h3>
<p>Move to the control with the <kbd>Tab</kbd> key and then activate the control with the <kbd>spacebar</kbd>.</p>
<p>This is a bit of a control test to make sure that the double handler works in the same way as the single handler and they both match the native expected outcome.</p>
<p>As expected both the single and double handlers perform the same with the standard test of triggering the control.</p>
<table>
  <caption>Outcomes from test 1: trigger control with spacebar</caption>
  <thead>
    <tr>
      <th>Browser / screenreader</th>
      <th>Native button behaviour</th>
      <th>Does single handler match native?</th>
      <th>Does double handler match native?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Win Firefox</td>
      <td>increments counter</td>
      <td>yes</td>
      <td>yes</td>
    </tr>
    <tr>
      <td>Win Chrome</td>
      <td>increments counter</td>
      <td>yes</td>
      <td>yes</td>
    </tr>
    <tr>
      <td>Win Edge</td>
      <td>increments counter</td>
      <td>yes</td>
      <td>yes</td>
    </tr>
    <tr>
      <td>MacOS Firefox</td>
      <td>increments counter</td>
      <td>yes</td>
      <td>yes</td>
    </tr>
    <tr>
      <td>MacOS Chrome</td>
      <td>increments counter</td>
      <td>yes</td>
      <td>yes</td>
    </tr>
    <tr>
      <td>MacOS Edge</td>
      <td>increments counter</td>
      <td>yes</td>
      <td>yes</td>
    </tr>
    <tr>
      <td>MacOS Safari</td>
      <td>increments counter</td>
      <td>yes</td>
      <td>yes</td>
    </tr>
    <tr>
      <td><strong>NVDA</strong> Win Firefox</td>
      <td>increments counter</td>
      <td>yes</td>
      <td>yes</td>
    </tr>
    <tr>
      <td><strong>NVDA</strong> Win Chrome</td>
      <td>increments counter</td>
      <td>yes</td>
      <td>yes</td>
    </tr>
    <tr>
      <td><strong>JAWS</strong> Win Chrome</td>
      <td>increments counter</td>
      <td>yes</td>
      <td>yes</td>
    </tr>
    <tr>
      <td><strong>JAWS</strong> Win Edge</td>
      <td>increments counter</td>
      <td>yes</td>
      <td>yes</td>
    </tr>
    <tr>
      <td><strong>Voiceover</strong> MacOS Safari</td>
      <td>increments counter</td>
      <td>yes</td>
      <td>yes</td>
    </tr>
  </tbody>
</table>
<h3>Test 2 - activation interruption</h3>
<p>The second test is to move to the link again but after pressing the <kbd>spacebar</kbd>, instead of releasing it, hold it down whilst pressing the <kbd>Tab</kbd> key.</p>
<p>This is the main test. We know native buttons have the option of cancelling a spacebar activation by using the tab key. This test checks how our different handlers cope with this and how different browsers and screen-readers handle it.</p>
<table>
  <caption>Outcomes from test 2: interrupt triggering of control with spacebar by using the tab key</caption>
  <thead>
    <tr>
      <th>Browser / screenreader</th>
      <th>Native button behaviour</th>
      <th>Does single handler match native?</th>
      <th>Does double handler match native?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Win Firefox</td>
      <td>stops button triggering</td>
      <td>no</td>
      <td>yes</td>
    </tr>
    <tr>
      <td>Win Chrome</td>
      <td>stops button triggering</td>
      <td>no</td>
      <td>yes</td>
    </tr>
    <tr>
      <td>Win Edge</td>
      <td>stops button triggering</td>
      <td>no</td>
      <td>yes</td>
    </tr>
    <tr>
      <td>MacOS Firefox</td>
      <td>stops button triggering</td>
      <td>no</td>
      <td>yes</td>
    </tr>
    <tr>
      <td>MacOS Chrome</td>
      <td>stops button triggering</td>
      <td>no</td>
      <td>yes</td>
    </tr>
    <tr>
      <td>MacOS Edge</td>
      <td>stops button triggering</td>
      <td>no</td>
      <td>yes</td>
    </tr>
    <tr>
      <td>MacOS Safari</td>
      <td>stops button triggering</td>
      <td>no</td>
      <td>yes</td>
    </tr>
    <tr>
      <td><strong>NVDA</strong> Win Firefox</td>
      <td>increments counter</td>
      <td>yes</td>
      <td>yes</td>
    </tr>
    <tr>
      <td><strong>NVDA</strong> Win Chrome</td>
      <td>increments counter</td>
      <td>yes</td>
      <td>yes</td>
    </tr>
    <tr>
      <td><strong>JAWS</strong> Win Chrome</td>
      <td>increments counter</td>
      <td>yes</td>
      <td>yes</td>
    </tr>
    <tr>
      <td><strong>JAWS</strong> Win Edge</td>
      <td>increments counter</td>
      <td>yes</td>
      <td>yes</td>
    </tr>
    <tr>
      <td><strong>Voiceover</strong> MacOS Safari</td>
      <td>stops button triggering</td>
      <td>no</td>
      <td>yes</td>
    </tr>
  </tbody>
</table>
<h2>The tests</h2>
<p>Successful activations will increment the counter on the control.</p>
<p>The tab stop link between examples are just to separate the tests.</p>
<div class="v0">
  <h3>Control</h3>
  <p>Test 1 expected: button is activated.</p>
  <p>Test 2 expected: tab key prevents spacebar from actioning the button.</p>
  <p><form action="http://www.example.com" method="get"><button class="btn">Native html button. <span data-count="0">0</span></button></form></p>
</div>
<p><a href="#">Tab stop (ignore, just for testing)</a></p>
<div class="v0">
  <h3>Standard link just with added role</h3>
  <p>Test 1 expected: link is not activated, page is scrolled.</p>
  <p>Test 2 expected: link is not activated, page scrolls and focus moves to next element.</p>
  <p><a class="btn" role="button" href="http://www.example.com?standard">Link with button classes (no js). <span data-count="0">0</span></a></p>
</div>
<p><a href="#">Tab stop (ignore, just for testing)</a></p>
<div class="v1">
  <h3>Single event</h3>
  <p>Test 1 expected: page is not scrolled, link is activated.</p>
  <p>Test 2 expected: link is activated (multiple times) and focus moves to next element.</p>
  <p><a class="btn" role="button" href="http://www.example.com?single">Link with keypress handler. <span data-count="0">0</span></a></p>
</div>
<p><a href="#">Tab stop (ignore, just for testing)</a></p>
<div class="v2">
  <h3>Double event</h3>
  <p>Test 1 expected: page is not scrolled, link is activated.</p>
  <p>Test 2 expected: link is not activated, focus moves to next element.</p>
  <p><a class="btn" role="button" href="http://www.example.com?double">Link with double handler. <span data-count="0">0</span></a></p>
</div>
<p><a href="#">Tab stop (ignore, just for testing)</a></p>
<script>


[].slice.call(document.querySelectorAll('.v1 a[role="button"]')).forEach(function (el) {
  el.addEventListener('keypress', function (e) {
    if (e.keyCode === 32) {
      e.preventDefault();
      el.click();

    }
  })
});

[].slice.call(document.querySelectorAll('.v2 a[role="button"]')).forEach(function (el) {
  el.addEventListener('keypress', function (e) {
    if (e.keyCode === 32) {
      e.preventDefault();
    }
  })
  el.addEventListener('keyup', function (e) {
    if (e.keyCode === 32) {
      e.preventDefault();
      el.click();

    }
  })
});

[].slice.call(document.querySelectorAll('.btn')).forEach(function(el){
  el.addEventListener('click', function(e){
    e.preventDefault();
    incrementAC(el);
  })
});

function incrementAC(el){
  var ac = el.querySelector("span");
  var cAC = ac.getAttribute('data-count');
  ac.innerHTML = parseInt(cAC) + 1;
  ac.setAttribute('data-count', parseInt(cAC) + 1);
}




// table styling

var el = document.getElementsByTagName("td");
for (var i = 0; i < el.length; i++) {
  if(el[i].innerHTML == "no") {
    el[i].className += " " + "no";
  }
  if(el[i].innerHTML == "yes") {
    el[i].className += " " + "yes";
  }
}
</script>
        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>WCAG 2.2 What you need to know</title>
        <link href="https://liptrot.org/posts/wcag2-2-what-you-need-to-know/"/>
        <updated>2023-02-08T13:00:00Z</updated>
        <id>https://liptrot.org/posts/wcag2-2-what-you-need-to-know/</id>
        <content type="html"><![CDATA[
          <p>WCAG 2.2 is a somewhat delayed update to 2.1 and adds 9 new success criteria on top of the existing ones in 2.1. It is primarily concerned with visual, cognitive and motor skill impairments.</p>
<h2>When will WCAG 2.2 be released?</h2>
<p>Changes to the new criteria following feedback after the draft stages has been taken into account and a new candidate recommendation was released in Jan 2023. This is now being looked at by the accessibility community for the ability to test, ease of understanding and impact for users. It is likely that the final recommendation will be released in the third quarter of 2023 (updated 25 April 2023).</p>
<h2>When will WCAG 2.2 become a legal requirement?</h2>
<p>WCAG itself is not a law but a series of guidelines. However it is referenced by other laws and is likely to be made reference to in legal cases.</p>
<p>WCAG is currently referenced in the Public Sector Bodies Accessibility Regulations (and the European equivalent) as the minimum standard to be reached. That 2018 regulation has already been amended (in 2022) to prepare for the new release of the guidelines. The new statement now reads (emphasis mine):</p>
<blockquote>
<p>A website or mobile application of a public sector body will be presumed to be in conformity with the accessibility requirement to the extent that the website or mobile application conforms to Level A and AA Success Criteria as set out in the Web Content Accessibility Guidelines recommended by the World Wide Web Consortium, as amended from time to time</p>
</blockquote>
<p>As such as soon as the new criteria are published they become enforceable.</p>
<h2>Are UK sites expected to be conformant as soon as they are released?</h2>
<p>Once the final recommendations are published there is likely to be a 12 month grace period for UK public sector sites to ensure they are compliant. The GOVUK Design System team will need to update their components and release them - they have a goal to do this within 6 months of release. This will give public sector teams an additional 6 months to apply those changes.</p>
<p><a href="https://accessibility.blog.gov.uk/2022/12/09/some-changes-to-the-public-sector-digital-accessibility-regulations/">UK government sites will being to be monitored for compliance in 2024.</a></p>
<p>However it would be beneficial for site owners to begin to review their designs now to see where the new criteria might affect them and begin to plan accordingly.</p>
<h2>What should I do?</h2>
<p>Most of these changes are likely to affect more commercial sites so if you are working on non-governmental clients there is likely to be more work required. However even if you only use government department components there is still work you can do to prepare.</p>
<ul>
<li>Don’t rush to make changes. Wait for the final release of the guidelines. But this doesn’t mean you cannot plan.</li>
<li>If you are responsible for procuring sites or services you should look to have WCAG 2.2 named in the contractual agreement as a requirement so everyone understands what is expected of them.</li>
<li>If you have a Design System, make sure the design system team are aware of the upcoming changes and have a plan ready.</li>
<li>Ensure that your own team is using the latest version of the relevant code libraries and that components used are being updated alongside libraries so you can take advantage of the central code updates when they come through.</li>
<li>Review any components your team have built and check that none of the new criteria affect them. Create a plan to update them if so.</li>
<li>Some of these changes are purely visual (like Focus Appearance) but others might require reworking of components (Dragging Movements) or even whole journeys (Accessible Authentication and Redundant Entry). Get the whole team involved so everyone knows what the aims of the criteria are and how you will meet them.</li>
</ul>
<h2>Has anything changed in the existing criteria?</h2>
<p>Two things have changed - <em>Parsing</em> has been removed (the first time this has happened) and the status of <em>Focus Visible</em> has been upgraded to level A instead of level AA.</p>
<h3>4.1.1 Parsing (A) has been removed</h3>
<p>There has been a lot of debate around this, but at the moment it looks like it will be removed because any failures caught by it currently are also covered by other criteria. This criteria often causes confusion around what is or is not classed as a failure vs just bad code. Much improved parity between browsers in how they handle poor html means its impact can be anticipated now whereas before it was often a different outcome for different browsers.</p>
<p>For example a duplicate ID might be an issue only if it is being to reference an element for accessibility purposes. Removal of this criteria means the confusion is removed and we can concentrate on the actual impact on the user.</p>
<p>This doesn’t mean you shouldn’t keep checking your HTML validates - it is still one of the simplest ways to check for a bunch of knock-on effects from accessibility to rendering and styling.</p>
<p>As WCAG is mean to be backwards-compatible and this is the first time a criterion has been removed, it’s not sure what effect, if any, this will have on things like the ISO (which is still using WCAG 2.0 as a benchmark).</p>
<h3>2.4.7 Focus Visible (A) has been updated</h3>
<p>This criterion was rated AA under WCAG 2.1 but has been moved to A under 2.2</p>
<h2>What are the new criteria?</h2>
<h3>2.4.11 Focus Appearance (AA)</h3>
<p>This is the most wide-ranging change as it is likely to impact most websites and even challenges some of the more basic styling techniques used for focus indication.</p>
<p>There is already a criterion called Focus Visible, but the requirements for it are quite minimal:</p>
<blockquote>
<p>Any keyboard operable user interface has a mode of operation where the keyboard focus indicator is visible.</p>
</blockquote>
<p>There wasn’t any minimum requirements of what that indicator should look like - is a thin border ok? visible to who - someone with good eyesight?</p>
<p>This new criterion looks to pin that indicator down with a series of rules around what the indicator should looks like. It boils down to these rules:</p>
<ul>
<li>good contrast (3:1) against other states and adjacent colours</li>
<li>a size equivalent to a 1px border around the element, or a 4px border on the shortest side of the element</li>
</ul>
<p>There are however details of this criterion which are <a href="https://github.com/w3c/wcag/issues/2679">causing confusion in the community</a> around how these values are calculated for specific use-cases. Also, how would this impact the standard application of a text-underline on focus? That underline is generally set to just 1px which is below the threshold for passing this criterion and places a lot of sites at risk of failing this straight away.</p>
<p>So at the moment this criterion is marked “At risk” but is unlikely to be changed at this stage so will either be implemented as it is or get pulled before publication. If it gets implemented expect a bit of confusion around how this should be tested and if something passes it or not.</p>
<p>Even if this criterion does not make it into the final release, it is worthwhile revisiting your product’s focus indicators to see if they really are as visible as they could be.</p>
<p>Alistair Campbell, part of the WCAG editorial team, has <a href="https://alastairc.uk/2023/02/focus-appearance-thoughts/">a good breakdown of the latest version</a>.</p>
<div class="note note--update">
<p><strong>Update: 22 March 2023</strong>  <a href="https://lists.w3.org/Archives/Public/w3c-wai-gl/2023JanMar/0309.html">this looks to have been dropped from AA level to AAA level</a>. This is a disappointing move as it leaves us without a clear definition of what visible actually means at the commonly used compliance levels of A and AA, despite Focus Visible still being a AA criterion.</p>
</div>
<p><a href="https://www.w3.org/WAI/WCAG22/Understanding/focus-appearance.html">Understanding Success Criterion 2.4.11: Focus Appearance</a></p>
<h3>2.4.12 Focus Not Obscured (Minimum) (AA)</h3>
<p>Still looking at improving how focus is handled in WCAG, this criterion ensures that after you have created a visible indicator, that you don’t then have something obscuring it entirely such as a non-modal dialog, a sticky navigation or cookie banner when it is focussed.</p>
<p>Think of when you tab down a page and the navigation stays fixed to the top of the browser window - we want to ensure the item with focus on the page is not covered by that navigation.</p>
<p><a href="https://www.w3.org/WAI/WCAG22/Understanding/focus-not-obscured-minimum">Understanding Success Criterion 2.4.12: Focus Not Obscured (Minimum)</a></p>
<h3>2.4.13 Focus Not Obscured (Enhanced) (AAA)</h3>
<p>This is the partner to the above criterion. Being the AAA version this is more strict and requires that no part of the focus indicator is obscured.</p>
<p><a href="https://www.w3.org/WAI/WCAG22/Understanding/focus-not-obscured-enhanced">Understanding Success Criterion 2.4.13: Focus Not Obscured (Enhanced)</a></p>
<h3>2.5.7 Dragging Movements (AA)</h3>
<p>This criterion is designed to help users who have difficulty with precision actions or who have to use non-standard input methods (such as eye-tracking). If an interface component requires a user to use a dragging motion to complete an action, then there must be a way of completing the action without dragging using a single pointer (ie not multi-touch gestures).</p>
<p>An example might be dragging a 3D visualisation of something to see it from all angles. Having arrow buttons would allow a user to be able to accomplish the same.</p>
<p>Another example is being able to drag items in a list to sort them, but also being able to click on an item in the list and have arrows appear to allow the item to be moved up and down.</p>
<p>A partner to this criterion is the existing 2.1.1 Keyboard but it was found there are instances where keyboard equivalence does not always equate to single pointer equivalence so a separate criterion was needed.</p>
<p>For example think of a horizontally scrolling component. It can be swiped (multi-touch) and keyboard can access it (because of focusable items inside it), but users who use a head-pointer will not be able to scroll it. This criteria catches these cases which would otherwise fall outside WCAG.</p>
<p>This new criterion also helps cover off touch experiences more comprehensively - but remember people on mobiles might want to use an external keyboard and those on desktops might zoom in and trigger a mobile view. It’s often best to consider viewport and input modalities as unrelated.</p>
<p><a href="https://www.w3.org/WAI/WCAG22/Understanding/dragging-movements">Understanding Success Criterion 2.5.7: Dragging Movements</a></p>
<h3>2.5.8 Target Size (Minimum) (AA)</h3>
<p>Target size has been part of design best practice for a long time and is covered currently by WCAG 2.5.5 (AAA) which requires a target of at least 44px by 44px (which is what Apple and Google recommend for their mobile interfaces). This new criterion adds a new minimum requirement at the AA level of 24px by 24px. Because of the AA rating this now comes under many of the legal requirements of various countries.</p>
<p>The same exemptions apply to this criterion as apply to the AAA one:</p>
<ul>
<li>the target is inline text within other copy (such as a paragraph) - note stacked links in a list are not exempted</li>
<li>the target size is essential for communicating information (for example map pins might need to be clustered to convey location)</li>
<li>browser defaults - like some other criteria, if you don’t alter a browser’s interpretation of a control (such as a calendar widget) then this does not apply</li>
<li>duplication - if another control which is compliant performs the same action as the non-complaint one means the non-compliant one is exempted as the user has the option to use the other control</li>
</ul>
<p>But there is an additional one for this new criterion around spacing:</p>
<ul>
<li>spacing - a target can be under 24px as long as the space between it and the next target makes up the difference. So a 20px button can be next to another one as long as there is a 4px gap between them. This might seem odd as it makes it possible to make a tiny target, but this criterion is all about accuracy rather than perception - can the user action this target without hitting others by mistake.</li>
</ul>
<p>Teams should still look to meet the AAA standard where possible (especially where the platform states it in their documentation as Apple and Google do), but this criterion does at least make everyone look to ensure they are doing the minimum.</p>
<p><a href="https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html">Understanding Success Criterion 2.5.8: Target Size (Minimum)</a></p>
<h3>3.2.6 Consistent Help (A)</h3>
<p>In order to make interfaces more consistent and help users find help when they need it (often a stressful situation), where a site displays certain help features, these should be present in the same place in relation to other content, on each page.</p>
<p>The features this applies to are:</p>
<ul>
<li>human contact details - this can be important for certain users who may find it difficult to use other methods of assistance
<ul>
<li>human contact details - email, phone number, opening hours</li>
<li>human contact mechanism - non-automated chat, contact form, social media</li>
</ul>
</li>
<li>self-help options - FAQs, support pages</li>
<li>fully-automated contact mechanism - chatbot</li>
</ul>
<p>Chat interfaces are especially useful as they allow the user to retain the current context whilst interacting with the source of help and allow the user to use their own vocabulary rather than the site’s.</p>
<p>This doesn’t mean the site has to provide these options - just if they are that they are presented consistently.</p>
<p>As the user moves through the site those contact features should be in the same relative visual location so the user knows where to look. If the user changes the screen size then all pages should act in the same way in where the contact options end up.</p>
<p><a href="https://www.w3.org/WAI/WCAG22/Understanding/consistent-help">Understanding Success Criterion 3.2.6: Consistent Help</a></p>
<h3>3.3.7 Accessible Authentication (AA)</h3>
<p>This criterion is designed to help users log into sites as smoothly as possible. Having to solve a puzzle, transcribe information (unless you can copy &amp; paste) or remember usernames and passwords can be a real struggle for many users - these are classed as a cognitive function test.</p>
<p>Username and password fields which are marked up correctly (and don’t prevent copy &amp; paste) can allow the browser or password managers to fill in the fields on behalf of the user which would then pass this criterion. Note personal information such as name, email address or phone number are not classed as a cognitive function test (though not allowing those to be auto-filled would fail WCAG 1.3.5 Identify Purpose).</p>
<p>Old-style bank authentication of the style “enter the 4th 6th and 8th characters from your password” would also fail this criteria as it requires transcription and does not support copy &amp; paste or autocomplete.</p>
<p>reCaptcha are exempted because the objects displayed are classed as “familiar” objects (think traffic lights), despite there being obvious issues with many of the source images and names being pulled from the US. Note those old-style Captchas which had a deformed word you had to recognise would fail this because it is not a familiar object and requires transcribing.</p>
<p>This criteria also applies to 2-factor authentication (it’s no good having an accessible first step if you then have to solve a puzzle on your phone) and username and password recovery (an essential part of authentication).</p>
<p><a href="https://www.w3.org/WAI/WCAG22/Understanding/accessible-authentication">Understanding Success Criterion 3.3.8: Accessible Authentication</a></p>
<h3>3.3.8 Accessible Authentication (No Exception) (AAA)</h3>
<p>This is a stricter version of the above. It removes the object exemption (and so the option for reCaptcha).</p>
<p><a href="https://www.w3.org/WAI/WCAG22/Understanding/accessible-authentication-no-exception">Understanding Success Criterion 3.3.8: Accessible Authentication (No Exception)</a></p>
<h3>3.3.9 Redundant Entry (A)</h3>
<p>On the face of it this is a simple criterion - don’t ask the user the same questions you already have the answers for, or at least tell them what they entered before so they can select it as an option. For example <em>“you said your email address was x would you like to use that?“</em> rather than <em>“enter your email address“</em> again.</p>
<p>What we are trying to avoid is the user having to enter the same data they already have and either getting a mismatch or having to use additional effort to enter or recall the data they previously entered.</p>
<p>Note - browser autocomplete is not a sufficient mechanism to pass this criterion.</p>
<blockquote>
<p>Information previously entered by or provided to the user that is required to be entered again in the <em>same process</em> is either auto-populated, or available for the user to select</p>
</blockquote>
<p>However the definition of a process says also can run across different domains. This paragraph from the guidelines could have an impact:</p>
<blockquote>
<p>so if a check-out process includes a 3rd party payment provider, that would be in scope</p>
</blockquote>
<p>So if the payment provider were to ask for an address which the user had already entered as part of their checkout process, this must be passed through to the provider page.</p>
<p><a href="https://www.w3.org/WAI/WCAG22/Understanding/redundant-entry">Understanding Success Criterion 3.3.7: Redundant Entry</a></p>
<h2>Further reading</h2>
<p><a href="https://medium.com/design-ibm/assessing-components-and-patterns-for-wcag-2-2-47ee3f0f468e">Assessing components and patterns for WCAG 2.2</a></p>

        ]]></content>
      </entry>
    
	
    
	
    
      
      <entry>
        <title>Colour and accessibility</title>
        <link href="https://liptrot.org/posts/colour-and-accessibility/"/>
        <updated>2023-02-06T13:00:00Z</updated>
        <id>https://liptrot.org/posts/colour-and-accessibility/</id>
        <content type="html"><![CDATA[
          <p>There are a few things to consider when thinking of colour and accessibility, but it generally comes down to one thing - can the user see what you are intending them to see?</p>
<p>If the user can't make out the text because it falls under the required contrast ratios, it is effectively not there for that user.</p>
<p>Making colours accessible can sometimes be seen as an unwanted constraint on creativity, but there are so many colours available that by seeing accessibility as a design philosophy it both reduces the possibilities to a more manageable number and gives a reason for using a particular shade over another.</p>
<p>For example, Slack used to have a palette of 132 colours until they did an accessibility review which enabled them to reduce it down to a much more manageable 18 colours.</p>
<h2>Contrast</h2>
<p>One of the most talked about is colour contrast. At its most basic this is making sure that a colour is clearly distinguishable from the surrounding colour so the item is clearly perceivable to the user. For example, making sure a font colour has a good contrast against the page background (anyone else remember that phase of web design where everything was small grey text on a white background?).</p>
<p>Contrast is important not only for users with reduced visual acuity, but good contrast helps when screen brightness is reduced (for example with battery saver options) or when viewing a screen in bright sun.</p>
<p>Colour contrast can be measured as a ratio and this is what you will often cited in accessibility reports or on contrast checkers, but generally you want at least 4.5:1 for text content and 3:1 for non-text content (to meet WCAG AA), but bear in mind these are the minimum and you want to be far exceeding these values (the higher the first number the better as the more clear it will be to the user). The WCAG AAA ratio for text contrast is 7:1, so aim for this instead.</p>
<p>Remember these ratios are also important for the various <em>states</em> of the items, so consider colour contrast when looking at focus and hover states too. You don't want a link which appears to disappear when the user tabs to it, and you also want the various states to be obvious when triggered.</p>
<p>Whilst contrast is most commonly linked to text it is also crucial for interface elements. Well defined borders on things like form inputs ensure users can perceive the element itself, important when there is no other indication (like text for a button).</p>
<p>Also pay attention to mixed colour backgrounds, such as when text is overlaid on images. Even if the component is designed with a more subdued image to allow the text to have good contrast, be aware that as the layout shifts based on the viewport, the position of the image in relation to the text may also move. Where the text once overlaid a contrasting part of the image may no longer be the case and the contrast may have suffered.</p>
<p>Colour as information
Colour is also something which shouldn't be used in isolation to convey information - for example saying &quot;credits are shown in green and debits in red&quot;, or just using a red outline to mark an error on a form input is not helpful. As not everyone perceives colour in the same way (various forms of colour-blindness are very common) it is important that text labels are also used to present the meaning, and it is the meaning which is referred to rather than the colour.</p>
<p>Similarly, just identifying links with a colour can leave users struggling to identify them, so consider keeping the underlines unless it is in a section of the page where it is obvious it is a link (such as a navigation area).</p>
<p>As such, colour should always be a secondary consideration. The simplest way to check something still makes sense is to view it in greyscale which you can do using Chrome's rendering options in devTools, or in MacOS's colour filters (under Accessibility in System Prefs).</p>
<h2>Colour-blindness</h2>
<p>Speaking of colour-blindness, there is a misconception that red/green colour-blindness just means you can't 'see' the difference between red and green. In fact it causes issues with any colour which uses red or green as a constituent part, for example purple. So the likelihood is many colours will actually look different to a user with this condition.</p>
<p>Also bear in mind that colour-blindness is not binary but has a spectrum of severity in the different types. There are emulators such as in the Chrome developer tools Rendering panel, but these show examples only (I've not found two emulators which agree on how something would be perceived). What they do show however is how different types of colour-blindness can also affect how effective colour contrast is, another reason why you want to make your contrasts as high as possible.</p>
<p>Bear in mind things other than the very common colour-blindness can affect colour perception. Most operating systems now include bedtime routine modes which change the colours emitted after a certain time to reduce blue-light exposure.</p>
<h2>Backgrounds and inverted colours</h2>
<p>Colour is sometimes used as a background to help define an area. Even where this background has good contrast against the surrounding area, because background colours are not included when using an inverted colour setting like Windows High Contrast this can be lost and important visual grouping lost.</p>
<p>To avoid this, use a transparent border on the element which will be highlighted in the inverted colour scheme to define the area in an alternate but just as effective way.</p>
<h2>Detrimental effects of colour choice</h2>
<p>As mentioned, some users have problems using sites which have acres of bright white backgrounds, so look at the possibility of implementing a dark mode as an option. Similarly, some users may struggle with a dark scheme so allow them to choose a lighter option. These can be tied to the operating system's user preferences setting, but should always include a toggle to allow the user user to override this for the individual site if desired.</p>
<p>Pure black on white can be difficult for some users with dyslexia, so look at using off-white and dark grey instead.</p>
<p>Finally, colour can also draw attention and distract or simply be overwhelming, so be aware of how this might affect users.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Basic screen‐reader accessibility testing</title>
        <link href="https://liptrot.org/posts/basic-screen-reader-accessiblity-testing/"/>
        <updated>2023-02-05T13:00:00Z</updated>
        <id>https://liptrot.org/posts/basic-screen-reader-accessiblity-testing/</id>
        <content type="html"><![CDATA[
          <p>Being able to check some code changes or a design with a screen‐reader is a major part of understanding accessibility, but many people put it off as it is so daunting.</p>
<p>It’s certainly understandable as most times you might see people using a screen‐reader they will have the speed turned up so high it is difficult to follow and they might jump around the page seemingly randomly.</p>
<p>But, for the most basic of testing, a simple top to bottom run through the page, you only need to know one or two keys commands.</p>
<h2>How screen‐readers move about a page</h2>
<p>Before we get into starting up our screen‐reader, let’s think about how a screen‐reader will move you around the page.</p>
<h3>Where am I?</h3>
<p>The first thing you might want to know when you land on a page which you can’t see, is “am I on the right page?”. To help with this the first thing you will hear when a page loads is the contents of the page title element. This is why having the title contain the purpose of the page (ideally the same as the page's h1 ) as well as the site's name is a great idea.</p>
<h3>Not your typical keyboard user</h3>
<p>Yes, screen‐readers make use of the keyboard to navigate, but put away thoughts that you will be moving about the page by hitting the tab key. Doing that will only let you hear the interactive content (links, form inputs, buttons etc), so you wouldn't really be able to listen to an article by tabbing around.</p>
<p>Instead you’ll be using the arrow keys to move up and down the page. As you move you will see an outline around content and this is a visual representation of what’s called the virtual cursor. This allows you to move by blocks of text, reading it aloud as you go, but will also read out extra information when you get to buttons, form inputs or other components.</p>
<p>As you move around the page you will see the browser focus (that focus state you get when you tab about with a keyboard) move with you when you reach an interactive element like a link, but then get left behind as you carry on using the virtual cursor.</p>
<h3>One long tube</h3>
<p>As you move about with a screen‐reader you will notice that the reading order follows the code order. To a screen‐reader user the page is always one long tube of content - the visual layout doesn’t really matter - which is also why “directional content” (where you might refer to content “over to the right”) is discouraged (although “above” or “below” is generally ok).</p>
<h3>Don’t sweat the content</h3>
<p>You might hear some content read out differently to how you might expect. In general, don’t worry about this (or check with an experienced user) as screen‐reader users can have different settings depending on their preferences. In particular reference numbers is one area where we see developers trying to force the screen‐reader to read it out in a particular way, not realising that all screen‐readers allow users to move character-by-character if required, so they can easily check the exact details if they want.</p>
<p>If you find yourself thinking more content is needed to help screen‐reader users understand an interface, the chances are they either don’t (again, check with an experienced user), or that content would help all users, or the interface may need to be reworked.</p>
<h2>Mac users</h2>
<p>If you are a Mac user then you already have a screen‐reader installed called Voiceover.</p>
<p>Most screen‐readers work best with specific browsers and in Voiceover’s case that is Safari.</p>
<p>You use Command + F5 to start (and importantly to stop) Voiceover.</p>
<h2>Windows users</h2>
<p>If you are on Windows, whilst there is a pre-installed screen‐reader called Narrator, it doesn’t have heavy usage so for testing I’d recommend using NVDA, which is a free download.</p>
<p>Most screen‐readers work best with specific browsers and in NVDA’s case that is Chrome or Firefox.</p>
<p>When you start NVDA it will appear as a tool tray icon near the date and time, you may need to expand the tool tray to see it. You stop NVDA just like any other application.</p>
<figure>
<img src="/assets/images/posts/nvda-tray.png" alt="Windows' system tray showing the expanded view with the purple and white NVDA icon" />
<figcaption>NVDA as a tray icon</figcaption>
</figure>
<p>Clicking on the icon will allow you to access the various settings.</p>
<details>
    <summary>There are a couple of setting changes which I recommend you make to NVDA.</summary>
    <div>
        Don’t be tempted to change any other settings whilst modifying these as it makes it more difficult to replicate issues and you can introduce unintended side-effects.
<p><h3>Change the voice</h3>
The default one is very robotic and quite difficult to listen to</p>
<p>Go to “Preferences”, then “Settings”, then “Speech”. Try out some of the synthesizers from the drop-down. Different voices using that synthesizer are available from the voices drop-down below it.</p>
<p>I find the Windows OneCore Hazel voice to be quite good, but try a few out and find one which you are happy listening to.</p>
<p><figure>
<img src="/assets/images/posts/nvda-voice.png" alt="NVDA's settings with the speech panel active showing a drop-down of different voices" />
<figcaption>Where to find the voice options</figcaption>
</figure></p>
<p><h3>Turn off Say All</h3>
This stops NVDA from just reading out the whole page as soon as it loads.</p>
<p>“Preferences”, then “Settings”, then “Browse Mode” and uncheck the “Automatic say all on page load” option.</p>
<p><figure>
<img src="/assets/images/posts/nvda-say-all.png" alt="NVDA's settings with the browse mode panel open showing the location of the Say All option" />
<figcaption>Where to find the Say All setting</figcaption>
</figure></p>
<p><h3>Turn off Mouse Tracking</h3>
This prevents NVDA reading out whatever is under your mouse cursor which makes it really easy to lose your place when testing things.</p>
<p>To turn this off go to “Preferences”, then “Settings”, then “Mouse” and uncheck “Enable mouse tracking”.</p>
<p><figure>
<img src="/assets/images/posts/nvda-mouse.png" alt="NVDA's settings showing the Mouse options" />
<figcaption>Where to find the Mouse Tracking set</figcaption>
</figure></p>
<p></div></p>
</details>
<h2>Getting started</h2>
<p>We’ll pick a simple (and well built) site to test our new screen‐reader skills. Open <a href="https://www.gov.uk/">GOV.UK</a> in the recommended browser and turn on your screen‐reader (you can use your mouse to place focus on the page, but once you have done that just use the keyboard).</p>
<p>The first thing you will notice is an outline around the element the screen‐reader is focussed on (remember this can be anything, including the whole page). This is the virtual cursor and will show you what the screen‐reader is talking about as you move about.</p>
<p>Before we start moving about, one useful key command to know is <kbd>Ctrl</kbd> - this stops the screen‐reader talking, until you navigate again. It can be very useful!</p>
<p>Let’s try just moving through the page.</p>
<p>If you are using Voiceover you will use <kbd>Ctrl</kbd> + <kbd>Option</kbd> + <kbd>right arrow</kbd> to move down the page (note, if the black outline is on the whole page, you might need to enter the page first by hitting <kbd>Ctrl</kbd> + <kbd>Option</kbd> + <kbd>shift</kbd> + <kbd>down arrow</kbd> - don’t worry, that’s the most complex combo you will need!). To move back up the page switch out the right arrow key for the left arrow key.</p>
<p>If you are using NVDA you just need to use the <kbd>down arrow</kbd>. To move back up simply use the <kbd>up arrow</kbd> key.</p>
<p>That’s it - that’s the basic navigation for using a screen‐reader!</p>
<h2>Navigating by headings</h2>
<p>This is all well and good, but it can take a long time to read through all of a page like this. So let’s add in one shortcut, navigating by headings.</p>
<p>For Voiceover you can use <kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>Cmd</kbd> + <kbd>h</kbd> to jump from heading to heading, NVDA users have it a lot easier as they can just hit the h key to do the same. Add in the shift key to reverse the direction.</p>
<p>You will hear the heading level read out as you do this and this highlights the importance of getting your heading hierarchy right as navigating by headings is a good technique for someone to get a mental layout of a page and its content and how it all relates to each other.</p>
<h2>Keep going</h2>
<p>Now you have started with your screen‐reader of choice, carry on learning the basics - I wrote some <a href="/guides">screen‐reader beginner’s guides</a> (for NVDA, Voiceover and JAWS) which take you through everything from how to understand what the screen‐readers are saying, to viewing lists of links and headings, how to navigate tables and more.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Keyboard-only accessibility testing</title>
        <link href="https://liptrot.org/posts/keyboard-only-accessibility-testing/"/>
        <updated>2022-12-06T13:00:00Z</updated>
        <id>https://liptrot.org/posts/keyboard-only-accessibility-testing/</id>
        <content type="html"><![CDATA[
          <p>Whilst this is a simple check to do, it actually covers several WCAG criteria because is such a core accessibility concern.</p>
<h2>Mac users</h2>
<p>If you are a Mac user, oddly tabbing to navigate links and form controls in a webpage is turned off by default. This affects Firefox and Safari.</p>
<details>
    <summary>How to enable tab navigation on Mac</summary>
    <div id="enable-tab-mac">
    <h3>Firefox</h3>
    <p>To fix Firefox you need to go make a change in the Mac system settings.</p>
    <p>Before OS 13 it is in <code>System Preferences > Keyboard > Shortcuts</code> and check “Use keyboard navigation to move focus between controls”.</p>
    <p>For OS 13 on it is in <code>System Preferences > Keyboard</code> and toggle on “Keyboard navigation”.</p>
    <img src="/assets/images/posts/mac-keyboard.png" alt="Mac OS Ventura keyboard settings showing the location of the tab navigation option" />
    <h3>Safari</h3>
    <p>For Safari you need to make a change to Safari's own settings. In <code>Safari > Settings > Advanced</code>, check the option “press Tab to highlight each item on a web page”.</p>
    <img src="/assets/images/posts/safari-keyboard.png" alt="Safari settings showing the location of the tab navigation option" />
    </div>
</details>
<h2>Navigating</h2>
<p>Use the <kbd>tab</kbd> key to navigate around just the interactive elements on the page. You can use <kbd>enter</kbd> or <kbd>space</kbd> to activate buttons and <kbd>enter</kbd> to activate links. Some components might require <kbd>arrow</kbd> keys - radio button groups show focus on <kbd>tab</kbd> and then you can use <kbd>space</kbd> to select that radio or use <kbd>arrow</kbd> keys to move up and down the list.</p>
<p>Check if there is a <code>skip link</code> - an in‐page link at the top of the page which takes you to the main content and means you don't have to tab‐key your way through all the primary navigation on every page.</p>
<p>Do all the things which allow interaction (link, buttons, form elements etc) get focus when you tab to them?</p>
<p>Can you reach everything you can interact with using a mouse with your keyboard instead?</p>
<figure>
<img src="/assets/images/posts/trainline.png" alt="Website with a button highlighted in the page and in the devtools. DevTools shows the button has a tabindex set to minus 1" />
<figcaption>The Trainline website showing controls which cannot be reached by keyboard. In this case it is due to use of a negative tabindex. <a href="/assets/images/posts/full-size/trainline.png" target="_blank">See larger image (new tab).</a></figcaption>
</figure>
<h2>Seeing where your focus is</h2>
<p>Keyboard use relies heavily on being able to see where the focus currently is. If this is taken away by css or obscured (or just forgotten about) it can make it very difficult to work out where you are on the page. Making focus states really obvious (and importantly contrast well against non-focus states) helps as focus can jump across large sections of the page.</p>
<p>Is there a good focus indicator for all the interactive content? Something which catches your eye easily so you can find it on a page.</p>
<p>If you can't see where the focus went, you need to check if this is just down to a poor focus state or because the focus has gone to content which has been hidden from view - something you will often find when content has been hidden off-screen until triggered (like a menu).</p>
<figure>
<img src="/assets/images/posts/lookers.png" alt="A website with a focus shown floating in the middle of the page, apparently on nothing. Another screenshot shows there is a hidden menu which has got the focus." />
<figcaption>A car dealer site showing how focus has gone to a hidden ‘mega-menu’ which is full of links. Whilst this will cause confusion in hiding the focus, it also shows it hasn’t been hidden correctly. This means keyboard users will have to tab through a lot of links to get to some of the primary navigation options. <a href="/assets/images/posts/full-size/lookers.png" target="_blank">See larger image (new tab).</a></figcaption>
</figure>
<p>Make sure you check the page in both desktop and mobile/tablet view. External keyboards are commonly paired to smaller devices and desktops can display the mobile view when the page is zoomed. Keyboards are often ignored when designing for mobile unfortunately.</p>
<figure>
<img src="/assets/images/posts/marks-and-spencer.png" alt="The Marks and Spencer homepage in tablet view with an icon shown forced to focus state but with no indicator visible" />
<figcaption>M&S website’s menu icon has no focus indicator. <a href="/assets/images/posts/full-size/marks-and-spencer.png" target="_blank">See larger image (new tab).</a></figcaption>
</figure>
<h2>Logical order</h2>
<p>Does the order in which the links, buttons etc get focus make sense? It is all too easy to use css like grid to change the visual order of content, or use html like <code>tabindex</code> to force the focus order without checking how this affects other users. A focus indicator jumping around a page haphazardly can be confusing or frustrating for a user.</p>
<p>Keyboard traps, where you find you cannot tab out of a component are not something you normally want. But occasionally they are desirable, like in the case of a modal dialog (often visually indicated by a dimming of the page behind it). With a dialog like this you want to keep the user within the dialog until they make some sort of decision and not to be able to break out and navigate the page behind.</p>
<h3>Testing order with Firefox</h3>
<p>You can test focus order visually using Firefox’s tab order option in developer tools. This will overlay numbers on the page showing where the focus will be placed.</p>
<figure>
<img src="/assets/images/posts/tabbing.png" alt="Firefox's devtools showing the accessibility panel" />
<figcaption>The “Show Tabbing Order” option in Firefox’s Accessibility panel of devTools. <a href="/assets/images/posts/tabbing.png" target="_blank">See larger image (new tab).</a></figcaption>
</figure>
<figure>
<img src="/assets/images/posts/morrisons.png" alt="Morrisons supermarket homepage with numbers overlaid showing where the focus lands and in what order" />
<figcaption>Morrisons website showing the Firefox “Show Tabbing Order” in action. <a href="/assets/images/posts/full-size/morrisons.png" target="_blank">See larger image (new tab).</a></figcaption>
</figure>
<h3>Testing order with activeElement</h3>
<p>Overlays like Firefox’s are good but it can be tricky to track down a disappearing focus, especially in a crowded interface. You can be more targeted by using activeElement in the console. In Chrome’s console select Create live expression (the eye icon) and add <code>document.activeElement</code>. This will create a snippet which will follow focus in the page and allow you to both see where the focus is and what elements it is actually focussed on.</p>
<figure>
<img src="/assets/images/posts/thomas-cook.png" alt="Thomas Cook website with an element highlighted on the page and devtools open showing the element and class list of the item which currently has focus." />
<figcaption>activeElement in use showing where the focus lies, despite no visible focus on the page itself. <a href="/assets/images/posts/full-size/thomas-cook.png" target="_blank">See larger image (new tab).</a></figcaption>
</figure>
<h2>Managing focus</h2>
<p>By this we mean, when focus is moved (not by the user), how is it handled? For example, clicking on a close icon in a dialog means you will be removing that icon from the page (as it is part of the dialog), so where does the focus end up? <a href="https://sarahmhigley.com/writing/focus-navigation-start-point/">Browsers do try to help with this</a> when an element is removed, but as this doesn't account for screen‐readers, the focus needs to be managed to make a better user experience.</p>
<p>Screen-magnification users can also set their view to follow the focus, so ensuring focus is managed well is also very important for these groups.</p>
<p>In our dialog example we'd want focus to be returned to the thing which triggered the dialog, or if the dialog wasn't triggered by the user clicking something, back to whatever the user had focus on when it appeared. The trick is to try and be logical about it and keep it close to where the user's attention is.</p>
<p>The more dynamic the page the more focus management will be needed and the more important keyboard testing becomes.</p>
<h2>Checking everything works</h2>
<p>As most developers build and test with a mouse it is all too easy to forget that not everyone can (or wants to) use one. So you can find buttons which only respond to a mouse click, effectively blocking a user from continuing.</p>
<p>So, can you complete the task with just a keyboard? At the most basic level this means can the user activate all the links, buttons and other interactive elements (including things like video players) on the page and complete any forms.</p>
<p>If you have any scrollable areas then make sure these can gain focus themselves to allow a keyboard user to be able to scroll the content, otherwise the content inside might not be reachable.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Links, hidden copy and voice recognition</title>
        <link href="https://liptrot.org/posts/links-hidden-copy-and-voice-recognition/"/>
        <updated>2021-08-16T13:00:00Z</updated>
        <id>https://liptrot.org/posts/links-hidden-copy-and-voice-recognition/</id>
        <content type="html"><![CDATA[
          <p>An often-used technique for ensuring links to different targets have different accessible names (think of the classic &quot;Read more&quot; links on a blog), is to add some &quot;contextual&quot; content. This is so that screen‐reader users, who might be viewing a list of links extracted from the page by their screen‐reader software, won't have to guess at where a link might take them and can instead action the link directly from that list.</p>
<p>However if not done well this can have a deterimental impact on other users, in-particular speech-recognition users.</p>
<p>If you are reliant on speech-recognition software your primary interaction model is likely going to be saying &quot;Tap (or click) [name of the thing on the screen]&quot;. So if a button has the text &quot;Submit&quot; on it, you might say &quot;Tap submit&quot; and the software will action the button.</p>
<p>Where this becomes more tricky is where the accessible name (the thing the speech-recognition software is waiting to hear) has been modified and no longer matches the visible name. This is exactly what we are doing when we add screen‐reader &quot;only&quot; contextual information to a link or other element.</p>
<p>General guidance is always to append the hidden copy to the visible copy to make it less problematic for speech-recognition users. But how exactly do other placements of this new copy affect the speech-recognition user's experience?</p>
<p>What I tested with:</p>
<ul>
<li>iOS Voice Control on iPad (7 gen) running 14.6 on Safari</li>
<li>Android Voice Access on Pixel 2 running Android 11 on Chrome 92.0.4515.131</li>
<li>Dragon on Windows 10 on IE11</li>
</ul>
<p>Dragon seems to find the best match, front-loading the wording vocalised by the user. If saying &quot;click account&quot; it would pick the 3 links on the page with &quot;account&quot; in the visible name (but won't also flag the ones with &quot;account&quot; in the hidden copy alongside them). It also can search hidden copy - for example try saying &quot;click of account&quot;.</p>
<p>Previous testing also suggests Dragon will search attributes for a match, so it will search in this order, stopping once it finds hits:</p>
<ul>
<li>visible text</li>
<li>hidden text</li>
<li>attributes - further testing needed</li>
</ul>
<p>On the examples below the phrasing &quot;tap&quot; is used for ease of writing, but this might be &quot;click&quot; instead if the speech-recognition is using mouse-style input rather than touch-screen.</p>
<h2>Standard link</h2>
<p>For control purposes. No hidden copy, visible text is the accessible name.</p>
<div class="example">
    <div class="example--render">
        <a href="#">Change name</a>
    </div>
    <div class="example__code">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Change name<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p></div></p>
</div>
<p>This works as expected in all tested software.</p>
<table>
    <caption>Saying "tap change name"</caption>
    <thead>
        <tr>
            <th>Software</th>
            <th>Result</th>
        </tr>
    </thead>
    <tbody>
        <tr><td>Voice Control iOS</td><td>Actions link</td></tr>
        <tr><td>Voice Access Android</td><td>Actions link</td></tr>
        <tr><td>Dragon</td><td>Actions link</td></tr>
    </tbody>
</table>
<h2>Unique visible text with hidden content appended</h2>
<div class="example">
    <div class="example--render">
        <a href="#">Edit applicant<span class="sr-only"> of account</span></a>
    </div>
    <div class="example__code">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    Edit applicant
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>sr-only<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> of account<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p></div></p>
</div>
<p>Voice Control on iOS was the interesting outlier here. It would action the link only if the visible text was unique on the page.</p>
<table>
    <caption>Saying "tap edit applicant"</caption>
    <thead>
        <tr>
            <th>Software</th>
            <th>Result</th>
        </tr>
    </thead>
    <tbody>
        <tr><td>Voice Control iOS</td><td>Actions link but only when the text is unique</td></tr>
        <tr><td>Voice Access Android</td><td>Actions link</td></tr>
        <tr><td>Dragon</td><td>Actions link</td></tr>
    </tbody>
</table>
<h2>Non-unique visible text with different hidden content appended</h2>
<div class="example">
    <div class="example--render">
        <a href="#">Edit name<span class="sr-only"> of account</span></a>
<p><a href="#">Edit name<span class="sr-only"> of employee</span></a>
</div>
<div class="example__code"></p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    Edit name
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>sr-only<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> of account<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    Edit name
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>sr-only<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> of employee<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p></div></p>
</div>
<p>When the visible text is no longer unique - which is often when the use-case for this kind of supplemental content is useful - Voice Control on iOS no longer responded to the input, not even to number potential targets.</p>
<table>
    <caption>Saying "tap edit name"</caption>
    <thead>
        <tr>
            <th>Software</th>
            <th>Result</th>
        </tr>
    </thead>
    <tbody>
        <tr><td>Voice Control iOS</td><td>Will not action any link, will not number links for selection</td></tr>
        <tr><td>Voice Access Android</td><td>Will assign a number to each link for selection</td></tr>
        <tr><td>Dragon</td><td>Will assign a number to each link for selection</td></tr>
    </tbody>
</table>
<h2>Unique visible text with hidden content interleaved</h2>
<div class="example">
    <div class="example--render">
        <a href="#">Delete <span class="sr-only">Lisa's </span>account</a>
    </div>
    <div class="example__code">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    Delete
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>sr-only<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Lisa's <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
    account
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p></div></p>
</div>
<p>As the user is unlikely to know there is hidden copy present the first test is the less plausible situation, but it is interesting that even with a unique link Voice Control on iOS is having problems.</p>
<p>With the second test (saying all visible content) only Dragon managed to map the request to the link.</p>
<p>We can safely say that interleaving hidden content is not to be advised.</p>
<table>
    <caption>Saying "tap delete" (stopping at hidden copy)</caption>
    <thead>
        <tr>
            <th>Software</th>
            <th>Result</th>
        </tr>
    </thead>
    <tbody>
        <tr><td>Voice Control iOS</td><td>Will not action link</td></tr>
        <tr><td>Voice Access Android</td><td>Actions link</td></tr>
        <tr><td>Dragon</td><td>Actions link</td></tr>
    </tbody>
</table>
<table>
    <caption>Saying "tap delete account" (visible text)</caption>
    <thead>
        <tr>
            <th>Software</th>
            <th>Result</th>
        </tr>
    </thead>
    <tbody>
        <tr><td>Voice Control iOS</td><td>Will not action link</td></tr>
        <tr><td>Voice Access Android</td><td>Will not action link</td></tr>
        <tr><td>Dragon</td><td>Actions link</td></tr>
    </tbody>
</table>
<h2>Non-unique visible text with hidden content interleaved</h2>
<div class="example">
    <div class="example--render">
        <a href="#">Remove <span class="sr-only">Bob's </span>permissions</a>
<p><a href="#">Remove <span class="sr-only">Bob's </span>account</a></p>
<p><a href="#">Remove <span class="sr-only">Pete's </span>account</a>
</div>
<div class="example__code"></p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Remove
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>sr-only<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Bob's <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
    permissions
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Remove
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>sr-only<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Bob's <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
    account
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Remove
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>sr-only<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Pete's <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
    account
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<p></div></p>
</div>
<p>A similar result to the above in that only Dragon manages the more likely scenario, although it oddly ignored one of the options.</p>
<table>
    <caption>Saying "tap remove" (stopping at hidden copy)</caption>
    <thead>
        <tr>
            <th>Software</th>
            <th>Result</th>
        </tr>
    </thead>
    <tbody>
        <tr><td>Voice Control iOS</td><td>Will not action link</td></tr>
        <tr><td>Voice Access Android</td><td>Will assign a number to all links for selection</td></tr>
        <tr><td>Dragon</td><td>Will assign a number to all links for selection</td></tr>
    </tbody>
</table>
<table>
    <caption>Saying "tap remove account" (visible text)</caption>
    <thead>
        <tr>
            <th>Software</th>
            <th>Result</th>
        </tr>
    </thead>
    <tbody>
        <tr><td>Voice Control iOS</td><td>Will not action link</td></tr>
        <tr><td>Voice Access Android</td><td>Will not action link</td></tr>
        <tr><td>Dragon</td><td>Will assign a number to bottom 2 links for selection</td></tr>
    </tbody>
</table>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>CSS Speech</title>
        <link href="https://liptrot.org/posts/css-speech/"/>
        <updated>2020-03-04T12:00:00Z</updated>
        <id>https://liptrot.org/posts/css-speech/</id>
        <content type="html"><![CDATA[
          <p>Ever wondered when testing with a screen-reader how you can get it to read out a number as individual digits instead of a single number (often including the word “million”)? The general advice would be not to be too worried about that as screen-reader users do have some control over this themselves in their settings, and can also read words character-by-character if needed. But it is something which is in the CSS spec, but up to now has been unsupported.</p>
<p>However Voiceover and Safari have now finally implemented some <a href="https://www.w3.org/TR/2018/NOTE-css3-speech-20180605/#speaking-props-speak-as">speak-as</a> css support.</p>
<p>This property can alter how screen-readers process content which could potentially be really useful but also possibly dangerous and unwelcome for screen-reader users.</p>
<p>Whilst this is a step-forward in support, Voiceover does however do some weird stuff when you use it on an inline element - for example making the parent element use the same setting, which can be especially problematic when using <code>spell-out</code>.</p>
<p>Unfortunately NVDA and JAWS are yet to do so anything with it at all.</p>
<p>There are other properties in the spec such as <code>voice-volume: loud</code> and <code>rest-before</code>, but the <code>speak-as</code> properties look to be the most useful in that balance of helping authors get meaning across without negative impact on screen-reader users.</p>
<h2>Examples</h2>
<p>Try out the examples below with your screen-reader to see how the different attributes work.</p>
<p>The following all work in Voiceover with Safari.</p>
<p>They do not currently (March 2020) work with JAWS or NVDA on any browser.</p>
<h3>Speak as digits</h3>
<h4>Numbers only</h4>
<div class="example">
    <div class="example--render">
        <p>The following number will be read out as normal</p>
        <p>1005600</p>
    </div>
    <div class="example__code">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>1005600<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
</code></pre>
<p></div></p>
</div>
<div class="example">
    <div class="example--render">
        <p>The following number is using the <code>digits</code> value.</p>
        <p style="speak-as: digits">1005600</p>
    </div>
    <div class="example__code">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">speak-as</span><span class="token punctuation">:</span> digits</span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span>1005600<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
</code></pre>
<p></div></p>
</div>
<h4>Mixed alpha-numeric</h4>
<div class="example">
    <div class="example--render">
        <p>The following number will be read out as normal</p>
        <p>10DIG05600L</p>
    </div>
    <div class="example__code">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>10DIG05600L<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
</code></pre>
<p></div></p>
</div>
<div class="example">
    <div class="example--render">
        <p>The following number is using the <code>digits</code> value.</p>
        <p style="speak-as: digits">10DIG05600L</p>
    </div>
    <div class="example__code">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">speak-as</span><span class="token punctuation">:</span> digits</span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span>10DIG05600L<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
</code></pre>
<p></div></p>
</div>
<h4>Using <code>speak-as:digits</code> on inline elements</h4>
<p>Using speak as digits on an inline element currently makes it's parent speak as digits also. In the following phrase only the second number should be spoken as digits.</p>
<div class="example">
    <div class="example--render">
        <p>This is a number 90909 and so is <span style="speak-as: digits">1005600</span></p>
    </div>
    <div class="example__code">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>This is a number 90909 and so is <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">speak-as</span><span class="token punctuation">:</span> digits</span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span>1005600<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
</code></pre>
<p></div></p>
</div>
<h3>Spell out</h3>
<div class="example">
    <div class="example--render">
        <p>The following phrase will be read out as normal</p>
        <p>Melbourne is a city in Australia</p>
    </div>
    <div class="example__code">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>Melbourne is a city in Australia<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
</code></pre>
<p></div></p>
</div>
<div class="example">
    <div class="example--render">
        <p>The following phrase will be instructed to be spelled out</p>
        <p style="speak-as: spell-out">Melbourne is a city in Australia</p>
    </div>
    <div class="example__code">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">speak-as</span><span class="token punctuation">:</span> spell-out</span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span>Melbourne is a city in Australia<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
</code></pre>
<p></div></p>
</div>
<div class="example">
    <div class="example--render">
        <p>The following reference will be instructed to be spelled out</p>
        <p style="speak-as: spell-out">10DIG05600L</p>
    </div>
    <div class="example__code">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">speak-as</span><span class="token punctuation">:</span> spell-out</span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span>10DIG05600L<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
</code></pre>
<p></div></p>
</div>
<p>Note, using spell-out on an inline element currently makes it's parent spell out also. In the following phrase only Australia should be spelled out.</p>
<div class="example">
    <div class="example--render">
        <p>Melbourne is a city in <span style="speak-as: spell-out">Australia</span></p>
    </div>
    <div class="example__code">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>Melbourne is a city in <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">speak-as</span><span class="token punctuation">:</span> spell-out</span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span>Australia<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
</code></pre>
<p></div></p>
</div>
<h3>Punctuation examples</h3>
<div class="example">
    <div class="example--render">
        <p>The following phrase will be read out as normal</p>
        <p>Melbourne is a city in Australia. It has a population of approx. 6 million people.</p>
    </div>
    <div class="example__code">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>Melbourne is a city in Australia. It has a population of approx. 6 million people.<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
</code></pre>
<p></div></p>
</div>
<div class="example">
    <div class="example--render">
        <p>The following phrase will be instructed to be read out with punctuation</p>
        <p style="speak-as: literal-punctuation">Melbourne is a city in Australia. It has a population of approx. 6 million people.</p>
    </div>
    <div class="example__code">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">speak-as</span><span class="token punctuation">:</span> literal-punctuation</span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span>Melbourne is a city in Australia. It has a population of approx. 6 million people.<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
</code></pre>
<p></div></p>
</div>
<div class="example">
    <div class="example--render">
        <p>The following phrase will be instructed to be read out without punctuation</p>
        <p style="speak-as: no-punctuation">Melbourne is a city in Australia. It has a population of approx. 6 million people.</p>
    </div>
    <div class="example__code">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">speak-as</span><span class="token punctuation">:</span> no-punctuation</span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span>Melbourne is a city in Australia. It has a population of approx. 6 million people.<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
</code></pre>
<p></div></p>
</div>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Predicting the future</title>
        <link href="https://liptrot.org/posts/predicting-the-future/"/>
        <updated>2009-05-18T12:00:00Z</updated>
        <id>https://liptrot.org/posts/predicting-the-future/</id>
        <content type="html"><![CDATA[
          <p>From the Newark Daily Advocate on March 25, 1893:</p>
<blockquote>
<p>Every person of fairly good education and of restless mind writes a book. As a rule, it is a superficial book, but it swells the bulk and it indicated the cerebral unrest that is trying to express itself. We have arrived at a condition in which more books are printed than the world can read. This is true not only of books that are not worth reading, but it is true of the books that are.</p>
<p>All this I take to be the result of an intellectual affranchisement that is new, and of a dissemination of knowledge instead of concentration of culture. Everybody wants to say something. But it is slowly growing upon the world that everybody has not got something to say. Therefore one may even at this moment detect the causes which will produce reaction. In 100 years there will not be so many books printed, but there will be more said. That seems to me to be inevitable.</p>
</blockquote>
<p>If you replace book with blog, <a href="http://www.paleofuture.com/blog/2009/5/18/predictions-for-1993-1893.html">this chap</a> has the current state of play down to a tee. Even down to the realisation that not everyone writing something is worth reading, but also that there are so many good writers that you just can't keep up.</p>
<img src="/assets/images/posts/book.jpg" alt="" >
<p>This totally mirrors my online reading habits at the moment. I've gone from a huge selection of websites in my rss reader to a very select few. Additionally the frequency with which I check them has dropped from checking every day to maybe once a week or fortnight. Mainly I think I have Twitter to thank for this. By selecting the right people to follow I can quickly dip into any breaking industry news or new techniques as it's guaranteed at least one of those people will tweet it. The remainder of the posts in my rss feed can now be saved for later as I know they are unlikely to be time-sensitive. Ironically, as the time I have to catch up on these posts tends to be when I'm away from my computer, I <a href="http://www.flickr.com/photos/adamliptrot/sets/72157615389861043/">publish them</a> into slim books (via Lulu and only for my use), but at least I know these writings are worth reading.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Building a blog with Flickr</title>
        <link href="https://liptrot.org/posts/building-a-blog-with-flickr/"/>
        <updated>2008-11-20T12:00:00Z</updated>
        <id>https://liptrot.org/posts/building-a-blog-with-flickr/</id>
        <content type="html"><![CDATA[
          <p>About a year ago I became the proud owner of a 1979 MGB GT and began restoring it. I’d been thinking about setting up a blog about the process for a while and have finally got around to it. Luckily, over the past few months I’d been pretty good at taking photographs to document it all and had uploaded them to Flickr.</p>
<img src="/assets/images/posts/incayellow.jpg" alt="Inca Yellow screenshot">
<p>Now, I’ve used <a href="http://expressionengine.com/">Expression Engine</a> before and this was my first thought when I sat down to put my MG blog together. However it did seem a bit of overkill for what I wanted and I’d been there, done that and wanted to try something a bit different.</p>
<p>As I’d been uploading all my <a href="http://www.flickr.com/photos/adamliptrot/sets/72157603651163453/">MG photos</a> to Flickr and knowing that their photo description field allows a limited but totally sufficient set of html tags coupled with a <a href="http://www.flickr.com/services/api/">nice API</a> (even though it’s <a href="http://morethanseven.net/2008/02/21/sorry-but-the-flickr-api-isnt-rest/">not RESTful</a>), I decided to try using Flickr as a blog engine.</p>
<p>Before I go on, take a quick look at the result: <a href="http://www.incayellow.com/">IncaYellow.com</a>. [Editors note from 2023 - the site is no longer running on the Flickr API.]</p>
<p>The Flickr API is really pretty nice to work with. However, it can be a touch slow so I added in a bit of server-side caching to save visitors having to wait too long. For example, this is pulling in the individual photo information with a little bit of simple caching:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">getPhotoInfo</span><span class="token punctuation">(</span><span class="token parameter">$p</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// build the API URL to call</span>
$params <span class="token operator">=</span> <span class="token function">array</span><span class="token punctuation">(</span>
    <span class="token string">'api_key'</span> <span class="token operator">=></span> <span class="token string">'YOUR_API_KEY'</span><span class="token punctuation">,</span>
    <span class="token string">'method'</span> <span class="token operator">=></span> <span class="token string">'flickr.photos.getInfo'</span><span class="token punctuation">,</span>
    <span class="token string">'photo_id'</span> <span class="token operator">=></span> $p<span class="token punctuation">,</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
$encoded_params <span class="token operator">=</span> <span class="token function">array</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">foreach</span> <span class="token punctuation">(</span>$params <span class="token keyword">as</span> <span class="token parameter">$k</span> <span class="token operator">=></span> $v<span class="token punctuation">)</span><span class="token punctuation">{</span>
    $encoded_params<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">urlencode</span><span class="token punctuation">(</span>$k<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token string">'='</span><span class="token punctuation">.</span><span class="token function">urlencode</span><span class="token punctuation">(</span>$v<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">//call the API and decode the response</span>
$flickrurl <span class="token operator">=</span> <span class="token string">"http://api.flickr.com/services/rest/?"</span><span class="token punctuation">.</span><span class="token function">implode</span><span class="token punctuation">(</span><span class="token string">'&amp;'</span><span class="token punctuation">,</span> $encoded_params<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">//set cache options</span>
$cachefile <span class="token operator">=</span> <span class="token string">'PATH_TO_CACHE_FOLDER'</span><span class="token punctuation">.</span>$p<span class="token punctuation">.</span><span class="token string">'photoData.xml'</span><span class="token punctuation">;</span>
$cachetimelimit <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token number">60</span> <span class="token operator">*</span> <span class="token number">60</span><span class="token punctuation">)</span> <span class="token operator">*</span> <span class="token number">24</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//day</span>


<span class="token comment">//use the cache if newer than $cachetimelimit</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">file_exists</span><span class="token punctuation">(</span>$cachefile<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token function">time</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> $cachetimelimit <span class="token operator">&lt;</span> <span class="token function">filemtime</span><span class="token punctuation">(</span>$cachefile<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    $xml <span class="token operator">=</span> <span class="token function">file_get_contents</span><span class="token punctuation">(</span>$cachefile<span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
    <span class="token comment">//get the data and save to the cache</span>
    $xml <span class="token operator">=</span> <span class="token function">file_get_contents</span><span class="token punctuation">(</span>$flickrurl<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token comment">// Cache the output to a file</span>
    $fp <span class="token operator">=</span> <span class="token function">fopen</span><span class="token punctuation">(</span>$cachefile<span class="token punctuation">,</span> <span class="token string">'w'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">fwrite</span><span class="token punctuation">(</span>$fp<span class="token punctuation">,</span> $xml<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">fclose</span><span class="token punctuation">(</span>$fp<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment">//dump the xml in a variable</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span> $xml <span class="token punctuation">)</span> <span class="token punctuation">{</span>
        $theStuff <span class="token operator">=</span> <span class="token function">simplexml_load_string</span><span class="token punctuation">(</span>$xml<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> $theStuff<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre>
<p>You can then parse the resulting xml file to pull out the required info. Using a couple of other Flickr API methods and the <a href="http://delicious.com/help/api">Delicious API</a> meant I could pretty much reproduce a full-on blog, complete with archives and tag pages.</p>
<p>Now obviously this wouldn’t suit most blogs, but I knew that my posts would be pretty short and always be accompanied by a photo, so I was set.</p>
<p>There are a few enhancements I’ve got in mind for the next few weeks. The main one is being able to add more than one photo for a given post, especially for those more tricky mechanical jobs. This seems like a perfect opportunity to use machine tags to relate photos to each other and by adding something like:</p>
<pre class="language-js"><code class="language-js"><span class="token literal-property property">incayellow</span><span class="token operator">:</span>post<span class="token operator">:</span><span class="token constant">PHOTOID</span>
</code></pre>
<p>to a photo, I could pull in all the other photos to do with that job. Comments are another nice-to-have, so I’ll be building that in too. I’ll also be tweaking the caching timing over time to find the optimal period to keep data for (it’d be nice to have the cache refresh for new posts). The other thing I just haven’t got around to yet is an RSS feed. I could just use the Flickr RSS feed, but that just seems lazy, so I’ll most likely roll my own. Also on the horizon is a 404 page, just because I think you should always have one.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>CSS3 Media Queries - Workshops for Web People</title>
        <link href="https://liptrot.org/posts/css3-media-queries/"/>
        <updated>2007-11-18T12:00:00Z</updated>
        <id>https://liptrot.org/posts/css3-media-queries/</id>
        <content type="html"><![CDATA[
          <p>I was at the first event run by the amiable Keir and Glenn under the banner of <a href="http://www.wfwp.co.uk/">Workshops for Web People</a> in Leicester last week, featuring <a href="http://www.stuffandnonsense.co.uk/">Andy Clarke‘s</a> follow-on presentation for his <a href="http://www.transcendingcss.com/">Transcending CSS</a> book. A well done to both the lads and Andy for putting on a great day and keeping everyone entertained and full of food and drink.</p>
<img src="/assets/images/posts/malarkey.jpg" alt="Andy Clarke in workshop pose" >
<p>Andy spent some time looking at CSS3 and where certain aspects of it can be used right now. One feature is that of <a href="http://www.w3.org/TR/css3-mediaqueries/">media queries</a>. These are a series of features such as width, height, aspect-ratio and resolution with min- or max- prefixes, which enable the serving of css tailored to specific devices. Andy showed and example where a media query could be used to serve up a separate layout for mobile devices - specifically his iPhone.</p>
<p>Inspired by this demo I decided to reproduce that on this site. My aim was for anyone viewing on a supporting browser to be served up an additional set of styles if their browser-window’s size would normally have given them scrollbars. In practice this meant adding the following code to my main css file where I import my other files:</p>
<pre class="language-css"><code class="language-css"><span class="token atrule"><span class="token rule">@import</span> <span class="token string">"/assets/reset.css"</span><span class="token punctuation">;</span></span>
<span class="token atrule"><span class="token rule">@import</span> <span class="token string">"/assets/screen.css"</span><span class="token punctuation">;</span></span>

<span class="token atrule"><span class="token rule">@media</span> all <span class="token keyword">and</span> <span class="token punctuation">(</span><span class="token property">max-width</span><span class="token punctuation">:</span> 800px<span class="token punctuation">)</span></span><span class="token punctuation">{</span>
    ...additional styles…
<span class="token punctuation">}</span>
</code></pre>
<p>This translates as “when the device supports media all and is no wider than 800px, use these rules”.  You can try this with Safari (I’ve tested on Safari 3) and Opera (tested on 9.24) , though not Firefox, by resizing you browser to under 800px and hitting refresh. The refresh is required to activate the stylesheets, so it is not as robust a solution as one of the javascript options for this particular use, but it does provide an insight into how powerful CSS3 could be if we could get it out of the gate. The obvious applications are for mobile devices - especially those which don’t identify themselves as handheld, so by-pass the normal for-mobile styles.</p>
<p>Note that trying to add this rule in a <code>&lt;link.. /&gt;</code> tag doesn’t seem to work as it gets applied by Firefox even when not matching the rules, it seems in that state the browser ignores the bit of the rule it doesn’t understand, proceeding to implement the bits it does.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Gorilla accessibility</title>
        <link href="https://liptrot.org/posts/gorilla-accessibility/"/>
        <updated>2007-09-05T12:00:00Z</updated>
        <id>https://liptrot.org/posts/gorilla-accessibility/</id>
        <content type="html"><![CDATA[
          <p>Cadbury’s have recently launched a new advertising campaign under the name <a href="http://www.aglassandahalffullproductions.com/">Glass And A Half Full Productions</a>. Whilst the advert itself is genius, it is the accompanying website which caught my eye.</p>
<img src="/assets/images/posts/gorilla_drummer.jpg" alt="The Cabury advert gorilla" >
<p>Not content with slapping together a basic site, they have gone the extra mile to ensure as many people as possible can get on board. As well as the standard Flash-powered content - note I say content, rather than site - they have a version running the video via Windows Media Player.</p>
<p>This alone gives them props as Flash is a more responsive video player, but they have also added a <a href="http://www.aglassandahalffullproductions.com/transcript.html">video transcript</a> - the first time I’ve seen it done on an advertising site. I’m no expert but the transcript seems very well executed, so I assume they recruited professionals to do the job.</p>
<p>My only niggle would be that the link to the WMV player from the html version opens in a new window whilst the link from the Flash version remains in the parent, but this is small fish compared to the great steps they’ve taken for accessibililty on the rest of the site. The interesting thing is that the transcript actually adds something to the experience for folks who can actually see the video, so everyone benefits.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Mobile web design</title>
        <link href="https://liptrot.org/posts/mobile-web-design/"/>
        <updated>2007-08-30T12:00:00Z</updated>
        <id>https://liptrot.org/posts/mobile-web-design/</id>
        <content type="html"><![CDATA[
          <p>I’ve just finished reading <a href="http://www.cameronmoll.com/">Cameron Moll‘s</a> latest book, <a href="http://mobilewebbook.com/">Mobile Web Design</a>, which is available as a 100-page PDF download for a mere $19. This is my first download of a purchased book and I’m pleasantly surprised by the format.</p>
<img src="/assets/images/posts/mobilewebdesign.jpg" alt="The book" >
<p>The general thrust of the book is that the content should probably not be just your standard site (one of 4 possible options Cameron outlines), but rather a separate section or domain with content tailored to the user on the move (mobile referring to the user rather than the device). Contextualising what content people will want from your website via their phone is probably the most challenging part of mobile web design. It is quite possible that it is something which is not present on your primary domain, but this book gives you some good examples to help you get thinking in the right direction and using the phones unique abilities to full effect.</p>
<p>This is not a technical reference, instead focusing on the greater picture, but Cameron gives plenty of links for additional reading, something which is important in what will possibly be many people’s first look at designing for mobile users. In all it was a great read, which I managed within a day, and anyone familiar with Cameron’s writing on his blog will feel right at home. Still not sure? The book site has a sample. Go download.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Web teams and the organisation</title>
        <link href="https://liptrot.org/posts/web-teams-and-the-organisation/"/>
        <updated>2007-07-04T12:00:00Z</updated>
        <id>https://liptrot.org/posts/web-teams-and-the-organisation/</id>
        <content type="html"><![CDATA[
          <p>Zeldman’s <a href="http://www.zeldman.com/2007/07/02/let-there-be-web-divisions/">latest post</a>, on the position of web teams in organisations, has such a resonance with me at the moment. Unfortunately from what he says it is a widespread occurence. In-house web development is often lumped in with either marketing or IT, both resulting from an ignorance of, or unwillingness to understand, what web developers actually do.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>NY Times Dictionary</title>
        <link href="https://liptrot.org/posts/ny-times-dictionary/"/>
        <updated>2007-06-28T12:00:00Z</updated>
        <id>https://liptrot.org/posts/ny-times-dictionary/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/nyt.jpg" alt="The lookup in action showing a popup over a highlighted term on the NY Times site" >
<p>Whilst reading an article on the <a href="http://www.nytimes.com/">NY Times</a> I came across their somewhat hidden dictionary feature. I’d double-clicked on a term I didn’t recognise, intending to do a right-click Google search, when a window popped up. I’d almost dismissed it before I realised it was a ‘feature’.</p>
<p>Apparantly, this has caused some annoyance among those who idly click their mouse as they read, or highlight words as they go, even so far as the creation of <a href="http://userscripts.org/scripts/show/7721">counter-scripts</a> and <a href="http://andrewsherman.blogspot.com/2007/05/how-to-stop-annoying-nytimes-dicitonary.html">ad-blocking techniques</a>. Plus I bet it confuses the heck out of new-to-the-web people for whom the NYTimes may be the first port-of-call. Whilst I do think it’s a neat feature, love the discoverability of it, and may be great for assisting understanding, perhaps there should be a toggle somewhere in the member centre (I had a look and could see one)?</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Safari on Windows</title>
        <link href="https://liptrot.org/posts/safari-on-windows/"/>
        <updated>2007-06-11T12:00:00Z</updated>
        <id>https://liptrot.org/posts/safari-on-windows/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/safari.jpg" alt="Safari in the Windows start menu" >
<p>One of the big announcements to come out of WWDC was the release of Safari for Windows. It’s still in beta but seems perfectly workable, although it is a bit frustrating that to open a new tab you have to remember a key combo or right-click whilst on every other browser it’s a double-click on the tab bar. I think I’ll definitely use it for a while on Windows as it seems to have some neat features, but whether it’ll replace Firefox (with its super-useful extensions) as my default is another thing.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Future of Web Design, London 07</title>
        <link href="https://liptrot.org/posts/future-of-web-design-london-07/"/>
        <updated>2007-04-23T13:00:00Z</updated>
        <id>https://liptrot.org/posts/future-of-web-design-london-07/</id>
        <content type="html"><![CDATA[
          <p>I came away from <a href="http://futureofwebdesign.com/">FOWD</a> with mixed feelings. One the one hand it was pretty different from what I had envisaged as a practical “design” focussed event (grids, typography etc), being more a mix of case studies of marketing/web firms projects (games and fashion sites), broad strokes of how to engage with your users and some more specific design threads about language and workflow.</p>
<img src="/assets/images/posts/jeff_florian.jpg" alt="Florian Schmitt and Jeff Croft on stage" >
<p>Overall, whilst very enjoyable it came across as a bit confused as to its aim, probably not helped by my internal assumptions tying to it last year’s <a href="https://liptrot.org/journal/entries/carson_joshua/">Carson Summit</a>. Despite that, all the presentations were engaging and well delivered and as always the organisation was flawless, so congrats to all involved. Even the sponsors contributions were more than the normal out-of-sight variety - Microsoft’s crash-out zone with bean-bags, XBox360s and live feed from the stage and Adobe’s provision of the after-event drinks.</p>
<p>For me the highlights were:</p>
<ul>
<li><a href="http://www.magneticn.co.uk/">Brendan Dawes‘</a> examples of small touches can make huge differences to a user journey (though I dispute his idea of Deal or No Deal as a work of genius)</li>
<li><a href="http://www.37signals.com/">Ryan Singer‘s</a> form improvement - must try to get to one of his workshops in the future.</li>
<li><a href="http://flickr.com/photos/george/">George Oates‘</a> use of urls to plan workflow</li>
<li><a href="http://www.malarkey.co.uk/">Andy Clarke‘s</a> cool wall</li>
<li><a href="http://www.adaptivepath.com/team/ryan.php">Ryan Freitas‘</a> Buddhism concept of web apps and also his use of cartoons to describe user interaction with a site.</li>
<li><a href="http://www.hi-res.net/">Florian Schmitt</a> and <a href="http://www2.jeffcroft.com/">Jeff Croft</a> demonstrating Flash as a de facto web standard</li>
</ul>
<p>Lots to think about. <a href="http://www.flickr.com/photos/adamliptrot/sets/72157600098749870/">More photos on Flickr.</a></p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>The Death of Institutionalised Education?</title>
        <link href="https://liptrot.org/posts/the-death-of-institutionalised-education/"/>
        <updated>2007-04-23T12:00:00Z</updated>
        <id>https://liptrot.org/posts/the-death-of-institutionalised-education/</id>
        <content type="html"><![CDATA[
          <p>By far the most interesting aspect of the recent <a href="http://futureofwebdesign.com/">Future of Web Design conference</a> was the last thing to be said. The final panel was opened up to the floor and a question was put forward regarding the future of education in web design in face of the amazing pace of new developments in the field. <a href="http://www.malarkey.co.uk/">Andy Clarke‘s</a> reply was that if educational institutions cannot keep pace with developments then “perhaps we should see the death of institutionalised education” in web design.</p>
<img src="/assets/images/posts/fowd_panel.jpg" alt="The speaker panel at the conference" >
<p>The spontaneous applause which this got from the floor indicates the understanding of <a href="http://kurafire.net/articles/web-standards-and-educations">how far behind schools, colleges and even some universities</a> are when compared to best industry practice. I can’t help but agree, but I know it will never happen.</p>
<p>As long as there are people wanting to learn web design there will be educators trying to deliver it, especially with changes to funding models in the UK making every place on a course important. The problem I can see is one of hard-pressed teachers trying to fit a technical and pretty abstract subject into a small slot in the timetable. Of course the easiest thing is to go for the easy win and get the kids using a tool like Dreamweaver or FrontPage to knock something up quickly with no thought of the code behind the scenes. At least that way they have something to stick in a portfolio at the end of the day. And lets not forget that most web design courses come under the auspices of the IT department, when to get the results we aspire to it should be a joint venture between IT, Art and even Humanities.</p>
<p>Teachers who commonly get landed with delivering a web design course typically are ill-equipped to do so at a level which will give their students an insight into the real work going on in the industry. Maybe this is where the industry should step in to help. We could produce lesson plans with accompanying teacher notes suitable for different lengths of course, just as they are available for other subjects. These could be updated with new technologies and changes to standards as unlike most subjects our industry is a fast-paced one which even full-time professionals sometimes have a hard time keeping up with, let alone hard-pressed teaching staff. We could produce some outstanding sample sites which could be broken down into their component parts complete with notes for use as teaching aids. We could even come up with a network of web design firms who would be open to have student placements or come into class for a guest speaker session. I’m sure that with a little effort the firms which put a bit of effort in could end up with an endless supply of new talent from these sources.</p>
<p>Of course it can’t be all one-way. We need the teachers to let us in. Just as we recognise their abilities when it comes to communicating an idea to young minds, they need to see that accepting help from us is not a threat to their teaching skills. It needs to be a partnership else we risk continuing on our current insane course where teachers are delivering outmoded classes to students who won’t know any different until they’re in the industry - if they ever make it that far.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Highland Fling 07</title>
        <link href="https://liptrot.org/posts/highland-fling-07/"/>
        <updated>2007-04-07T12:00:00Z</updated>
        <id>https://liptrot.org/posts/highland-fling-07/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/highlandfling.jpg" alt="The audience at the conference" >
<p>Thursday (5th April) was the first (hopefully annual) <a href="http://thehighlandfling.com/2007/">Highland Fling</a>. It is really good to see an event in the top half of the country - even if it did mean a 5am start to get up there in time! Fortunately I was on the train with fellow Highland Fling-ers <a href="http://morethanseven.net/">Gareth</a> and Mark who prevented me from falling asleep and missing my stop. A short walk to the Symposium Hall in the Royal College of Surgeons gave us a quick glimpse of Edinburgh before the conference started.</p>
<p><a href="http://www.alanwhitewebdevelopment.com/">Alan</a> had managed to gather an impressive group of speakers for the inaugrual Fling, with Jeremy Keith kicking off events with an introduction to the concepts of progressive enhancement (via chair design and the zx81). All the speakers managed to pitch their slots at the right level, with not too much in the way of coding tutorials but lots of useful debate and theoreticals. Andy Budd in particular gave a great presentation on CSS3 and why it is taking so long for the next recommendation (CSS2.1) to get out of the draft phase.</p>
<p>Mark Norman Francis covered how Yahoo uses graded browser support, despite suffering from a cold; Christian Heilmann and James Edwards covered Javascript and Ajax from 2 slightly opposing viewpoints - both compelling arguments; Drew McLellan ran through microformats and the potential use as an API; and Andy Clarke finished off with a talk about the future including a reveal of the new Stuff and Nonsense design.</p>
<p>Whislt lunch wasn’t provided, the location of the conference meant there were plenty of places to grab some good food - I can now recommend Black Medicine Coffee Co. which had great smoothies and free wifi. Coffee and biscuits were put on in both breaks and Alan even managed to provide some excellent swag! As usual all the speakers excelled and both they and Alan should be congratulated on a great day out which was fantastic value for money. <a href="http://www.flickr.com/photos/adamliptrot/sets/72157600053280575/">More photos on Flickr.</a></p>
<p>Here’s to next year!</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>The Machine is Us/ing Us</title>
        <link href="https://liptrot.org/posts/the-machine-is-us-ing-us/"/>
        <updated>2007-03-13T12:00:00Z</updated>
        <id>https://liptrot.org/posts/the-machine-is-us-ing-us/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/web20.gif" alt="" >
<p>If you’ve ever struggled to explain how the web has changed and where it is going to someone, point them at <a href="http://www.youtube.com/watch?v=6gmP4nk0EOE">this video</a>. In under 5 minutes it gives you a fantastic impression of what Web 2.0 really means.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Webcards</title>
        <link href="https://liptrot.org/posts/webcards/"/>
        <updated>2007-01-25T12:00:00Z</updated>
        <id>https://liptrot.org/posts/webcards/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/microformats.jpg" alt="" >
<p><a href="http://www.whymicroformats.com/webcards/index.html">WebCards</a> is the latest browser extension which takes advantage of microformats. Built by the chaps from <a href="http://www.whymicroformats.com/pages/home">whymicroformats</a>, it exposes microformats embedded in pages - events, contact details that sort of thing. It is still in Alpha/Beta at the moment, but you can sign up for notification when it launches (initially for Firefox) - though I wish they’d get rid of the annoying pop-up about a license requirement just for viewing an information page.</p>
<p>With Firefox looking to embed microformat support in version 3 and Microsoft also taking notice, it looks like this small but powerful tool is about to get a lot more attention.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Outlook 2007 parties like it’s 1999</title>
        <link href="https://liptrot.org/posts/outlook_2007_parties_like_its_1999/"/>
        <updated>2007-01-12T12:00:00Z</updated>
        <id>https://liptrot.org/posts/outlook_2007_parties_like_its_1999/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/outlook.jpg" alt="The Outlook mail interface" >
<p>If you ever have to create HTML emails for clients, the upcoming Outlook 2007 holds a <a href="http://www.sitepoint.com/blogs/2007/01/10/microsoft-breaks-html-email-rendering-in-outlook/">nasty surprise</a>. Microsoft have decided to remove the IE rendering engine and replace it with Word’s rather more poor one. In doing so they are pushing HTML emails back to the days of HTML 4.01 and CSS1 - those specs were last updated over 8 years ago. You’ve got to admit their timing sucks, just as IE finally gets a whole lot better, they decide to rip it out.</p>
<img src="/assets/images/posts/apple.gif" alt="A complex HTML email from Apple" >
<p>Take a look at the <a href="http://msdn2.microsoft.com/en-us/library/aa338201.aspx#Word2007MailHTMLandCSS_SupportedHTMLElementsAttributesandCSSProperties">supported items</a> and you’ll see there are no background images or css floats and positioning. How does this affect us? Well, it’s kinda like the browser position in the bad old days, if you are trying to push forward with CSS-based emails, you will be in for some headaches as they have made it pretty much impossible to do this. As <a href="http://joe.hardy.id.au/blog/2006/11/21/broken-html-rendering-in-outlook-2007/">Joe Hardy notes</a>, even though align is supported, glitches make it useless - and the problems don’t stop there, check out his article for all the nasties. As Outlook is the primary company email client and comes with every Windows PC, it remains the most important email client out there for better or worse. The <a href="http://www.campaignmonitor.com/blog/archives/2007/01/microsoft_takes_email_design_b.html">Campaign Monitor</a> crew have a screenshot comparison of their CSS email newsletter in the Outlook 2000 and 2007 to show the difference the change of rendering engine really means.</p>
<p>Yes we could argue about whether HTML belongs in email, but many people expect it to be there - both clients and customers - that the view of developers is really not an issue. You cannot ignore that a graphical email has a lot more impact than a text-only one (assuming that the email client does not block the images by default, or the customer has the awareness to unblock them). Personally I think the decision to use HTML or text should be ruled by the content. HTML emails are particularly suited to e-commerce where the product is what the customer wants to see - Apple’s emails are a good example of these. Text-only emails are similarly effective where pure information is key - job board updates, blog newsletters and such. Like it or not HTML emails will continue to be requested and Microsoft have now made it more difficult to do this in a way that moves us forward.</p>
<p>They had a great opportunity to use the IE7 engine in Outlook, but instead have forced us to roll back our designs back to either fully table-based or text-based instead of the graceful degradation that CSS support could give us.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Apple iPhone</title>
        <link href="https://liptrot.org/posts/apple_iphone/"/>
        <updated>2007-01-09T12:00:00Z</updated>
        <id>https://liptrot.org/posts/apple_iphone/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/iphone.jpg" alt="iPhone device" >
<p>Despite Linksys already having brought out a product called iPhone, Apple today revealed their long-anticipated entry into the mobile/smart phone market bearing the same name. The <a href="http://www.apple.com/iphone/">iPhone</a> was among a slew of products the various pundits hoped would be announced in Steve Jobs’ keynote address at the San Francisco MacWorld conference, although pretty much the whole of the keynote was given over to this and the previously announed iTV. This meant no immediately announced updates to hardware (except a new Airport), no iWork 07 and an iTV which had the most basic feature list (although still darn cool and sure to be built upon).</p>
<p>The iPhone looks like a great piece of kit, combining a full web browser (Safari) a mail client, wireless and bluetooth access, photo software (all running on OSX), and of course a video iPod. That last bit shouldn’t be a surprise as it is Apple’s killer app for this type of hardware and the thing they have over their competitors in the smartphone market. I think we’ll see all the major players move to the touch-screen interface in the coming months as Apple’s share of customers increases, though it is interesting they moved away from the clickwheel interaction for the iPod part of the phone.</p>
<p>We may also be seeing the first device which popularises the mobile web with the inclusion of a slightly tweaked Safari browser, giving people a consistent experience as they move from desktop to iPhone as it syncs your bookmarks between the two. This may be the end of WAP 2.0 and <a href="http://en.wikipedia.org/wiki/Walled_garden_(media)">walled gardens</a>.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Microsoft homepage</title>
        <link href="https://liptrot.org/posts/microsoft_homepage/"/>
        <updated>2006-12-20T12:00:00Z</updated>
        <id>https://liptrot.org/posts/microsoft_homepage/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/ms.jpg" alt="Screenshot of the homepage" >
<p>Microsoft have recently updated their homepage (they’re moving the whole site to Sharepoint as part of the change). It is now a fully css-based page, albeit with an HTML 4.0 Transitional doctype.</p>
<p>Additionally some of the code is a little disappointing, for example instead of using heading elements they have employed classes:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>heading<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Popular Downloads<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
</code></pre>
<p>Now, I’m guessing the Sharepoint might have something to do with this, in which case it isn’t a great advert for it.</p>
<p>On the plus side, I do like the design as it seems more task-oriented such as the New PC section in the Home User area, though this is let down by the slow response of the navigation, it just doesn’t feel right.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Future of Web Design</title>
        <link href="https://liptrot.org/posts/future_of_web_design/"/>
        <updated>2006-12-19T12:00:00Z</updated>
        <id>https://liptrot.org/posts/future_of_web_design/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/logo.gif" alt="" >
<p><a href="http://www.carsonified.com/">Ryan Carson</a> must be one of the busiest guys on the web. In addition to currently selling off DropSend , launching Hey Amigo and running Vitamin and Carson Workshops, he has taken the Future of Web Apps conference from London into the States. Now he’s expanding his events portfolio to include the <a href="http://www.carsonified.com/biz-tips/learning-about-new-business-models">recently</a> announced <a href="http://www.futureofwebdesign.com/">Future of Web Design</a>. How I wish he’d launched that before I’d spent my conference budget for the year!</p>
<p>From the looks of it, the new event will cater for the more UI-centred aspect of web development of typography, layouts and branding (I think I can guess a few of the speakers already), as opposed to the more wide-ranging Apps conference. This is great as the design-type sessions at atmedia this year were heavily attended and showed that there is definitely a demand for this.</p>
<p>We’ve gone from having no large web conferences in the UK to having atmedia, dconstruct and the Future of ... in the space of a couple of years. It’s going to get to the point where I either can’t make them all or have to self-fund my way around. It’s a nice problem to have.</p>
<p>Anyway, if you think you can make it to London in April, go and sign up, registration fr FoWD opens 18th January. If it is anything like last year’s FoWA or if the line-up is a strong as the upcoming one it should be a cracking day.</p>
<p>UPDATE: Unfortunately I’ll be missing this year’s FoWA conference as I’ll be out the country, but I definitely be looking forward to FoWD.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Podcasts</title>
        <link href="https://liptrot.org/posts/podcasts/"/>
        <updated>2006-12-04T12:00:00Z</updated>
        <id>https://liptrot.org/posts/podcasts/</id>
        <content type="html"><![CDATA[
          <p>My commute means I’m in my car for a good 2 hours a day when I’m in the office, making it an ideal time to catch up on some podcasts. I find that they are ideal for the journey to work as they provide a good transition between home and the office. Sound quality on all of these is great, though with some of the shows where an interview is conducted via Skype or similar the interviewee’s volume could do with raising a touch.
I’ve now got a solid few feeds which throw up enough to keep me occupied.</p>
<h2><a href="http://www.boagworld.com/">Boagworld</a></h2>
<p>Paul Boag from Headscape produces a pretty regular podcast aimed at the beginner developer and managers. Don’t let this put out off if you don’t count yourself as either of these as Paul covers a wide range of topics and there will generally be something to pique your interest.</p>
<h2><a href="http://www.dl.tv/">dl.tv</a></h2>
<p>The only one I don’t listen to on the move as it’s a video. Patrick Norton and Robert Heron cover all things gadetry from HD tvs to Vista to digital French rabbits. I’m constantly amazed by the knowledge displayed by these two.</p>
<h2><a href="http://www.brianoberkirch.com/">Edgework</a></h2>
<p>A great series of interviews from Brian Oberkirch with some of the web luminaries such as Ryan Carson, Jason Fried and Jeff Veen to note a few recent ones.</p>
<h2><a href="http://livefromthe101.com/">Live from the 101</a></h2>
<p>Bryan Veloso of <a href="http://avalonstar.com/">Avalonstar</a> and Dan Rubin of <a href="http://superfluousbanter.org/">Superfluous Banter</a> team up to deliver a great podcast. This normally sounds a lot like a chat over a cup of coffee between two mates which makes it fantastic listening.</p>
<h2><a href="http://www.web20show.com/">The Web 2.0 Show</a></h2>
<p>Don't let the title of this one put you off, it was named way before the whole O’Reilly thing. Pretty irregular but a good listen as they have a good interview each episode.</p>
<h2><a href="http://www.thinkvitamin.com/interviews/">Vitamin</a></h2>
<p>The lovely people over at Carson post their interviews as audio files as well as a full transcript. Again great interviews with people like Dan Cederholm of Simplebits and Kevin Rose of Digg.</p>
<h2><a href="http://blog.pcmag.com/blogs/wnn/">What’s New Now</a></h2>
<p>From the same stable as dl.tv this is a general round-up of all recent technology news</p>
<p>What’s good about all these are that the personalities of the interviewers really comes across in the audio format, meaning that even if all of them talked to the same person it would result in quite different discussions.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Password Complexity</title>
        <link href="https://liptrot.org/posts/password_complexity/"/>
        <updated>2006-11-14T12:00:00Z</updated>
        <id>https://liptrot.org/posts/password_complexity/</id>
        <content type="html"><![CDATA[
          <p>It’s that time of year again and I’m on the hunt for a good car insurance deal. Not wanting to repeatedly add my details into a dozen or so sites I thought I’d make use of one of the many comparison sites to do the leg-work for me. All good so far, until I had to create a password to go with my personal information. Now most sites stipulate a pasword between say 6 and 12 characters, sometimes requiring letters and numbers if they’re being concious about security. Not so insuresupermarket.com. No, they require exactly 8 characters, letters and numbers, and no characters to recurr more than twice. I have to say I was hard-pressed to come up with a password that I’d remember which matched these tight requirements. This coming at the end of a long form-filling exercise is not the best way to garner repeat customers.</p>
<p>Ironically I now can’t find anywhere on their site to retrieve a saved quote.</p>
<img src="/assets/images/posts/car_password_error.gif" alt="Browser alert box which says your password must contain exactly 8 characters and a whole lot of other complex rules" >
<p>Not only that but their form validation only validates one field at a time, meaning that if you miss a couple of required fields you can end up having to resubmit the same form several times.</p>
<p>Thank goodness this is a once-per-year event.</p>
<h2>Response from insuresupermarket</h2>
<p>Andy Haigh, Insuresupermarket Product Manager, kindly responded to this post:</p>
<blockquote>
<p>Adam, I agree with your concern over the password complexity that we use on our Motor Insurance site. In fact we have recently being making changes to improve this and this will be going live very soon now. However, let me explain why we have such tight constraints on our password and what it is used for:</p>
<p>We use the password that the user enters for 2 reasons:</p>
<ul>
<li>for the user to retrieve their saved quote from some of the insurers sites</li>
<li>we also email you a link to our results quote page and the password is used by the user to access this</li>
</ul>
<p>The issue that we face as an aggregator, is that the insurers use a range of constraints on their password validation. This means that the password our user selects needs to meet the password constraints of ALL the insurers where we pass through the password from our site to the insurers sites. It would be much nicer if the insurers used a common set of validation rules.</p>
<p>The improvements to the password question went live yesterday (16 Nov). We now just use the password so that the user can retrieve their emailed results.</p>
</blockquote>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Joe Clark&#39;s Micropatronage Project</title>
        <link href="https://liptrot.org/posts/joe_clarks_micropatronage/"/>
        <updated>2006-11-10T12:00:00Z</updated>
        <id>https://liptrot.org/posts/joe_clarks_micropatronage/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/gave-Joe-a-fiver.jpg" alt="I gave Joe a fiver. And he's worth it! The Joe Clark Micorpatronage Project" >
<p><a href="https://joeclark.org/access/">Joe Clark</a> is one of the most enthusiastic people I’ve heard talk about accessiblity. When WCAG 2 came out he was the first to <a href="http://alistapart.com/articles/tohellwithwcag2">point out issues</a> with the documentation, and must still be among the few who have read all WCAG 2 documents. His commitment is especially evident when it comes to multimedia accessibillity (I still remember him gathering a posse to go and see captioned films after <a href="http://www.atmedia2005.co.uk/">@media 2005</a>).</p>
<p>Now Joe is starting a research project to establish a set of standards for captioning, audio description, subtitling, and dubbing. It will also develop training and certification and even create specialist fonts to use. Now all this costs money and Joe is looking for funding to enable him to go out and get the $7 million Canadian the project will need over the life of the project. He’s after $7,777 to enable him to devote all his time to fundraising for 4 months - so this is subsidence living - and is asking for help from the development community to help achieve this target. When you consider the size of the community and the sum needed I’m sure he’ll have no problem getting there, and having seen Joe’s enthusiasm I’m sure he’ll manage to get the project funding too.</p>
<p>Head over to the Open &amp; Closed Project (link removed due to ownership change) to find out more and donate.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Checkout Retail Manager</title>
        <link href="https://liptrot.org/posts/checkout_retail_manager/"/>
        <updated>2006-11-05T12:00:00Z</updated>
        <id>https://liptrot.org/posts/checkout_retail_manager/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/checkout.jpg" alt="The Checkout app icon - a store with a red and white striped awning" >
<p>From the <a href="http://www.madebysofa.com/">same chaps</a> who’ve recently launched <a href="http://www.discoapp.com/">Disco</a>, that smokin’ disc-burning app, comes <a href="http://www.checkoutapp.com/">Checkout</a>. This is a nice looking and well-featured point-of-sale application, including stock and order management. Having used a few of these myself, this seems pretty much sorted from what I can derive from the screenshots/screencasts on the site. It’s really for the smaller businesses at the moment though as you can’t network copies together, so you’d be reliant on one till, however it is ideal for small online stores where all your transactions are postal and can be handled by a single computer.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>TextMate gets all spooky</title>
        <link href="https://liptrot.org/posts/textmate_gets_all_spooky/"/>
        <updated>2006-10-31T12:00:00Z</updated>
        <id>https://liptrot.org/posts/textmate_gets_all_spooky/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/SpookyText.jpg" alt="The textmate dock icon as a halloween pumpkin" >
<p>A nice touch from <a href="http://macromates.com/">TextMate</a> - an auto-update gives the icon and project background a Halloween makeover.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Microsoft Releases Internet Explorer 7</title>
        <link href="https://liptrot.org/posts/microsoft_releases_internet_explorer_7/"/>
        <updated>2006-10-19T12:00:00Z</updated>
        <id>https://liptrot.org/posts/microsoft_releases_internet_explorer_7/</id>
        <content type="html"><![CDATA[
          <p>The day has finally dawned and <a href="http://www.microsoft.com/windows/ie/default.mspx">IE7</a> is now in the public arena. Well, sort of. Microsoft has included it as a high-priority update, so you will be prompted to install it. However there is an opt-out for those who cannot move to the new version for whatever reason and they have even released a blocker to prevent it being downloaded for companies who need to remain where they are. Read more about the release over at the <a href="http://blogs.msdn.com/ie/">IE Blog</a>.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Inside Man</title>
        <link href="https://liptrot.org/posts/inside_man/"/>
        <updated>2006-10-16T12:00:00Z</updated>
        <id>https://liptrot.org/posts/inside_man/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/InsideMan.jpg" alt="Masked robbers in a scene from the movie" />
<p>From the energetic 'Chaiyya Chaiyya' opening music and Clive Owen's short monologue you know that Spike Lee has delivered with this film.</p>
<p>An outstanding cast is the first thing which strikes you when you first see this film on the shelf - Denzel Washington, Jodie Foster, Clive Owen, Christopher Plummer and Willem Dafoe. If this film hadn't delivered I'd have been mightily disappointed. Luckily I wasn't.</p>
<p>Washington plays Keith Frazier, a hostage negotiator brought in when a bank robbery turns into a seige. Clive Owen shines as the uncompromising gang leader and much of the film takes place within the confines of the bank as the two do their respective 'jobs'.</p>
<p>If I have one gripe it is that Foster and Dafoe don't have bigger parts, but it is a credit to Lee that he managed to get them for such relatively small, unexplored supporting roles.</p>
<p>I won't elaborate on the plot as that would spoil your enjoyment, suffice to say this is a definite recommendation.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Dansk beer</title>
        <link href="https://liptrot.org/posts/dansk_beer/"/>
        <updated>2006-10-15T12:00:00Z</updated>
        <id>https://liptrot.org/posts/dansk_beer/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/DanskBeer.jpg" alt="Four bottles of Danish beer" />
<p>My brother dropped by recently on a brief stay from Copenhagen, bringing with him some splendid specimens of Danish beer. Compared to our local ales, these are both in much larger bottles and much stronger - around 7% compared to our native 5%. Needless to say I’ll be saving these for a non-school night!</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Geek up your toddlers</title>
        <link href="https://liptrot.org/posts/geek_up_your_toddlers/"/>
        <updated>2006-10-06T12:00:00Z</updated>
        <id>https://liptrot.org/posts/geek_up_your_toddlers/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/brio.jpg" alt="Promo artwork for the new toys" />
<p>Fed-up of the trainset? You can now extend it and add geek-points at the same time. Brio have brought out <a href="http://www.brio.net/network/">Brio Networkers</a>, characters based on your computer’s innards. There’s an email hub, a search-bot, a CD-burner and a recycle bin; plus of course the enemy - viruses and pop-ups. Bonus is that it links up to existing Brio-style railways so you aren’t starting from scratch.</p>
<p>The website is great too and well worth a look. Who knows, this could give us the first generation wise to the dangers of viruses.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Webcameron</title>
        <link href="https://liptrot.org/posts/webcameron/"/>
        <updated>2006-10-03T12:00:00Z</updated>
        <id>https://liptrot.org/posts/webcameron/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/cameron.gif" alt="Screenshot of the new site" />
<p>Blogs made more in-roads into the political dictionary this week with the (Beta, of course) launch of <a href="http://www.webcameron.org.uk/">webcameron</a>, David Cameron’s new site. It’s only been up a couple of days so posts are still a little thin on the ground and I’m sure he’s still getting used to the idea. Design firm <a href="http://www.headlondon.com/">Head London</a> have made a pretty good job of it all, and it fairly sings web 2.0. Everything is there - count them - Tag Cloud, Flickr feed, YouTube-style videos, guest blogs, widgets, PodCasts. Unfortunately there are a couple of non-Web2.0 code issues - a double doctype, inline styles and javascript in the hrefs, but it is light years ahead of what we would normally expect from a politician’s site.</p>
<p>The design is nice and clean, keeping away from the oh-so-obvious party-blue, and giving us a site it is actually pleasurable to be on. There is even a video clip of a conversation between (I assume) a guy from Head London and Mr Cameron regarding the sections of the site which haven’t launched and how they were going to deal with the high volume of comments. Now I would have thought that they would have given this a bit of thought beforehand, making sure that the early adopters weren’t left hanging waiting for replies. I’m sure there are several people employed full-time just moderating the comments, which all have to be approved before publication.</p>
<p>I hope that this site continues to be updated and isn’t left to be another fashion-following fad. Whether this is a good movement for politics itself I’m not sure - is it heading too far towards personality-led politics - but it does make the party more human, something which many large companies have already discovered.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>This site&#39;s DNA</title>
        <link href="https://liptrot.org/posts/this_sites_dna/"/>
        <updated>2006-08-23T12:00:00Z</updated>
        <id>https://liptrot.org/posts/this_sites_dna/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/DNA_liptrot.jpg" alt="A colourful DNA-style rendering of the site's code">
<p>There’s a <a href="http://www.dna11.com/">clever company</a> out there which can create a piece of artwork for your lounge wall based on your DNA. Apparantly they send a DNA sample kit out to you and you returm your DNA from which they make the art, and very nice it is too. But it does seem a lot of work and does cost quite a bit - labs generally don’t come cheap.</p>
<p>So why not get art from something you use every day - your favourite site, or your own site? Here’s where <a href="http://www.baekdal.com/">Thomas Baekdal</a> comes in with his <a href="http://www.baekdal.com/future/web2dna">WEB2DNA</a>. This parses your site, much like an RSS and allocates coloured lines depending on what markup it finds. Different types of site end up with their own unique artwork with more semantic sites getting brighter piccies than one which uses lots of font tags. Oh, and as Thomas points out, due to the way in which this is all constructed it works best in IE rather than the usual Firefox recommendation.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Dell starts blogging</title>
        <link href="https://liptrot.org/posts/dell_starts_blogging/"/>
        <updated>2006-07-12T12:00:00Z</updated>
        <id>https://liptrot.org/posts/dell_starts_blogging/</id>
        <content type="html"><![CDATA[
          <p>Dell has launched a company blog called <a href="http://one2one.dell.com/">one2one</a>. Unfortunately for Dell, instead of talking about things the customers want to hear about through such a interactive medium, they have chosen to use it to wave the corporate flag. Product launches and back-patting seem the order of the day. That is not what a blog is about - you can have those as nice features on your company site. Blogs are about revealing the people behind the company and maybe the behind-the-scenes work they do, the reasons the company does what it does.</p>
<p>For a company a large as Dell a blog is a golden opportunity to connect with their customers, find out what they want or what is causing them concern - much more so than any number of feedback questionnaires would. In a blog you can go back and ask for clarification and also be seen to be acting. Dell should be addressing customer support issues which seem to be the main complaint about them. Also they need to ensure their customers can find them - I could see no links to the blog from the main Dell site, even after using their search tool.</p>
<p>Don’t get me wrong, I think it is a huge thing that Dell have decided to start blogging, but I hope they manage to keep it away from the in-your-face marketing people. This could do more for their reputation than their marketing dept could imagine if done right.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Bookroll</title>
        <link href="https://liptrot.org/posts/bookroll/"/>
        <updated>2006-06-27T12:00:00Z</updated>
        <id>https://liptrot.org/posts/bookroll/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/books.jpg" alt="Covers of the new books" />
<p>There's been a surge in new web development books being announced in the past few weeks, so here's a quick run-down.</p>
<h2><a href="http://www.clagnut.com/blog/1751/">Web Accessibility: Web Standards and Regulatory Compliance</a></h2>
<p>A welcome addition, especially in light of the upcoming WCAG 2.0 release. A replacement on the shelves for the good, but aging <a href="http://www.amazon.co.uk/exec/obidos/ASIN/1904151000/qid=1151433881/sr=8-5/ref=sr_8_xs_ap_i5_xgl/203-0199538-5094339">Accessible Web Sites</a> from the now defunct Glasshaus, it will hopefully be covering the accessibility issues of some of the newer techniques such as image replacement and oh I dunno, ajax? Looking at the contributing author list this looks like it will be a good read.</p>
<h2><a href="http://www.quirksmode.org/book/">Ppk on JavaScript</a></h2>
<p>This is one I'm waiting for, having made my merry way through <a href="http://adactio.com/">Jeremy Keith's</a> <a href="http://www.domscripting.com/book/">DOM Scripting (for good, not evil)</a>, I've been wanting more, but also wanted to avoid polluting my clean js knowledge with old-school techniques. <a href="http://www.quirksmode.org/blog/archives/2006/06/more_about_the.html">Ppk says this is definitely a sequel kind of read</a> so it should work out quite well.</p>
<h2><a href="http://www.amazon.co.uk/exec/obidos/ASIN/0321410971/ref=wl_itt_dp/203-0199538-5094339?%5Fencoding=UTF8&amp;coliid=I2UF5S1HO2XET1&amp;colid=SX7BU9ORG1N5">Transcending CSS: The Fine Art of Web Design</a></h2>
<p>I missed <a href="http://www.stuffandnonsense.co.uk/">Andy's</a> talk at this year's atmedia - damned 2 tracks! - but this may make up for it. It looks to be a 'think past the restrictions of CSS' vibe. Not much info apart from that, so we'll have to wait and see.</p>
<h2><a href="http://www.amazon.co.uk/exec/obidos/ASIN/0596102356/ref=wl_itt_dp/203-0199538-5094339?%5Fencoding=UTF8&amp;coliid=I6J8985V0JQQS&amp;colid=SX7BU9ORG1N5">Building Scalable Web Sites</a></h2>
<p><a href="http://www.iamcal.com/">Cal Henderson</a> did a great stint at the <a href="https://liptrot.org/journal/entries/carson_cal/">Carson Summit</a> and I hope this book follows his presenting style rather than the more dry style O'Reilly is more known for.</p>
<h2><a href="http://beginningwebdesign.com/">Learn web design the right way</a></h2>
<p>From all the reviews I've seen this is the book to buy anyone you know who is just getting into web design. Something we've been missing and one I'm going to recommend.</p>
<h2><a href="http://htmlmastery.com/">HTML Mastery</a></h2>
<p>Another Friends of Ed book, this time by <a href="http://joeblade.com/">Paul Haine</a> and I'm guessing a non-official companion to <a href="http://www.andybudd.com/">Andy Budd's CSS Mastery</a>.</p>
<h2><a href="http://www.amazon.co.uk/exec/obidos/ASIN/0321385551/qid=1151434552/sr=1-2/ref=sr_1_2_2/203-0199538-5094339">Designing With Web Standards, 2nd edition</a></h2>
<p>A <a href="http://www.zeldman.com/2006/06/16/dwws-2e-cover-preview/">green cover</a> for the new edition. Question is, will it still be referred to as 'the orange book'?</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>BBC Blogging</title>
        <link href="https://liptrot.org/posts/bbc_blogging/"/>
        <updated>2006-06-26T12:00:00Z</updated>
        <id>https://liptrot.org/posts/bbc_blogging/</id>
        <content type="html"><![CDATA[
          <p>The BBC has launched a new news blog called <a href="http://www.bbc.co.uk/blogs/theeditors/">The Editors</a>. After being initially disappointed that it wasn't an editorial viewpoint on the news (though that is dealt with <a href="http://www.bbc.co.uk/blogs/nickrobinson/">elsewhere</a>), I was pleasantly surprised. The Editors comes across as an in-depth Points of View, giving a personable face to a large corporation and covering the reasons behind some of the decisions the BBC makes which impact on their customers.</p>
<p>Informing customers is a great reason for a company publishing a blog, especially one as large and as public as the BBC. They've also ensured that they have gathered staff from the web, TV and radio, giving a wide base of topics, each with their own RSS feed.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>36 Quai des Orfèvres</title>
        <link href="https://liptrot.org/posts/36_quai_des_orfevres/"/>
        <updated>2006-06-19T12:00:00Z</updated>
        <id>https://liptrot.org/posts/36_quai_des_orfevres/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/36.jpg" alt="Scene from the movie, Daniel Auteuil and Daniel Duval looking serious in long dark raincoats in a blue-tinged outdoor setting" />
<p>This was a recommendation which got me past my usual reluctance to look at subtitled movies, and I'm glad it did.</p>
<p>The 36 of the title refers to the Parisian HQ of the Criminal Division of the DRPJ - the equivalent of the UK's Scotland Yard.</p>
<p>The film follows the rivalry of two captains - Vrinks of the BRI (the anti-gang squad) and Klein, the head of the BRB (anti-robbery) - as they bash heads over the hunting of a vicious armoured car gang. It's had its fair share of comparisons to Heat, but 36 doesn't characterise the criminals so much as it concentrates on the darker side of policing on the edge as the two captains race to stop the next hit. Lines get blurred between the cops and the robbers, Vrinks and Klein pushing the envelope (anyone who's a fan of The Shield will recognise this).</p>
<p>Gérard Depardieu and Daniel Auteuil shine as the two leads, presenting the gritty side of Parisian policing. This is bound to be remade into a Hollywood version, hopefully when they do they'll keep the darkness of it all.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Back from @media 2006</title>
        <link href="https://liptrot.org/posts/back_from_atmedia_2006/"/>
        <updated>2006-06-19T12:00:00Z</updated>
        <id>https://liptrot.org/posts/back_from_atmedia_2006/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/atmedia_dan.jpg" alt="Dan on stage" />
<p>I think <a href="http://www.vivabit.com/bollocks/">Patrick</a> has put himself in a bit of a tight spot. Looking at my bookshelf I can see at least 6 books authored by people who presented this year. Making next year's conference as good as this year's is going to be a real challenge. It was really great to see some familiar faces among the crowd and get to meet a bunch of new ones. The conference was split along two tracks which caused a good few people to wish they could split themselves in half and it meant some really tough decisions - how do you decide between <a href="http://www.stuffandnonsense.co.uk/">Andy Clarke</a> and <a href="http://www.tantek.com/">Tantek Celik</a>?</p>
<p>Anyway here are my best bits:</p>
<p>The WCAG panel encouraging people to actually read the 2.0 draft before making their mind up (and finding out about the quick references they've just put out); though most people agreed having <a href="http://joeclark.org/">Joe Clark</a> there would have made it more of a debate.</p>
<p><a href="http://www.veen.com/jeff/">Jeff Veen's</a> 'Next Generation of Web Apps' presentation was the highlight of the whole conference and a great way to finish off day 1. I've always wanted to see Jeff speak as it was his <a href="http://www.amazon.co.uk/exec/obidos/ASIN/0789723700/qid=1150712536/sr=1-1/ref=sr_1_2_1/203-0199538-5094339">Art and Science of Web Design book</a> which gave me a huge leg-up in web design and he didn't disappoint, giving an inspiring look at the state of the industry, how far we've come and where we might be going next.</p>
<p>The social calendar sprang back into action with Patrick managing to convince the bar to open up for football and after a win and a few drinks it was down to the Texas Embassy for food with <a href="http://www.morethanseven.net/">Gareth</a> and <a href="http://thinkdrastic.net/">Olly</a>.</p>
<p><a href="http://www.simplebits.com/">Dan Cederholm</a> kicked of day 2 with a look into making sites bulletproof with examples from his <a href="http://corkd.com/">Cork'd</a> site and re-energised everyone after the excesses of the night before.</p>
<p><a href="http://www.cameronmoll.com/">Cameron Moll</a> told us how to look towards providing content to mobile devices and gave everyone some really useful tips to go away with. Yahoo!'s <a href="http://nate.koechley.com/blog/">Nate Koechley's</a> look at how they implemented standards into 3 of their upcoming products shows us how far the community has come in the past couple of years. Chatting to him afterwards about microformats and social tagging, he came across as a really nice guy.</p>
<p>Speaking of microformats, Tantek Celik enthused the whole lot of us with a run-down of what they are and the potential of them - along with examples of them out in the wild.</p>
<p>The final session was a great light-hearted 'hot topics' panel most ably hosted by <a href="http://adactio.com/journal/">Jeremy Keith</a> - a great way to round of the day, followed by beer in the pub (<a href="http://www.webexposia.com/">CJ</a> - are you going to start importing UK beer to Canada?).</p>
<p>What I noticed this year was a move towards more strategic thinking rather than nuts and bolts stuff. Also the presentations were without an exception amazing - from the crafted slides to the practiced speakers - coupled with a great venue this was a top class event. Congrats to Patrick and here's to @media 2007.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Movies and Microformats</title>
        <link href="https://liptrot.org/posts/movies_and_microformats/"/>
        <updated>2006-06-19T12:00:00Z</updated>
        <id>https://liptrot.org/posts/movies_and_microformats/</id>
        <content type="html"><![CDATA[
          <p>Following <a href="http://www.vivabit.com/atmedia2006/sessions/#microformats">Tantek‘s</a> inspiring presentation at this year’s <a href="/posts/back_from_atmedia_2006/">@media</a>, I’ve decided to step up my game a little and seeing a great movie at the weekend gave me the perfect opportunity to try it all out.</p>
<p>I’ve kept the whole thing pretty simple - the <a href="http://www.microformats.org/">Microformats</a> site has a bunch of examples of microformats in use already and hReview was the obvious choice.</p>
<p>The code runs like this. The <a href="http://microformats.org/wiki/hreview">hReview</a> only requires the item being reviewed, but obviously for a review to be useful it needs a bit extra.</p>
<p>As the power of microformats comes from them being pulled out of context (eg <a href="http://kitchen.technorati.com/search/">Technorati’s new search tool</a>), I wanted to attach my name and url to the review. This is done via the reviewer item, wrapped up in <a href="http://microformats.org/wiki/hcard">hCard</a>.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>reviewer vcard<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>url fn<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://www.liptrot.org/about<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Adam Liptrot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
</code></pre>
<p>The reviewer also has the date of the review assigned to it. Dates are something which have to be machine-readable and so must have a format which is common.</p>
<p>This format is contained within the title attribute of the abbr tag, as it is effectively abbreviating the more readable ‘June 19th 2006’ or even ‘yesterday’. So we add the following after the link within the reviewer span:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>abbr</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>dtreviewed<span class="token punctuation">"</span></span> <span class="token attr-name">title</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>20060619<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>June 19th 2006<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>abbr</span><span class="token punctuation">></span></span>
</code></pre>
<p>Then we have the mandatory item which I’ve wrapped in a link to the IMDB site reference (oh, and I’ve added a language tag to the link too, as it’s a French film).</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>item<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>fr<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>url fn<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://www.imdb.com/title/tt0390808/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>36 Quai des Orfèvres<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
</code></pre>
<p>Put it all together with a rating and the review itself and we get the full entry.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>hreview<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>reviewer vcard<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>url fn<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://www.liptrot.org/about<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Adam Liptrot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>abbr</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>dtreviewed<span class="token punctuation">"</span></span> <span class="token attr-name">title</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>20060619<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>June 19th 2006<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>abbr</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>item<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>fr<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>url fn<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://www.imdb.com/title/tt0390808/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>36 Quai des Orfèvres<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">></span></span>Rating:<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>rating<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>4<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span> out of 5<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>description<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>Movie review goes here...<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
</code></pre>
<p>At some point in the next few weeks I’ll update my previous movie reviews in the same way.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Smackbook Pro</title>
        <link href="https://liptrot.org/posts/smackbook-pro/"/>
        <updated>2006-05-25T12:00:00Z</updated>
        <id>https://liptrot.org/posts/smackbook-pro/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/smackbook.jpg" alt="A Macbook being smacked on the side of the screen" />
<p>The MacBook Pro laptops have a motion-sensor in them, designed to prevent damage to the hard-drive when dropped. This has already been put to admirable use for <a href="http://isnoop.net/blog/2006/05/20/macsaber-turn-your-mac-into-a-jedi-weapon">Mac lightsabre fights</a> (I can imagine the calls that would be put into tech repair from people renacting the Darth/Obi Wan fights).</p>
<p>Here's a much more <a href="http://blog.medallia.com/2006/05/smacbook_pro.html">work-friendly use</a>. This bit of scripting uses the motion-sensor to change virtual desktops when the monitor is tapped. <a href="http://www.youtube.com/watch?v=6uvQTTPr9Rw&amp;search=macbook%20pro">The video</a> is just great and it looks so much easier than a cluster of key combos.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Did someone say we&#39;d won?</title>
        <link href="https://liptrot.org/posts/did-someone-say-we-won/"/>
        <updated>2006-05-17T12:00:00Z</updated>
        <id>https://liptrot.org/posts/did-someone-say-we-won/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/stylegala_wsa.gif" alt="Stylegala, a publication about web design and standards. Web Standards Awards - form, function combined" />
<p>Coincidentally, <a href="http://www.webstandardsawards.com/">Web Standards Awards</a> is closing at the same time that <a href="http://www.stylegala.com/">Stylegala</a> is up for sale. Does this mean that the standards war is won? Well, no. WSA reached the 100-site milestone in January and Stylegala has had a distinct lack of new additions in the past few months. The WSA is much more along the lines of the Web Standards Project, the core of the site is the promotion of standards, with sites judged by the <a href="http://www.webstandardsawards.com/criteria/#WJudges">great and the good of web design</a>. The annoucement says it all:</p>
<blockquote>
    It's no longer a myth that you can produce a stunning site with Web Standards
</blockquote>
<p>and the 100 site mark is a good place to bow out. Plus these guys have a lot of other stuff to do.</p>
<p>Job done. War won? Nope, there are still an awful lot of sites out there partying like it's 1999, but the tide has turned. The WSA stands as a showcase to standard-compliant design. Stylegala on the other hand is a gallery, a place for inspiration, although it has actually been more than just a gallery for some time. However the gallery does seem to have fallen by the wayside since the heady days of March 2005 when 20 sites were added. In the past few months only a couple of sites have made it in, despite, as the WSA declares:</p>
<blockquote>
    beautiful sites with beautiful code are being produced by the hundreds; every month, every week, every day
</blockquote>
<p>Maybe the problem is that it is too difficult to seperate out just 10 sites a month to feature - what about the ones that don't make it, are they not worthy? This is probably why many recent sites have been high-profile ones (like <a href="http://veerle.duoh.com/index.php">Verlee</a> and <a href="http://www.uxmag.com/">UX Magazine</a> which everyone can put on a pedestal. Stylegala looks like it has just been overwhelmed.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Apple localization</title>
        <link href="https://liptrot.org/posts/apple-localization/"/>
        <updated>2006-05-01T12:00:00Z</updated>
        <id>https://liptrot.org/posts/apple-localization/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/macmini.gif" alt="Select your Mac Mini screenshots from the UK and US sites" />
<p>Browsing around the <a href="http://store.apple.com/">Apple store website</a>, I came across an interesting example of localization. Localization is the customisation of a product to a particular market, whether that be changing menus or content to a different language or modifying aspects of the prduct to take account of differences in culture.</p>
<p>On the Mac Mini page of the UK Apple store the product description goes “More expandability options and ports”, whilst on the US page it says “More expansion options and ports”. Not sure what cultural differences they are taking account of here, but for me the US description certainly sounds better.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Reboot the BBC</title>
        <link href="https://liptrot.org/posts/reboot-the-bbc/"/>
        <updated>2006-04-27T12:00:00Z</updated>
        <id>https://liptrot.org/posts/reboot-the-bbc/</id>
        <content type="html"><![CDATA[
          <p>It’s a pity the BBC didn’t get <a href="http://open.bbc.co.uk/reboot/">this sorted</a> to coincide with the general <a href="http://www.cssreboot.com/">CSS reboot of 1st May</a>, but it is nevertheless a cool project - not least as the winning design gets to have their design as the real homepage for a day.</p>
<p>This competition does raise some interesting points though.</p>
<p>The related blog states that :</p>
<p>It’s your homepage, (it’s your BBC) and I want to offer everyone the opportunity to feedback to us what they want it to look like.</p>
<p>OK, but I think it’s a safe bet that the submitted designs won’t have any meaningful user-testing behind them (though I’d like to be proved wrong) and so will refect the opinions of the designer. Granted the BBC might be able to derive some usability metrics from looking at common themes within the designs, such as highlighting a certain section of the site.</p>
<p>Also worth thinking about is that the BBC homepage is an international page. How will the submissions reflect the 2 versions of the page - the UK side and the world side? (Some of these questions might have been answered in the FAQs but the site has been largely unavailable all day.)</p>
<p>I’m looking forward to see the designs come in, might even get around to doing one myself.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>The Microsoft Mac Lab</title>
        <link href="https://liptrot.org/posts/the-microsoft-mac-lab/"/>
        <updated>2006-04-21T12:00:00Z</updated>
        <id>https://liptrot.org/posts/the-microsoft-mac-lab/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/MacMini.jpg" alt="Shelves of Mac Minis" />
<p>David Weiss has <a href="http://davidweiss.blogspot.com/2006/04/tour-of-microsofts-mac-lab.html">a tour of the Mac lab</a> at Microsoft on his blog. What hits you is the amount of testing they do, the huge amount of cabling - and yes the 150 Mac minis they use for automation. Lucky for Microsoft Apple don’t produce that many configurations.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>More stuff to read</title>
        <link href="https://liptrot.org/posts/more-stuff-to-read/"/>
        <updated>2006-04-18T12:00:00Z</updated>
        <id>https://liptrot.org/posts/more-stuff-to-read/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/vitamin.jpg" alt="Vitamin homepage" />
<p>Dang it! As soon as I start getting my RSS reader under control, along come 2 sites which are sure to demand my attention.</p>
<p>From the talented hands of <a href="http://joshuaink.com/">John Oxton</a> comes <a href="http://bitesizestandards.com/">Bite Size Standards</a>, a multi-author site which aims to give good advice but in manageable “while the kettle’s boiling” chunks. I especially like the further reading references at the bottom of each post to let you delve a little deeper if you’re hankering after more depth.</p>
<p>Then there’s <a href="http://www.thinkvitamin.com/">Vitamin</a>, a web magazine from <a href="http://www.carsonsystems.com/">Carson Systems</a> which visually reminds me of <a href="http://www.uxmag.com/">UX Magazine</a>, but has a wider remit and appears more hands-on. Vitamin has a stack of great content to launch with, and no wonder, just take a look at that <a href="http://www.thinkvitamin.com/advisoryboard.php">author list/advisory board</a>. I’m off to cull some of my RSS feeds to make room in my day for all this stuff.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Eolas hits</title>
        <link href="https://liptrot.org/posts/eolas-hits/"/>
        <updated>2006-04-12T12:00:00Z</updated>
        <id>https://liptrot.org/posts/eolas-hits/</id>
        <content type="html"><![CDATA[
          <p>The Eolas vs Microsoft case has finally hit home. Microsoft released the <a href="http://www.microsoft.com/technet/security/advisory/912945.mspx">updates for IE</a> today, including the patch to require an <a href="http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/overview/activating_activex.asp">extra click for ActiveX controls</a>. Microsoft however have given us an extra 2 months by including a hotfix which delays the impact until June. So if you haven’t updated your code, now would be a good time.</p>
<p>I’m with ole <a href="http://www.w3.org/2003/10/27-rogan.html">Tim Berners Lee</a> on this one. Good on Microsoft for not backing down to patent extortion, far too much of that malarkey goes on as it is, though whether it’ll end up doing them more damage with the community than good we’ll only see later down the road. Eolas, can’t you see you’re antagonizing just about everyone out there?</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Dunstan&#39;s back</title>
        <link href="https://liptrot.org/posts/dunstans-back/"/>
        <updated>2006-04-10T12:00:00Z</updated>
        <id>https://liptrot.org/posts/dunstans-back/</id>
        <content type="html"><![CDATA[
          <p>Well, not quite yet. Dunstan Orchard is showing off a possible <a href="http://www.flickr.com/photos/dunstan/tags/blog/">design for his new blog on Flickr</a>. I go with Jon Hick’s comment and say release it now and get posting - <a href="http://1976design.com/blog/">you’ve been gone too long</a>!</p>
<p>The white text on black seems to be the trend for 2006 (<a href="http://veerle.duoh.com/">Verlee</a>, <a href="http://www.dustindiaz.com/">Dustin Diaz</a>).</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Microsoft Expression</title>
        <link href="https://liptrot.org/posts/microsoft-expression/"/>
        <updated>2006-04-10T12:00:00Z</updated>
        <id>https://liptrot.org/posts/microsoft-expression/</id>
        <content type="html"><![CDATA[
          <p>Microsoft has announced their new development software, called <a href="http://www.microsoft.com/products/expression/en/default.mspx">Expression</a> (and so the inevitable death of Frontpage by June 2008 - yey!). It is a set of graphic, interactive and web software which is aimed at the Windows application and web developers. I don’t know about this one, can it be good enough to pry away creatives from their Macs and Adobe products? Does anyone have time to learn another product? The first 2 packages are available now for trial, I’m going to have a play with the web segment when it comes out, but I have a feeling it’ll be one of those trials I end up removing rather than upgrading.</p>
<p>From the video-demo the web part looks a lot like most other visual development environments for the web, though it appears to have a rendering engine built from the ground-up to be standards-compliant and that isn’t IE7. Why not? Personally I’d still be testing everything in multiple browsers starting with FireFox. Built-in rendering engines just make me suspicious.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>CSS Naked Day</title>
        <link href="https://liptrot.org/posts/css-naked-day/"/>
        <updated>2006-04-05T12:00:00Z</updated>
        <id>https://liptrot.org/posts/css-naked-day/</id>
        <content type="html"><![CDATA[
          <p>Where’d the design go? Well, it’s CSS Naked Day, an annual event to promote Web Standards. By producing semantic code this site should still make sense with the styles turned off.</p>
<p>To know more about why styles are disabled on this website visit the <a href="http://naked.dustindiaz.com/">Annual CSS Naked Day website</a> for more information.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>CNN Subtle Redesign</title>
        <link href="https://liptrot.org/posts/cnn-subtle-redesign/"/>
        <updated>2006-03-28T12:00:00Z</updated>
        <id>https://liptrot.org/posts/cnn-subtle-redesign/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/cnn.gif" alt="CNN navigation showing a select input" />
<p>CNN has made a slight shift in th elayout of its US homepage. By moving the navigation to a horizontal type, they have made more room for their video offerings.</p>
<p>Unfortunately they have run out of room and had to relegate some of the sections to a drop-down listing. I’m sure they could have put RSS, CNNtoGo et al to a ‘utility’ bar and allowed those 5 sidelined sections to have presence in the main bar.</p>
<p>Not to mention it doesn’t work if you are running around with javascript turned off.</p>
<p>I think the resolution thing is less of an issue, strangely enough. 1024 is becoming a more defacto standard and as with other sites moving to this they have put the less important content on that side of the screen, so as those browsing with smaller viewports still get the page’s message.</p>
<p>However I do think that CNN should have maybe looked at a browser-width-dependent layout.</p>
<p>CNN’s web team probably have a terrible time juggling stakeholders, but if a site is unusable or difficult to navigate then everyone is going to lose out.</p>
<p>Why shouldn’t big sites have good IA and design? The BBC site always gets cited as a pillar of the web community by developers and the public. Sure it is difficult to do well, but the CNN nav bar now just feels thrown together, and I think is harder to read than their vertical version.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Illustrating A List Apart</title>
        <link href="https://liptrot.org/posts/illustrating-a-list-apart/"/>
        <updated>2006-03-21T12:00:00Z</updated>
        <id>https://liptrot.org/posts/illustrating-a-list-apart/</id>
        <content type="html"><![CDATA[
          <p>Kevin Cornell’s illustrations have become a trademark of <a href="http://alistapart.com/">A List Apart</a>. In an article on <a href="http://www.bearskinrug.co.uk/_articles/2006/03/20/the_process/">Bearskinrug</a> he explains how he approaches the job of illustrating, taking ALA as an example.</p>
<p>Reading about his design process you can’t help but see definite parallels with web design. In particular is the concept of preliminary sketches done in the rough and in black and white - identical to the idea of wireframing in greyscale to prevent clients fixating on colours. One approach I found useful was that he charges for revisions to ensure revisions are meaningful and kept to a minimum. This is something I’ll be taking into my process - perhaps the first 2 revisions are free and subsequent ones are charged at a fixed rate.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Comment Is Free - and political</title>
        <link href="https://liptrot.org/posts/comment-is-free-and-political/"/>
        <updated>2006-03-15T12:00:00Z</updated>
        <id>https://liptrot.org/posts/comment-is-free-and-political/</id>
        <content type="html"><![CDATA[
          <p><a href="http://commentisfree.guardian.co.uk/">Comment Is Free</a>, a new editorial blog from the Guardian has just launched.</p>
<p>After following <a href="http://www.benhammersley.com/">Ben Hammersley‘s</a> posts about building this site I was interested to see how it panned out.</p>
<p>I do welcome the Guardian’s creation of an editorial site where we can read about opinions rather than just the dry facts. it is something which I think has been lacking from online news sites for a long time and I’m sure Comment Is Free will find some big names to contribute over the next few weeks. The addition of open comments to those posts is something more of a risk.</p>
<p>I can imagine the bosses at the Guardian being a little concerned about opening up a blog which will include posts on political subjects to the general public. Politics is one of those subjects which you are always warned away from at dinner parties in case it turns into an impromtu rehash of Bugsy Malone.</p>
<p><a href="http://commentisfree.guardian.co.uk/george_galloway/2006/03/israeli_aggression_british_bet.html">George Galloway's post</a> has resulted in something of a heated exchange but just like the <a href="http://www.newsvine.com/">Newsvine</a> entry on the same subject has one or two well thought out comments which add to the information provided by the main post.</p>
<p>I’m still unsure as to how much goodness these systems will give. You still have to wade through some rubbish to find the good comments on both sites. I think the most interesting thing they will contribute is the potential for providing an international viewpoint on a news event. When the BBC opens up certain stories with a “Have your Say” section it more often than not adds value. This may be because they are able to moderate the posts more fully and I think this is where the Guardian and Newsvine will need to concentrate their efforts.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>WaSP Redesign</title>
        <link href="https://liptrot.org/posts/wasp-redesign/"/>
        <updated>2006-03-15T12:00:00Z</updated>
        <id>https://liptrot.org/posts/wasp-redesign/</id>
        <content type="html"><![CDATA[
          <p>The <a href="http://www.webstandards.org/">Web Standards Project</a> has launched their new site at SxSW. Andy Clarke a WaSP member himself was responsible for the design (<a href="http://www.stuffandnonsense.co.uk/archives/designing_for_the_web_standards_project.html">see his post for more details</a>) and very nice it is too. I wasn’t too keen on it when I initially saw it - I think it was the industrial gold and black - but as you walk though it you notice all the little design details which really pulls the site together.</p>
<p>The reorganisation seems to focus attention more on what the team does, in particular the Task Forces. A welcome addtion is a list of who the WaSP members are and who is in which Task Force.</p>
<p>Also of note is that the site will be allowing comments on articles for the first time which along with the opening of their annual meeting at SxSW to the delegates points to a more receptive organisation. Now that can only be a good thing.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Ajax Patented</title>
        <link href="https://liptrot.org/posts/ajax-patented/"/>
        <updated>2006-02-24T12:00:00Z</updated>
        <id>https://liptrot.org/posts/ajax-patented/</id>
        <content type="html"><![CDATA[
          <p>Small web firm <a href="http://www.balthaser.com/">Balthaser</a> has been <a href="http://news.com.com/Company+claims+patent+win+in+online+rich+media/2100-1030_3-6042085.html?tag=st.ref.goo">granted a patent</a> for using Flash, Flex, Java, Ajax, and XAML over the internet.</p>
<p>I hope this is a non-issue. The guy says he won't enforce the patent himself but will sell it off to the highest bidder.</p>
<p>Am I the only one who thinks that it is ironic that someone who says he's been using this technology since the 1990s, still has a full-Flash site with non skip link?</p>
<p>He sounds like the most annoying bloke ever. &quot;My mom saw me struggling, and one day said, 'Why don't you figure out a way to bottle up that Balthaser magic.'&quot; Urgh. Just the fact that he could even think of patenting something like this earns him the disrespect of all the web developers out there and proves that he just doesn't get it.</p>
<p>I can't see how this will make it past the first legal test. It certainly doesn't appear that he was influential in the development of any of these technologies.</p>
<p>I'm off to patent electricity. I've been using it for 30 years now and I'm sure no-one else has.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>To Podcast or not to Podcast?</title>
        <link href="https://liptrot.org/posts/to-podcast-or-not-to-podcast/"/>
        <updated>2006-02-24T12:00:00Z</updated>
        <id>https://liptrot.org/posts/to-podcast-or-not-to-podcast/</id>
        <content type="html"><![CDATA[
          <p>Jeremy Keith has posted a <a href="http://adactio.com/journal/1091/">Podcast of the Carson Summit</a> using the mp3s from Carson Workshops. He’s done this because Carson placed <a href="http://www.carsonworkshops.com/summit/">links to the mp3s</a> and called them Podcasts. Whilst the usefulness of having a podcast for a knowingly limited number of files (when podcasts are more suited to regular postings) is questionable, the point Jeremy is making is that the term Podcast is being used for any mp3 download.</p>
<p>This is something I’ve been trying to drill into people at work. However Podcast is a buzz term and whilst inaccurately used, does tend to fire people’s imagination more.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Scanner Darkly</title>
        <link href="https://liptrot.org/posts/scanner-darkly/"/>
        <updated>2006-02-21T12:00:00Z</updated>
        <id>https://liptrot.org/posts/scanner-darkly/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/scanner.jpg" alt="Still from the movie showing Keanu Reeves digitised face" />
<p>I always have mixed feelings about movies made out of Philip K. Dick books as they are not always well-executed. But I always live in hope that someone out there will do his books justice with a new movie.</p>
<p>However this one may be different. <a href="http://wip.warnerbros.com/index.html?site=ascannerdarkly">Scanner Darkly</a> isn’t of one of his stories I’ve read, so have no preconceptions about how it should play out. Shot in a cross between comic book and live action it is definitely eye-catching.</p>
<p>Come on, give us a release date!</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Measure Map bought by Google</title>
        <link href="https://liptrot.org/posts/measure-map-bought-by-google/"/>
        <updated>2006-02-17T12:00:00Z</updated>
        <id>https://liptrot.org/posts/measure-map-bought-by-google/</id>
        <content type="html"><![CDATA[
          <p>It seems that <a href="http://blog.flickr.com/flickrblog/2005/03/yahoo_actually_.html">everyone</a> is getting <a href="http://upcoming.org/news/archives/2005/10/05/yahoo_ac/index.php">aquired</a> these days.</p>
<p>Of course the sign of a great product must be when it <a href="http://googleblog.blogspot.com/2006/02/here-comes-measure-map.html">gets bought before it’s even launched</a>.</p>
<p><a href="http://www.measuremap.com/">MeasureMap</a> is a web analytics service created by Jeff Veen and others at Adaptive Path. Jeff is moving to Google with the product.</p>
<p>I’ve been waiting for MeasureMap to launch ever since I saw hints of the UI a while back and had been wondering why it was taking so long to hit the shelves, I’m guessing this had something to do with it.</p>
<p>The question everyone must be asking is, how is this going to align with the similarly shy Google Analytics.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Molly and Andy go to Newcastle</title>
        <link href="https://liptrot.org/posts/molly-and-andy-go-to-newcastle/"/>
        <updated>2006-02-16T12:00:00Z</updated>
        <id>https://liptrot.org/posts/molly-and-andy-go-to-newcastle/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/layer.gif" alt="CSS Layer Cake" />
<p><a href="http://www.molly.com/">Molly Holzschlag</a> and <a href="http://www.stuffandnonsense.co.uk/">Andy Clarke</a> gave a talk last night at the North East Usability and Accessibility Group at Northumbria University, entitled “Standards and the Design of Usable Sites”. Congrats to <a href="http://tomsimcox.com/blog/">Tom</a> and the University team for putting on a good event - with wine and nibbles too!</p>
<p>Molly opened the show with a run-down of the history of standards on the web. It’s amazing how far the web has come in such a short time and having hand-coded many a table-based page in the early days, I don’t think I could ever go back to coding that way - in fact I think it would take me quite a while to remember all the tricks we used to have to employ to get the pages to work in the browsers of the day. She did a great overview of modern web standards and the Layer Cake way of coding - structure, content, presentation, behaviour - though every time she used the term, the film kept jumping into my head.</p>
<p>An interesting thing to which Molly alluded was that even if the IE team got the browser up to spec. with all standards/recommendations, then they still have to ensure it plays nicely with Windows Vista and this requirement would overrule any standards in the case of conflict. Personally this is not something I’d even thought about having an impact on the development of IE. I could understand (to an extent) them not wanting to break all their big client’s sites, but this adds another dimension. I can’t imagine all the pressure the IE team are getting from all sides in the run-up to the launch of IE7.</p>
<p>Molly also mentioned the use of microformats and their potential for the future of the web. After hearing them talked about at the Carson Summit they are something I’ll be taking more notice of.</p>
<p>Andy’s talk focussed on the extent of user experience on the web. He illustrated the old way of doing things when trying to provide accessible content to as many people as possible - Betsie on the BBC and <a href="http://www.amazon.com/access">Amazon Access</a>. His point was that these methods may provide the main content of the full version but provide none of the user experience which is available on the ‘full’ version.</p>
<p>He then ran through the design of elements of <a href="http://www.karova.com/">Karova store</a> and how they employed ‘Tesco testing’ to get some eye-opening usability data - in this case the difference in how men and women process on-scren layouts.</p>
<p>Molly and Andy are great public speakers and a big thanks to them for making the effort to come to Newcastle.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Ajax Workshop</title>
        <link href="https://liptrot.org/posts/ajax-workshop/"/>
        <updated>2006-02-14T12:00:00Z</updated>
        <id>https://liptrot.org/posts/ajax-workshop/</id>
        <content type="html"><![CDATA[
          <p>After the Carson Summit I had a spare day before ClearLeft/Jeremy Keith’s Ajax workshop. This meant I had time do give my brain some downtime before ramming it full of more web knowledge again.</p>
<p>Jeremy and the ClearLeft crew did a great job putting the event on, from greeting the attendees in the hotel lobby to providing an ad hoc wireless network.</p>
<p>The morning was pimarily taken up with a review of Javascript syntax and an overview of DOM scipting and the Ajax proper started after lunch. The morning’s tutoring was definitely worth it though as Ajax relies on this to perform. Jeremy is a great speaker and managed to explain the ins and outs of Ajax in a way which cause a lightbulb to go on in my head at least a couple of times. As anyone who has seen him speak before or has read his book will know, he is a great advocate of unobtrusive scripting, using hooks in the code to tie in your javascript. He applies the same sort of graceful degredation to his Ajax coding.</p>
<p>His approach is to code the application so it works as a traditional page with the page refreshes that entails. Then add in the Ajax to ‘Hijax’ the page, diverting the call to the Ajax code if the client browser supports it. This relies on the server-side architecture being coded in a modular way. What this means is that you can target the server-side code for a particular module within a page. This may require some change of coding methodology, but it will mean you only have to code it once for both standard calls and Ajax calls.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Munich, the movie</title>
        <link href="https://liptrot.org/posts/munich-the-movie/"/>
        <updated>2006-02-14T12:00:00Z</updated>
        <id>https://liptrot.org/posts/munich-the-movie/</id>
        <content type="html"><![CDATA[
          <img src="/assets/images/posts/munich.jpg" alt="Scene from the movie with Geoffrey Rush and Eric Bana" />
<p>This was one of those movies where you seem to recognise many of the actors, but can't generally place them. A bit of research on IMDB sorted me out.</p>
<p>Ephraim, the Mossad hander was played by Geoffrey Rush, who for some reason kept reminding me of Sgt Bilko, and who played the ghostly Captain Barbossa in Pirates of the Caribbean.Then there was Eric Bana who also played Hector in Troy and coincidentally starred in Black Hawk Down which I watched on the way back from my London trip.</p>
<p>The movie was a pleasant surprise in that it balanced good dialogue with a fast-paced script that never lingered too long, coupled with lots of location changes to make a very visually appealing movie.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Carson Summit Part 1: Joshua Schachter - Delicious</title>
        <link href="https://liptrot.org/posts/carson-summit-part-1/"/>
        <updated>2006-02-13T12:00:00Z</updated>
        <id>https://liptrot.org/posts/carson-summit-part-1/</id>
        <content type="html"><![CDATA[
          <p>Things we've learned.</p>
<p>The first talk of the day was a great one and set the tone for the rest of the day. Joshua gave us 45 minutes chock-full of useful information on how to get the most out your servers (from using a proxy to throttle performance, to server caching); building an API (the main point being make it easy for people to get in and out of it by using a simple solution such as XML and not requiring an API key); and URL-rewriting.</p>
<p>URL beautification became a common theme throughout the day as several of the talks urged for simple URLs. Joshua's reasoning was that they are the main marketing push for your site as they are copied and pasted everywhere.</p>
<p>Other points</p>
<ul>
<li>Don't add features which replicate other well-used applications - eg personal messaging which is limited to a site - why not just use email instead?</li>
<li>Don't give people the features they want - find the underlying problem they want to solve and give them what they need.</li>
<li>Top 10 lists just encourage people to spam your site - people start focussing on the list position.</li>
</ul>
<p>Tagging was one of the most useful things Joshua discussed as it is something I'm looking at for a couple of projects. Interestingly del.icio.us was built out of a txt file based system Joshua had for bookmarking websites, which eventually distilled his descriptions down into one-word meaningful 'tags'. He urged people not to be tempted to auto-add tags for users as this removes the attention required to give meaningful tags - the transaction cost of having to add tags each time makes the tag system stronger (although don't overdo this cost). I'm glad he spoke against a forced vocab list for tags. His reasoning was that a tag will mean different things to different people and there is no way you can add a 'description' to each tag.</p>
<p>He said make sure you measure useage of features over a period of time - if they are still using the feature long after it launched then it is a success. When testing for usability, don't give people tasks or goals as it makes them act totally different to how they would normally - they start reading everything on the screen.</p>
<p>For marketing he said they didn't really do any - most of it was evangalising users and he points out that del.icio.us isn't a community site, the community exists outside on AIM and email and other communication methods. Del.icio.us doesn't own the community (along with all the pitfalls of hosting such a community).</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Carson Summit Part 2: Cal Henderson - Flickr</title>
        <link href="https://liptrot.org/posts/carson-summit-part-2/"/>
        <updated>2006-02-13T12:00:00Z</updated>
        <id>https://liptrot.org/posts/carson-summit-part-2/</id>
        <content type="html"><![CDATA[
          <h2>Building Flickr</h2>
<p>Cal looks at 10 things which he sees as being instrumental to Web 2.0 from the point of view of Flickr.</p>
<h3>Collaboration</h3>
<p>Allowing people to list friends on Flickr enables a social network to develop, making the site better for them and for you. In addition, people within the network can add metadata to each other's photos so giving added benefit to all.</p>
<h3>Aggregation</h3>
<p>Having multiple types of data for each item (date, tags, geolocation, 'interestingness') means you can display it in lots of different ways.</p>
<h3>Open APIs</h3>
<p>Start with a basic API (ie ready-only) and work up to a full-featured one. The advantage of APIs is that it allows others to build features for you that you have neither the resources or inclination to build yourself. In addition it forms a free marketing tool as people who use it will talk about it.</p>
<p>A selfish reason for building an API is that it makes getting at your data easier so reducing the number of people grabbing your data by more invasive methods such as page-scraping.</p>
<h3>Clean URLs</h3>
<p>2 out of 2 for this one! Cal adds that once given a nice url, it should never be changed as it will have been bookmarked and linked to. Obvious but worth re-stating. He also mentions that as urls become cleaner more people will start to manipulate them, so Flickr for example shows the hierarchy of the information within the url. He goes on to say that it's worth making sure your urls will scale with the site.</p>
<h3>AJAX</h3>
<p>Not the first time this will be looked at today, this enables load on the server to be reduced (something which was raised later was that you might experience increased server load as your users interact more with the site - but that's all good!).</p>
<h3>Unicode UTF-8</h3>
<p>It's all about internationalisation and localisation, baby! Cal points out the difference between the two (enabling storage vs output in differnet language).</p>
<h3>Desktop integration</h3>
<p>Bringing the website out of the browser means your site has more reach and makes it easier for users to interact with it (dragging &amp; dropping files is one task which is far easier to accomplish on the desktop). Build widgets to allow uploading of files, plugging into the API. Allow email to be a delivery tool for publishing content.</p>
<h3>Mobile</h3>
<p>WAP really hasn't changed our lives, but many of the newer phones have browsers based on Opera. Cal's main point here is that it is a different type of user who is going to be using a mobile to view the site and so you should re-purpose your content to suit; swapping out the styles may no longer be enough.</p>
<h3>Open Data</h3>
<p>This is important stuff for service sites - allow your users to feel that they can leave with all their data at any time (and that includes any metadata which they may have added while using your service). All this can be accmplished via APIs allowing 3rd party sevices to add more value.</p>
<h3>Open Content</h3>
<p>Again important stuff. The data belongs to the user along with all the rights, unless specified by the user by Creative Commons or suchlike. The site cannot use or modiy the data without their permission.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Carson Summit Part 3: Tom Coates - Yahoo!</title>
        <link href="https://liptrot.org/posts/carson-summit-part-3/"/>
        <updated>2006-02-13T12:00:00Z</updated>
        <id>https://liptrot.org/posts/carson-summit-part-3/</id>
        <content type="html"><![CDATA[
          <p>In &quot;Designing Web 2.0-native Products for Fun and Profit&quot;, Tom looks at some guidelines for building web apps in the spirit of Web 2.0 and it was all good stuff. His main thrust was that the web has the opportunity to move from isolated sites to a model based on interconnected services.</p>
<p>Every service can be built upon existing services and this makes them all the more powerful. This all incorporates the use of APIs of course which has the effect of embedding your service within the community. An interesting point was that the combination of GoogleMaps and GoogleAds could enable everyone's favourite search engine to target their advertising geographically. This ties into <a href="http://www.oreillynet.com/pub/a/oreilly/tim/news/2005/09/30/what-is-web-20.html?page=1">Tim O'Reilly's assertion</a> that the race is one to 'own' certain types of data - eg location, identity, calendaring of public events. It is these services which will form the basis of the web as a platform.</p>
<p>He then went on to identify the 'Architectural Principles' of Web 2.0, citing Matt Biddulph's <a href="http://hackdiary.com/slides/xtech2005/">'The Application of Weblike Design to Data'</a>.</p>
<ul>
<li>Add value to the aggregate web of data.</li>
<li>Build for normal users (consumers); developers (give them hooks to build on); machines (predictability).</li>
<li>Start designing with data not pages.</li>
<li>Identify your first order objects (eg tv programmes, people, events) and make them addressable. Give them a unique and well-structured url, a single page for services to reference so everyone knows they are talking about the same thing - means aggregation can be effective.</li>
<li>Readable, reliable and hackable urls. Use directories to represent hierarchies (enables hackable urls) to reflect the structure of the data. They shouldn't reflect the underlying technology so use mod_rewrite or equivalent to clean them up (3 out of 3!). This goes most of the way towards making them as humanly readable as possible.</li>
<li>Correlate with external identifier schemes - knowing what you are referring to and linking to other sources eg IMDB for movie information.</li>
<li>Build list views and batch manipulation interfaces to go with the destination (first order) pages. These are the 3 core types of page. You can then use Ajax/Flash to manipulate the data within each type of page -only manipulate the concept within the page in question eg don't edit tags within a list page.</li>
<li>Parallel data representation. Reuse the data in parallel to the original page eg RSS for the list page and XML for the destination page. Del.icio.us uses RSS really well. <a href="http://www.microformats.org/">Microformats</a> can be used too.</li>
<li>Make your data as discoverable as possible.</li>
</ul>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Carson Summit Part 4: David Heinemeier Hansson - 37signals</title>
        <link href="https://liptrot.org/posts/carson-summit-part-4/"/>
        <updated>2006-02-13T12:00:00Z</updated>
        <id>https://liptrot.org/posts/carson-summit-part-4/</id>
        <content type="html"><![CDATA[
          <p>&quot;Happy Programming and Sustainable Productivity with Ruby on Rails&quot;</p>
<p>Having had a cursory look at Rails I can see where this talk is heading from the outset. It is centred around 'convention over configuration' and the basic premise seems to be that most of the work done by web programmers is mundane and is repeated again and again - 'You are not a snowflake'. Shouldn't you then concentrate on what makes you unique in coding terms and let the framework do all the heavy lifting?</p>
<p>To demonstrate this he shows us some code in Rails and proceeds to remove everything which confers some sort of pattern, from naming fields in tables to setting defaults. This leaves a much slimmed down code example. If we make the configuration the exception rather than the norm we can write slimmer, more beautiful code.</p>
<p>Flexibility is overrated - it leads to more complex systems which are harder to modify; constraints are liberating and lead to consistent systems and happier teams.</p>
<p>He then moves into Rails proper and demonstrates how it encourages good practice, for example by incorporating test pages into the cycle; &quot;You do know testing is good, don't you?&quot; Compare this to PHP (David developed in PHP for 5 years) where the devil on the other shoulder tends to get heard: &quot;You can test it at the end&quot;, &quot;No-one else needs to know how this algorithm works - it makes you a more valuable employee!&quot;.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Carson Summit Part 5: Shaun Inman - Mint</title>
        <link href="https://liptrot.org/posts/carson-summit-part-5/"/>
        <updated>2006-02-13T12:00:00Z</updated>
        <id>https://liptrot.org/posts/carson-summit-part-5/</id>
        <content type="html"><![CDATA[
          <p>In &quot;10 Reasons Why You Need to Build an API&quot;, Shaun gives us his list of goodness you get from APIs</p>
<p>APIs obscure the storage format and the retreival process.</p>
<ol>
<li>Increase brand awareness. You start to see your brand outside of its normal home and this gets noticed. eg GoogleMaps, Flickr. It also has the dual benefit of empowering users who then readily talk/blog about how they did it.</li>
<li>Allows users to own their own data - builds goodwill.</li>
<li>Builds goodwill for developers - Flickr use their own API internally to save their teams time.</li>
<li>Good excuse for a community.</li>
<li>Improves code quality - you have to keep the API in mind while developing and it clarifies the mental model of your application.</li>
<li>Simplifies the internal re-use of data (see 3.)</li>
<li>Allows others to extend the functionality of your application - things you don't have time to develop eg SVG charting in Mint.</li>
<li>Allows alternate input mechanisms - eg desktop input.</li>
<li>Unanticipated applications of your data eg Chicago Crime mashup.</li>
<li>Turns your application into a platform on which other things depend.</li>
</ol>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Carson Summit Part 6: Ryan Carson - DropSend</title>
        <link href="https://liptrot.org/posts/carson-summit-part-6/"/>
        <updated>2006-02-13T12:00:00Z</updated>
        <id>https://liptrot.org/posts/carson-summit-part-6/</id>
        <content type="html"><![CDATA[
          <p>&quot;How to Build an Enterprise Web App on a Budget&quot;.</p>
<p>This was a great talk and made my top spot on the feedback. No-one ever talks about this kind of detail in the frank was that Ryan did.</p>
<h2>Why build?</h2>
<p>You don't have to be big anymore. Web applications are much more acceptable to people than they were a few years ago. Combine this with the plummeting cost of hardware and availability of Open Source software and OS.</p>
<h2>Enterprise</h2>
<p>Ryan defines enterprise as mass market or 1,000+ users.</p>
<h2>The Budget</h2>
<p>He says that the minimum cost for an enterprise web app is £30,000. you should make sure that the idea is financially viable ie that it is worth paying for. use your common sense - would you pay for it? be cautious about your projections - get a pessimistic guess and then cut by 45%. Are you still in business? Then go ahead, oh, and make sure you plann for profit from the start.</p>
<p>DropSend is a hardware intensive application so some of the following figures would need adjusting for other apps.</p>
<table>
    <caption>Breakdown of costs for DropSend</caption>
		<thead>
		<tr><th>Item</th><th>Cost</th></tr>
		</thead>
		<tbody>
		<tr><td>Branding and UI design</td>
			<td>Ryan Shelton Mutado.com £5,000</td></tr>
		<tr><td>Development</td>
			<td>Plum Digital Media £8,500 + equity</td></tr>
		<tr><td>Desktop Apps</td>
			<td>£2,750</td></tr>
		<tr><td>XHTML/CSS</td>
			<td>£1,600</td></tr>
		<tr><td>Hardware</td>
			<td>Old Linux box for dev testing £500</td></tr>
		<tr><td>Hosting and maintenance</td>
			<td>5 Servers from BitPusher £800 pcm</td></tr>
		<tr><td>Legal</td>
			<td>£2,630</td></tr>
		<tr><td>Accounting</td>
			<td>£500</td></tr>
		<tr><td>Linux Specialist</td>
			<td>£500</td></tr>
		<tr><td>Misc</td>
			<td>£1,950</td></tr>
		<tr><td>Trademark</td>
			<td>£250</td></tr>
		<tr><td>Merchant Account</td>
			<td>Halifax £200</td></tr>
		<tr><td>Payment Processor</td>
			<td>Secure Trading £500</td></tr>
		</tbody>
		<tfoot>
		<tr><td>Total</td><td>£25,680</td></tr>
		</tfoot>
	</table>
<p>And that only includes one month of hosting.</p>
<p>To help with raising this capital Ryan ran a side business - Carson Workshops - but it still took a year to raise the necessary.</p>
<h2>Building a team on a budget</h2>
<p>Go for quiet talent rather than rock-stars. Big names cost and are generally busy busy.</p>
<p>Offer a percentage of product equity (2-5%) which becomes bankable if the product is aquired.</p>
<p>Ask for recommendations - getting the wrong person can be disasterous. or you can always outsource - Ryan tried India but it didn't work out for him, largely due to the distances involved.</p>
<h2>Scalability</h2>
<p>Buy just enough hardware to launch, but build your app so it easily scales - can you easily plug in disk space? Don't get tempted by lots of shiny new servers.</p>
<p>Plan for scalability but don't obsess about it.</p>
<h2>Keeping it cheap</h2>
<p>Don't spend money unless you have to:</p>
<ul>
<li>no stationary (DropSend wasted ٟ,000 on this!)</li>
<li>no new shiny machines - they built DropSend on a aging beige pc.</li>
<li>no luxuries</li>
<li>no features beyond the bare minimum - don't be tempted to say &quot;what if we did this&quot;. You can add more features later, anything else is stopping you from launching and generating profit.</li>
</ul>
<p>Before you spend anything more than £25, just check yourself and make sure you really need it.</p>
<p>Make deals. Build websites, give away equity, give advertising on your blog.</p>
<p>Use IM, no phone calls.</p>
<p>Do as much yourself as possible:</p>
<ul>
<li>wireframing</li>
<li>marketing</li>
<li>user testing</li>
<li>bookkeeping</li>
<li>copy writing</li>
<li>get friends to help with user testing</li>
<li>shop around - the first hosting quote ryan got was for £12,000 pcm!</li>
</ul>
<h2>Pessimism</h2>
<p>You will go 10% over budget and 3 months over schedule. Plan for it at the outset and put it in the cash flow. Are you still in business?</p>
<h2>Lawyers</h2>
<p>Make use of those free 1 hour consultations!</p>
<p>Company terms of service will cost £1,000; contracts for freelancers £800; privacy policy (from Clickdocs) £15.</p>
<h2>Cheap Software/hardware</h2>
<p>DropSend was developed primarily with cheap/free software from start to finish.</p>
<ul>
<li>Project management - BaseCamp</li>
<li>Bug Tracking - Trac</li>
<li>Meetings - Skype and AIM</li>
<li>Version Control - SubVersion</li>
<li>LAMP</li>
<li>£200 Linux box for testing.</li>
</ul>
<h2>Marketing</h2>
<p>Don't spend money! Use blogs and word of mouth. Look for viral delivery tools - make your app tell other people about your app (eg DropSend sends email notifications and includes info on itself). Write about your app for the trade magazine of your target audience - they will generally be happy to accept it.</p>
<h2>Venture Capital</h2>
<p>You need a seriously good reason to give away some of your company to v.c.</p>

        ]]></content>
      </entry>
    
	
    
      
      <entry>
        <title>Carson Summit Part 7: Steffen Meschkat - Google</title>
        <link href="https://liptrot.org/posts/carson-summit-part-7/"/>
        <updated>2006-02-13T12:00:00Z</updated>
        <id>https://liptrot.org/posts/carson-summit-part-7/</id>
        <content type="html"><![CDATA[
          <p>In &quot;Greater Expectations - Reality-Checking the AJAX Web Application Architecture&quot;, Steffen spends quite a bit of time beating up the javascript syntax and web programming in general. However he does come down on the side of Ajax (despite its name) in that it removes the requirement for a server-side session state for transient sessions.</p>
<p>He cheers up a little towards the end saying javascript has been compared to Lisp with C syntax. I get the distinct impression that he was speaking from a hardcore programmer's point of view, but unfortunately this made a lot of what he was saying difficult to understand for many of the mere web programmers out there.</p>
<p>I'd love to see that 1-to-1 virtual reality model of the entire world.</p>

        ]]></content>
      </entry>
    
	
</feed>