alphagov / govuk-design-system

One place for service teams to find styles, components and patterns for designing government services.
https://www.gov.uk/design-system
MIT License
497 stars 231 forks source link

WCAG 2.2 development update: Exit this page || Focus Not Obscured #2538

Closed owenatgov closed 1 year ago

owenatgov commented 1 year ago

What

Investigate potential ways to ensure that the Exit this Page button doesn't fail WCAG 2.2 SC 2.4.12: focus not obscured.

Why

The EtP button is using position: sticky to ensure that it is always present on the screen for users to have easy access to it. This creates a risk that the button could be floating above a focused element, leading to us failing 2.4.12.

Part of https://github.com/alphagov/govuk-design-system/issues/1755

Who needs to work on this

Developers, Accessibility specialists

Done when

Decision log

Update this log as the discussions progress.

Action items

Suggested actions

querkmachine commented 1 year ago

Having given this a quick poke...

The bad news: In its current form, the EtP button's stickiness does indeed fail WCAG 2.2 § 2.4.12.

The good news: Applying a large enough scroll-padding-top to the <html> element makes it no longer fail the criterion, and that technique is supported by every modern browser and has been for several major versions now.

The expected news: That won't work in Internet Explorer.

The ugly news: Ideally the value of scroll-padding-top would need to at least equal the visual height of the button—however the height of the button is not fixed, and it changes depending on what text is in it, whether the indicator lights are visible, any text size adjustments made in the browser settings or with user styles, etc. We may have to set that value computationally using JS, probably falling back to a 'fits most' value of some kind.

dav-idc commented 1 year ago

@owenatgov and I had a chat today about this, and we've got a few takeaways, action items, and suggested actions:

Takeaways

Action items

Suggested actions

querkmachine commented 1 year ago
  • Discuss whether we're okay with the 3% of potential browser scenarios not passing on 2.4.12 where position:sticky is activated but scroll-padding isn't available

As an extension of this, we could use @supports to feature detect support for scroll-padding and only apply position: sticky if it is. This would deal with the 3%, but does so by putting them into the 'no sticky button' bucket.

owenatgov commented 1 year ago

I started writing a big analysis of the browser overlap before @querkmachine noted the idea to use @supports which I think is a much more robust idea than trying to calculate whether to let that 3% slip or not. Considering that the plan right now is to remove position: fixed as a fallback for older browsers, this seems consistent.

FWIW a rough rundown of my 3% analysis:

I think the number of users impacted by the @supports fallback will be minimal and therefore worth implementing.

dav-idc commented 1 year ago

Agreed on that front, @supports is a great shout and really simplifies the explanation for how our fallback works too.

I'll modify the initial description of this issue so we can track our decisions

owenatgov commented 1 year ago

After mucking around I've put together a demo (on the main etp branch because I forgot to make a PR 🤦🏻). This, as discussed in the issue, reliably adds scroll padding when the button is on the page.

I did run into a snag when trying to implement this however: how do we apply this to a page with EtP on bearing in mind that scroll-padding only works when applied to the scroll parent of a given scroll section? In this case it's the entire page so it has to be on the html tag.

Ideas for how to implement scroll-padding

1. Update .govuk-template

.govuk-template is the class we add to the html tag in our page template and that we recommend teams do when not using our template. We therefore already have something we can use to deliver the scroll-padding styling.

A risk here is how this might interact with service teams who are already using scroll-padding or any part of the scroll snap module which scroll-padding is part of. We're potentially creating unexpected failures in services by adding something that's relevant to a comparatively small number of scenarios.

2. Create a modifier class with the styling

We could create a modifier class eg: .govuk-template--exit-this-page to ring-fence the styling and recommend it only be applied to pages with the button on. The problem here is how we then implement it. We can add it via the button js but this doesn't account for instances where the user doesn't have js available. We would therefore need to ask teams to add this class to their services pages with an EtP button on, adding extra steps to the implementation of the button and the pattern.

It also doesn't completely solve the above risk of clashing with existing scroll snap module uses.

3. Use :has to sniff for an exit this page button

We could implement the styling in .govuk-template but use a :has selector to check if the page contains an EtP button and only apply scroll-padding then. eg:

.govuk-template:has(.govuk-exit-this-page) {
    scroll-padding: 4rem;
}

The problem here is the pretty meagre browser support for :has. A way around this could be to have it available by default using something like:

@supports not selector(:has(*)) {
    scroll-padding: 4rem;
}

...but I ran into issues getting this to work against our current linter which doesn't support selector.

The previous issue on implementation risk again rears its ugly head.

My solution

I decided to go for a simplified version of 3. My code for this can be found here.

This effectively reverse engineers 3 in that we set scroll-padding by default and use :has to remove it if the button isn't present.

Re: the conflicting implementation issue, I have a reckon that by putting this rule in .govuk-template we are putting it at the back of the cascade for services and therefore is easily overridden. This is assuming that teams have a preset scroll-padding rule on their html.

A decision we have to make therefore is if we're ok with users potentially getting served this scroll-padding rule unexpectedly.

owenatgov commented 1 year ago

Some outcomes with a chat with devs:

It's unclear if WCAG are content with "older" browsers (ie: browsers that don't support scroll-padding) not passing the criterion. There was a reckon that this was the inference from the content and the suggestion to use scroll-padding. Therefore could we be content with only thinking about this criterion for "newer" browsers? That would mean we could bring position: fixed back as a fallback so older browsers received the button enhancement.

From this thought we could also ask: could we apply this via js and be content that that's the only way this style is applied?

One for @davidc-gds.

querkmachine commented 1 year ago

A decision we have to make therefore is if we're ok with users potentially getting served this scroll-padding rule unexpectedly.

I think I'm reasonably comfy with just having scroll-padding apply to all browsers, without needing to remove it again if the EtP button is absent.

There are no obvious negative consequences to this style existing on a page if the EtP button is absent. In-page anchor targets will be offset slightly instead of being butted right to the top of the viewport, but if anything that's probably an improvement!

It would conflict with any full-page scroll-snapping functionality being used, but this style of scrolljacking isn't something I think we'd ever expect to be used on GOV.UK, and if it's really necessary the style can still be overridden through the cascade.

dav-idc commented 1 year ago

The 'suggested actions' for this issue have all been moved over to a new issue:

Rationale: It recommends making a net-new pattern related to 'sticky' elements, which is outside the scope of the GOV.UK Frontend updates for WCAG 2.2.

That new issue has been added to this other epic: