Software Engineer or Frontend Developer

As a Software Engineer or Frontend Developer, you have one of the most important roles when it comes to accessibility. A design can have considered accessibility, but it’s up to you to build it to work correctly.

By using existing libraries and frameworks such as GOV.UK Frontend and DWP CASA, you can get a lot of good practices for accessibility built in, however we need to be mindful of how we apply them.

Using GOV.UK Frontend does not mean your service automatically meets level AA of WCAG 2.2. You’ll still need to make sure your service as a whole meets accessibility requirements.

If you want to see how your code test with assistive technology, we have published guidance on how to do accessibility testing

Working with others

You will need to work closely with interaction designers and content designers to make sure things like hover states, error messages and hidden text are considered.

You will also want to work with QA Testers to make sure accessibility is part of the acceptance tests and your definition of done.

Things to consider as a Software Engineer or Frontend Developer

Alternative text for non-text content

If an image is purely decorative then you do not need to provide alternative text (also known as “alt text”), but if it adds context to the content or additional information, then it should have a description.

All images should be marked as decorative using an empty alt attribute.

For example:

Code example
<img src="office-background.jpg" alt="" />

You should work with an Interaction Designer and a Content Designer to make sure alternative text is provided for images that need it.

Announce dynamic content

If the content of a page changes dynamically, such as a pop-up or using live data, you must announce the changes to a screen reader.

Usually this would be done using the aria-live attributes. Adding aria-live to an element will tell the screen reader that it needs to monitor that content because it is likely to change at some point.

For example, if you have a live chat function, the screen reader would need to know every time a new message was available. By adding aria-live to the chat window, every time you append something to it the screen reader will read it out. By setting it to polite, it means the screen reader will finish anything it is already reading before reading out the appended message.

Code example
<div id="chat-window" aria-live="polite">
    Hello, how can I assist you?

You can read more about aria on MDN.

Content and focus order

The content and the focus order needs to be logical. You should not use CSS to rearrange the content on the page to read in a different order to the way it is presented in the DOM. If you turn the CSS off, the page should read in the same order as it would if the CSS is turned on.

The focus order is also important. When tabbing through the page it should be obvious where the focus will go next. A logical order means the focus is always moving left to right and top to bottom within each section, and left to right and top to bottom between each section.

Cookie consent is part of of the General Data Protection Regulations (GDPR) and not strictly an accessibility issue. However a lot of the time cookie consent is presented in pop-up or banner form, and this can make your site inaccessible.

Here are some examples of how your cookie banner could make your site inaccessible:

  • The cookie consent is a pop-up which is not announced to a screen reader. This fails WCAG 4.1.2 Name, Role, Value.
  • The cookie consent is a pop-up which is cannot be navigated by keyboard. This fails WCAG 2.1.1 Keyboard.
  • The cookie consent is a pop-up and the keyboard focus can disappear behind it. This fails 2.4.7 Focus visible.
  • The cookie consent is presented as a banner at the bottom of the page but is the first content made available to keyboard focus or screen readers. This fails WCAG 1.3.2 Meaningful sequence.
  • The cookie consent uses links which are styled to look like buttons but cannot be programmatically determined to be buttons. This fails WCAG 4.1.2 Name, Role, Value

There is a GOV.UK Cookie banner component and a GOV.UK Cookie banner page in the Design System.

Correct roles

For any elements on the page, they should use the correct HTML tags. If you absolutely must use a different tag than would usually be expected, then you need to assign it the correct role. This allows assistive technology to still interact with the element as if the correct tag were used.

A common example of this is styling links to look like buttons. We should not really do this anyway as it makes user interfaces hard to predict. Links should navigate between pages and buttons should interact with data, such as submitting a form. However there might be some instances where research shows that a link needs to be more visible, such as a call to action.

For example:

Code example
<a href="/apply-now" class="btn" role="button">Apply now</a> 

By giving the link a role of button, it can now be determined to be a button. So if somebody is using voice recognition software such as Dragon, when they say “click button”, Dragon will be able to find it on the page.

You can read more about aria roles on MDN.

DWP CASA framework

DWP CASA is a NodeJS framework built and maintained by DWP Engineering.

It ships with GOV.UK Frontend built in and will give you additional features such as routing logic, validation helpers, session management and protection against common security vulnerabilities.

If you’re building a NodeJS project in DWP, it is recommended you use the DWP CASA framework.

Existing patterns and components

Always start by using the existing components and patterns in the GOV.UK Design System and the DWP Design System.

These components often have accessibility considerations built in, so it’s not enough to just style your components to look similar.

You should work with an Interaction Designer to understand what parts of the design exist already. If you need to build something from scratch you will need to do additional work to make sure it’s accessible.

GOV.UK Frontend

If you’re building a service for GOV.UK then you will need to use GOV.UK Frontend, and you will need to use version 3.0 or newer as older versions are not WCAG compliant.

If you’re building a service for internal use or some other purpose, you might still want to consider using GOV.UK Frontend because it gives you a lot of styles and components that are accessible and designed to be compliant with WCAG level AA.

GOV.UK Frontend comes with templates and style sheets. It comes with accessible considerations built in such as colours, line-heights, letter spacing and responsive layouts. It will also allow you to use any of the components in the GOV.UK Design System.

A common misconception is that use of GOV.UK Frontend components automatically results in WCAG compliance. This is not the case. You need to use the components properly and will still need to carry out thorough accessibility testing. There are lots of detailed noted on the GOV.UK Design System site which provide guidance on how and when to use components properly.

You can use the templates in an unbranded mode. So even if you want to brand your website or service differently, you can still get all of the benefits of using GOV.UK Frontend.

If you choose not to use GOV.UK Frontend, then it’s likely you will need to do additional work both in development and testing.

Heading hierarchy

Always use the correct heading levels.

A heading can have any level from H1 to H6. Every page should have a single H1, and each heading level should relate to all the headings above it. The higher the number, the more detail on the topic you should be going into.

For example, your might have a page to provide information on COVID-19. On that page you might have a section for information on how to protect yourself, and you might have another sections getting tested.

Code example
<h1>Stop the spread of COVID-19</h1>

  <h2>How to stay safe</h2>
    <h3>Wearing a mask</h3>
    <h3>Washing your hands</h3>
    <h3>Social distancing</h3>

  <h2>How to get a test</h2>
    <h3>Getting tested if you're a key worker</h3>
    <h3>Getting a test for somebody in a care home</h3>

If you need to change the size of the heading, use a different class to style it rather than changing the heading level itself.

For example:

Code example
<h1 class="govuk-heading-s">This is a small H1</h1>
<h2 class="govuk-heading-l">This is a large H2</h2>

Inputs and labels

All form inputs need labels. It is not acceptable to have a form input without one, and trying to make them too fancy can make them inaccessible.

For some reason forms often get over-designed and the use of labels is not consistent. There is a trend of using placeholder text instead of labels and also using floating labels which use CSS or JavaScript to animate the label to a different position when then field is focussed.

Any input without a label will fail WCAG 3.3.2 Labels or Instructions. A label should be explicit and should link the for attribute on the label to the id attribute of the input. This way the user has a larger target size and it is always clear which field the label is related to.

You should not use placeholder text instead of a label. A label should describe instruction for the input, and placeholder text should be reserved for an example if it is needed. If you use placeholder text instead of a label, you cannot then check what you entered against the instructions without deleting it back out the field.

For example:

Code example
<label for="reference">Enter your reference</label>
<input id="reference" placeholder="ABC-123-123" name="reference" type="text" />

Inputs control purpose

Adding autocomplete attributes to certain fields helps browsers auto-fill personal information. This can be useful for a person with memory related disabilities, motor impairments, or people where English is not their first language.

As part of 1.3.5: Identify Input Purpose we need to look at which fields may need autocomplete attributes to help users complete the service. For example, the autocomplete attribute for a date of birth.

Autocomplete attributes are intended to be used when people are entering their own personal information. For internal systems where staff are inputting other peoples details, we should not use autocomplete attributes as it could lead to the wrong information being entered accidentally.

A recommended autocomplete attribute list shows which fields we might need to use autocomplete on, including attributes like name, telephone number and passwords.

Keyboard focus

Every interactive element on the page needs to be accessible to a keyboard. This means you should be able to press the tab and arrow keys to navigate links, form inputs and submit buttons without any issues.

The focus must be visible at all times when using a keyboard. This means it must never focus anything which is off the page or obscured by another element. It must also be styled in a way so that it has enough contrast between any text and the background.

If you’re using GOV.UK Frontend, you will need to be using version 3.0 or newer to get the compliant focus styles. The old versions will fail WCAG on focus contrast. You can read more about the updated GOV.UK styles in the following GDS blog post: We’ve made the GDS Design System more accessible .

For any link, remove everything else on the page and make sure it still makes sense. For example “Change” is not clear when you view it in isolation, but “Change bank details” is.

If you need to, you can use visually hidden text to add context to a link. This is text which is still read out by a screen reader but cannot be seen on the screen. For example:

Code example
<a href="#">
  Change <span class="govuk-visually-hidden">bank details</span>

Never use a link which tells the user to “Click here”. The word “click” makes an assumption that a mouse is being used, but the user could be using a keyboard or some form of assistive technology.

You should work with a Content Designer to make sure all links make sense out of context.

No keyboard traps

A keyboard user must be able to enter and exit sections without ever needing to use a mouse.

For example, if the user enters a pop-up window, but cannot focus the close button to exit the pop-up, this would be a keyboard trap.

Another example is a social media feed which uses an infinity scroll mechanism to constantly load in more posts as you near the bottom of the section. This could potentially trap the keyboard user from ever reaching the content beyond it.

The easiest way to check this is just to use the tab and arrow keys to interact with every part of the page. If at any point you need to refresh the page to get out of something, then this would be a fail.

No reliance on JavaScript

When building any website or service, it must work without JavaScript turned on.

JavaScript should be introduced as an enhancement and not as an essential component of the page, so if a user has it turned off or if it does not load then the page still functions.

There are many reasons why JavaScript might not load, especially on poor internet connections or mobile devices. You should never assume that only the 1% of people who deliberately disable JavaScript will be the only people affected.

Orientation and reflow

Every page must work regardless of the orientation of the device. This means switching between portrait and landscape should not cause any parts of the site to break.

The content should reflow if you scale the size of the window, and at no point should any text become unreadable at a minimum of 256px wide.

No items should scroll horizontally unless meaning would be lost otherwise. For example, an image or a complex data table.

Page title

Titles should describe the purpose and content of the page.

The title is usually the H1, apart from when the H1 contains identifiable information.

For example, if the H1 is “What is your date of birth?” then it would also be the title.

However, sometimes the H1 can contain personal information, for example “What is John Smith’s date of birth”. In this case, the title should be different to the H1 as there is a risk the information would be included in analytics data.

In cases like this, the title should be as close as possible to the H1 but not identical to it. For example, it could be “What is your partner’s date of birth?”.

The standard format for titles on a service is to set the context in 3 parts and separate them using en dashes (not hyphens). The 3 parts are:
H1 – Service context – Domain context.

For example:

Code example
<title>What is your name? – Apply for Universal Credit – GOV.UK</title>

If there are errors on the page, then the page context part of the title should be prefixed with Error:. You can read more about this on the GOV.UK pattern for validation errors.

You should work with a Content Designer and QA Tester to make sure the titles are correct when deciding if the page is finished.

Page URL

You can refer to the page URL guidance in the Service manual.

The page purpose should be clear from the URL. URLs are often overlooked as something that should be designed. But they’re an important part of accessibility as they can orientate users. They can also make content easier to find if a user needs to come back later.

An example of a good url is:

Code example

An example of a bad url is:

Code example

You should work with a Content Designer to make sure the URLs follow the most helpful format for the user.

Setting the language

The language of a page should be set. This allows browsers to render the correct content, but it also allows assistive technologies to be able to pronounce the content correctly.

The language of the page should always be set on the HTML tag, but you also need to set the languages of any parts that might be different. For example, you might have a link labelled “Cymraeg“ to switch the language into Welsh. If you don’t add a lang attribute with a Welsh code, the screen reader will try to read it out in English and it will get the pronunciation wrong.

For example:

Code example
<!DOCTYPE html>
<html lang="en">
      <li><a href="home">Home</a></li>
      <li><a href="welsh" lang="cy">Cymraeg</a></li>

If you don’t set the language of the page, you will fail WCAG 3.1.1 Language of page, and if you don’t tag up any differences in language correctly you will fail WCAG 3.1.2 Language of parts.

If you have repetitive content on a page then you need to provide a way to skip over that content. The most common use of a skip link is to bypass the navigation menu by placing a link at the top of the body tag which jumps to the main tag.

You may also need skip links if you include things like social media feeds which can trap a keyboard user.

For example:

Code example
  <a href="#main-content">Skip to main content</a>
  <main id="main-content">

Skip links are often not visible on the page, they are styled to only appear when using screen readers or when they receive keyboard focus. A skip link does not need to be hidden from the page, but they do need to be present to jump over anything which might be a burden for the user.


If there are any time limits on the service, then they will need to be accessible. The most common timeout encountered on GOV.UK services is the session.

If you have any kind of timeout in your service then it must meet one of the following criteria in order to be considered compliant:

  • the default time limit is set to at least 20 hours
  • the user must be able to turn off the time limit completely before encountering it
  • the user must be able to adjust the time limit before encountering it, to a minimum of 10 times the original time limit
  • the user must be warned they are about to reach the time limit and be given at least 20 seconds to reset the timer. The user must be allowed to do reset the timer at least 10 times, and resetting the timer must not clear any of the information the user has already entered.

The only exceptions are when the time limit is in real-time, such as an auction which ends at 5pm. Or, if the time limit is essential such as booking tickets where the tickets can only be placed on hold a reasonable amount of time.

You should use the Manage a session timeout pattern from the DWP Design System.

Valid code

Assistive technologies rely on code being valid. Like a browser, if the code is not valid, then the technology has to try and guess how it should be interpreted, and this can make them behave in an unpredictable way.

We have published guidance on validating HTML.

Validation and error messages

Validation might be done in the frontend, in the back-end, or both. There are accessibility considerations for any kind of validation.

Real time validation

It is recommended that forms on a page are only validated once the user submits the form. Real-time validation can be annoying and inaccessible. It tends to throw errors before you’ve finished typing which can cause confusion.

If you do real-time validation, you will need to consider how that is announced to a screen reader. If you’re appending error messages to the page using JavaScript then you will need to do additional work to make sure you have used the right aria tags to announce the errors to a screen reader user in a non-intrusive way.

On submit validation

If you validate on form submission, you need to make sure you re-run the validation and that the user is alerted to the error each time they click submit.

If you don’t do this, secondary form errors are often not highlighted to screen reader users as there is no change of state on the page.

Dealing with user input

If you know what you are expecting the user to fill in, it can be tempting to lock down the fields. But you should not use limitations like the maxlength attribute. These can cause difficulties for people using voice controllers such as Dragon.

When using voice controllers, when the user pauses for breath it can automatically add a space. It is much more accessible to tell the user there is a character limit in the hint text, but don’t actually limit the field. Then you can remove the whitespace and validate what was actually inputted once the form is submitted.

For example, if you were trying to validate a National Insurance number you would use the following steps:

  1. allow the user to enter more than 9 characters
  2. allow the user to submit the form
  3. remove whitespaces, hyphens etc, and convert to uppercase
  4. check it is a valid National Insurance number
  5. accept the data as valid or reload the page with errors

This way you are not burdening the user with getting everything perfect. We know assistive technologies can add spaces, and we know some people won’t use capital letters, so we can do the hard work to make it simple.

Do not add random database rules

When analysing database schema, it is quite common to find character limits and rules which do not represent real world scenarios. Making assumptions about how long a persons name should be, or not allowing characters with accents or hyphens can quickly make things inaccessible.

Many assistive technologies allow people to create their own dictionaries. These are words or phrases that are common to the user but not to the native language. Their name is one of the things they will most likely store. You should not be telling people they entered their name wrong, and you should not be creating barriers for assistive technology by forcing the user to format their name in a way which fits the rules you have made up.

Error messages

Whenever a validation error is detected, you must inform the user that there is an error, and you must make it clear how to fix the error.

The standard way to do this in Government is to use the following patterns and components in the GOV.UK Design System.

It is not enough to just tell the user there is an error somewhere. You must make it obvious to them which fields are causing the error and clearly explain what they must do to fix it.

Error pages

Error pages are different to validation errors. These are pages your user might see when something goes wrong with the service on a technical level rather than something the user has entered incorrectly.

These errors are called server errors or HTTP status codes and you must consider what you will show the user if one of them occurs. You should not just relay the code to the user because they will not understand what has gone wrong.

For example, if the user tries to navigate to a step in a journey several days after they’ve submitted an application, do not just show them a page which says “401: Unauthorised” or “Session expired”. Instead, you could explain to the user why they cannot start on this page, or redirect them back to the start page of the journey.