Skip to content

Instantly share code, notes, and snippets.

@selfthinker
Last active November 5, 2024 13:51
Show Gist options
  • Save selfthinker/207d3d3682bd549599ceec20cb1cb087 to your computer and use it in GitHub Desktop.
Save selfthinker/207d3d3682bd549599ceec20cb1cb087 to your computer and use it in GitHub Desktop.
Show possible accessibility issues coming from Govspeak on www.gov.uk

govspeak-a11y.user.css

What is it

govspeak-a11y.user.css is a so called 'user style' which can be installed with the help of the Stylus browser extension. It is a tool to help GOV.UK publishers see some accessibility issues coming from Govspeak.

It will show two different kinds of issues:

  • ❌ red errors show definite problems
  • ⚠️ orange warnings show potential issues that might not necessarily be an issue or that is not as severe

It doesn't show all possible accessibility issues, just some of the most common ones. To see more accessibility issues, use something like WAVE.

How to use it

  1. Install the Stylus browser extension, either Stylus for Chrome or Stylus for Firefox or you can install the Chrome extension in Edge if you 'Allow extensions from other stores'
  2. Open govspeak-a11y.user.css directly Install directly with Stylus
  3. Click the "Install style" button in the top left of the view that opens within Stylus (keep the 'Check for updates' checkbox checked)
  4. Browse pages on www.gov.uk or preview pages in publishers, and if there are certain types of accessibility issues on the page, they will automatically be highlighted and briefly described

To disable the style again, click the Stylus icon in the toolbar to the right of your browser's address bar. And then click the style's name in the dropdown that appears.

Screenshot showing how to disable the style as described above.

What does it look like

Some example screenshots of the tool in action:

The style applied to a snippet of a page, showing how a heading is highlighted with an error to not use the same two headings of the same level after each other and a table is highlighted with a warning as having just one row. The style applied to another snippet of a page, showing how a heading is highlighted with a warning to avoid using lower level headings and a table is highlighted with an error as having no table headers.
/* ==UserStyle==
@name Govspeak accessibility issues
@namespace github.com/alphagov
@description Show possible accessibility issues coming from Govspeak on www.gov.uk
@version 1.2.8
@license MIT
@author Crown Copyright, Government Digital Service
@preprocessor less
@homepageURL https://gist.github.com/selfthinker/207d3d3682bd549599ceec20cb1cb087
@updateURL https://gist.githubusercontent.com/selfthinker/207d3d3682bd549599ceec20cb1cb087/raw/govspeak-a11y.user.css
==/UserStyle== */
@-moz-document domain("www.gov.uk"), domain("publishing.service.gov.uk"), domain("dev.gov.uk"), domain("webarchive.nationalarchives.gov.uk") {
/* == Mixins == */
.error() {
color: #000;
background-color: #fcc;
outline: 2px solid #c00;
/* &::before { content: "❌ " } */
}
/* warning = we can't be sure if it's a problem, or it's a lesser issue */
.warning() {
color: #000;
background-color: #fc0;
outline: 2px dotted #c00;
/* &::before { content: "⚠️ " } */
}
.help() {
font-size: 1.1875rem;
font-weight: normal;
font-style: normal;
color: #333;
background-color: #fff;
padding: 0 .2em;
}
.help-block() {
.help();
display: block;
}
.help-inline() {
.help();
}
.empty() {
display: inline-block;
min-width: 1em;
min-height: 1em;
}
.reset() {
color: inherit;
background-color: inherit;
outline: inherit;
&::after {
display: none;
}
}
/* == Inline text == */
div.govuk-govspeak strong {
.warning();
&::after {
.help-inline();
content: "⚠️ Use bold sparingly and not instead of a heading."
}
}
div.govuk-govspeak tbody td:first-child strong {
&::after {
content: "⚠️ Do not use bold instead of a table header."
}
}
div.govuk-govspeak th strong {
&::after {
content: "⚠️ There is no need to make table headers bold."
}
}
div.govuk-govspeak em {
.error();
&::after {
.help-inline();
content: "❌ Do not use italics, they will not show up on pages."
}
}
div.govuk-govspeak div.highlight-answer em,
div.govuk-govspeak div.stat-headline em {
.reset();
}
div.govuk-govspeak small {
.warning();
&::after {
.help-inline();
content: "⚠️ Do not make the font smaller."
}
}
div.govuk-govspeak sub,
div.govuk-govspeak sup {
.warning();
&::after {
.help-inline();
content: "⚠️ Do not use 'sub' or 'sup' to make the font smaller."
}
}
/* sup is automatically used for footnotes, therefore not showing the error for those */
div.govuk-govspeak a[href^="#"] sup,
div.govuk-govspeak sup:has(a[href^="#"]) {
.reset();
}
/* == Headings == */
div.govuk-govspeak h1 {
.error();
&::after {
.help-block();
content: "❌ Do not use H1 within Govspeak. It won't show as a heading."
}
}
/* only checks completely empty headings, not those with only spaces or  s,
as those will be in CSS4 and are not supported in most browsers;
although Firefox supports its own version for most whitespace (except entities) */
div.govuk-govspeak h1:empty,
div.govuk-govspeak h2:empty,
div.govuk-govspeak h3:empty,
div.govuk-govspeak h4:empty,
div.govuk-govspeak h5:empty,
div.govuk-govspeak h6:empty {
.error();
.empty();
&::after {
.help-block();
content: "❌ This heading is empty."
}
}
/* doesn't work in non-Firefox when combined with the above */
div.govuk-govspeak h1:-moz-only-whitespace,
div.govuk-govspeak h2:-moz-only-whitespace,
div.govuk-govspeak h3:-moz-only-whitespace,
div.govuk-govspeak h4:-moz-only-whitespace,
div.govuk-govspeak h5:-moz-only-whitespace,
div.govuk-govspeak h6:-moz-only-whitespace {
.error();
.empty();
&::after {
.help-block();
content: "❌ This heading is empty."
}
}
div.govuk-govspeak h4,
div.govuk-govspeak h5,
div.govuk-govspeak h6 {
.warning();
&::after {
.help-block();
content: "⚠️ Avoid using lower level headings."
}
}
div.govuk-govspeak h1 + h1,
div.govuk-govspeak h2 + h2,
div.govuk-govspeak h3 + h3,
div.govuk-govspeak h4 + h4,
div.govuk-govspeak h5 + h5,
div.govuk-govspeak h6 + h6 {
.error();
&::after {
.help-block();
content: "❌ Do not use two headings of the same level after each other."
}
}
/* == Links == */
div.govuk-govspeak a[href$=".pdf"],
div.govuk-govspeak a[href$=".docx"],
div.govuk-govspeak a[href$=".doc"],
div.govuk-govspeak a[href$=".odt"],
div.govuk-govspeak a[href$=".xls"],
div.govuk-govspeak a[href$=".xlsx"],
div.govuk-govspeak a[href$=".ods"],
div.govuk-govspeak a[href$=".csv"],
div.govuk-govspeak a[href$=".rtf"],
div.govuk-govspeak a[href$=".ppt"],
div.govuk-govspeak a[href$=".pptx"],
div.govuk-govspeak a[href$=".odp"],
div.govuk-govspeak a[href$=".zip"] {
.warning();
&::after {
.help-inline();
content: "⚠️ Do not link to files directly."
}
}
/* attachments link to files directly, but are okay because they include file information */
div.gem-c-attachment__details .gem-c-attachment__title a,
div.gem-c-attachment__thumbnail a,
span.gem-c-attachment-link a,
span.inline-attachment a,
span.attachment-inline a,
div.attachment-details .title a,
div.attachment-thumb a,
div.form-download a {
.reset() !important;
}
div.govuk-govspeak a:empty {
.error();
.empty();
&::after {
.help-inline();
content: "❌ This link is empty."
}
}
div.govuk-govspeak a:-moz-only-whitespace {
.error();
.empty();
&::after {
.help-inline();
content: "❌ This link is empty."
}
}
/* == Images == */
/* images cannot have CSS-generated content,
therefore the help text is attached to something else
most images are within a `figure` element, so it often gets attached to that
this won't work in the few cases that are not within such elements
*/
/* removed `div.govuk-govspeak` because images are often in teasers or top of the page, not in Govspeak */
figure:has(img:is([alt*="png"], [alt*="jpeg"], [alt*="jpg"], [alt*="gif"], [alt*="webp"], [alt*="_"])) {
.error();
&::before {
.help-block();
content: "❌ Do not use a file name as the alt text.";
}
}
/* historically, alt text couldn't be left empty, so people used to leave these instead */
figure:has(img:is([alt=" "], [alt='""'], [alt="''"])) {
.error();
&::before {
.help-block();
content: "❌ Do not use a space or quotation marks without any content as the alt text."
}
}
/* this can only happen if HTML is used within Govspeak */
/* the help text is attached before the next element, if available
if not available, there won't be any text */
div.govuk-govspeak img:not([alt]) {
.error();
& + *::before {
.help-block();
content: "❌ Image is missing the 'alt' parameter."
}
}
/* empty alt in linked images, except for attachment thumbnails which have an aria-hidden */
a:not([aria-hidden="true"]):has(>img[alt=""]) {
.error();
display: inline-block;
&::before {
.help-block();
content: "❌ Do not leave alt text empty in linked images."
}
}
/* not using these for now...
* never seen an animated gif on gov.uk, so might not be necessary
figure:has(img[src$=".gif"]) {
.warning();
&::before {
.help-block();
content: "⚠️ Check if this is an animated gif."
}
}
* we tell people to leave alt empty, so less of a point to highlight these
figure:has(img[alt=""]) {
.warning();
&::before {
.help-block();
content: "⚠️ Check if this is an informative image or described in text."
}
}
* not too important compared with other issues
figure:has(img:is([alt^="Image of"], [alt^="Picture of"], [alt^="Photo of"])) {
.warning();
&::before {
.help-block();
content: "⚠️ Do not start alt text with 'Image of' etc."
}
}
*/
/* == Tables == */
/* only 1 column */
div.govuk-govspeak tr > td:not([colspan]):only-child,
div.govuk-govspeak tr > th:not([colspan]):only-child {
.error();
&::after {
.help-inline();
content: "❌ Do not use tables for layout purposes.";
}
}
div.govuk-govspeak table > tbody > tr:only-child {
.warning();
&::after {
.help-inline();
content: "⚠️ There is only 1 row.";
}
}
/* only checks completely empty cells, not those with only spaces or  s,
as those will be in CSS4 and are not supported in most browsers;
although Firefox supports its own version for most whitespace (except entities) */
/* empty `th`s are not possible with Govspeak */
/* :empty doesn't work in non-Firefox when combined with :-moz-only-whitespace */
div.govuk-govspeak td:empty {
.warning();
}
div.govuk-govspeak td:-moz-only-whitespace {
.warning();
}
div.govuk-govspeak table:has(td:empty)::after {
.help-block();
border: 2px dotted #c00;
content: "⚠️ This table has empty cells."
}
div.govuk-govspeak table:has(td:-moz-only-whitespace)::after {
.help-block();
border: 2px dotted #c00;
content: "⚠️ This table has empty cells."
}
div.govuk-govspeak table thead th ~ td {
.error() !important;
&::after {
.help-inline();
content: "❌ Do not leave cells in the header row empty.";
}
}
/* probably missing row headers if top left cell is empty */
div.govuk-govspeak table thead:has(td:first-child:empty) + tbody tr td:first-child {
.warning();
&::after {
.help-inline();
content: "⚠️ Might need row headers.";
}
}
div.govuk-govspeak table thead:has(td:first-child:-moz-only-whitespace) + tbody tr td:first-child {
.warning();
&::after {
.help-inline();
content: "⚠️ Might need row headers.";
}
}
div.govuk-govspeak table:not(:has(th)) {
.error();
&::before {
.help-block();
content: "❌ This table has no table headers.";
}
}
div.govuk-govspeak table thead tr + tr {
.error();
&::before {
.help-inline();
content: "❌ Do not use more than one header row.";
}
}
div.govuk-govspeak table td:has(br),
div.govuk-govspeak table th:has(br) {
.warning();
&::before {
.help-block();
content: "⚠️ Check <br> is not used for layout purposes.";
}
}
/* not using these for now as tables can be quite busy with too many errors,
and these are more usability rather than accessibility issues
div.govuk-govspeak table tbody tr td:nth-child(n+6) {
.warning();
&::after {
.help-inline();
content: "⚠️ Avoid too many columns."
}
}
div.govuk-govspeak table tbody tr:nth-of-type(n+11) {
.warning();
&::after {
.help-inline();
content: "⚠️ Avoid too many rows."
}
}
div.govuk-govspeak table tbody tr:nth-of-type(n+25) {
.error();
&::after {
.help-inline();
content: "❌ This table is getting too long."
}
}
*/
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment