A Whole Lot of Bovver Over Hover

A mouse flying in front of a computer screen with the words :hover :hover :hover :hover :hover underneath

If you have read some of my recent posts here—or, to be more accurate, taken part in one of them—you’ll know that I’ve tried to demystify issues relating to contrast and color.

Specifically, I wanted to work through when certain cases fail Success Criteria (SC) 1.4.1 Use of Color or 1.4.11 Non-text Contrast. I did this through the medium of quiz and with a frighteningly painful series of puns. Just in case you escaped the pain before now, I will quickly refer you to those articles:

In both articles, I was interested in the default state of the controls in question and, in a few places, the focus state. While I did add some hover styles, that was not really the, um, focus of either article (sorry ’bout that one). They were little more than red herrings. While blissfully basking in the feeling that, with those articles, I had solved all the possible mysteries related to button and link styling, indicating the state of a page element, or focus indication (as if), there was a little gremlin lurking that continued to rear its head. And it would rear its head whenever a mouse pointer dared to cross its path. I am referring to the :hover CSS pseudo class.

Let’s Focus on the Important Stuff

Before covering the issue that :hover has been presenting us with, let’s briefly cover its counterpart :focus, and explain why it’s important.

All web browsers have a default style that they apply to any focusable element when it receives focus. It varies from browser to browser and across operating systems, and how well they work depends on many factors:

  • What background color is present behind/next to the element that has focus?
  • Is the OS set to light or dark mode?
  • Has the user set their own accent color in the OS preferences that might change that focus style?

Generally speaking, though, it’s safe to say that the default focus indicator has not always been great. There have been some improvements of late, though: Firefox no longer has a measly, barely-there dotted focus indicator, and Chrome has also introduced a two-tone focus indicator that should increase its chances of working against a wider range of backgrounds. But, still, you cannot be absolutely sure that the default style will work in all scenarios. But why is this focus indicator needed?

If you are a sighted keyboard-only user, the focus indicator is critical for you to understand where you are on a web page as you navigate around using the TAB key (or sometimes using the arrow keys, depending on the widget you’re interacting with). The default focus indicator may not always be too clear, but it’s a whole lot better than no focus indication. Precious designers who don’t like ‘those dotted outlines’ and insist on setting * {outline:none} get a deservedly frowny look from me, and a certain amount of tutting. Wait til they learn about :focus-visible, that will blow their minds.

Whether you consider yourself to have perfect vision or whether you have very low vision, a clear focus indicator is the most important feature that lets you know where you are on the page when navigating with the keyboard. If you’re jumping large distances across a page—for example, tabbing from a header area into the body of a page—without a clear focus indicator, you might feel somewhat in no man’s land. Even when navigating an interface component with multiple buttons, links and other levers to pull that seem to be presented in a logical order, can you really be sure which control you are on without a clear focus indicator? Are you sure that you have set focus on the ‘Cancel’ button, before you press SPACE to activate it? Or could you, perhaps, have set focus on the ‘Yes, I’m really sure I want to close my account’ button? It’s kinda important to know, right?

If you leave the CSS alone and rely on the default focus indicator style, it might not always be that clear to see, but you won’t be failing any WCAG SC. However, the moment that you start tweaking focus styles, you’re fair game! If you create your own focus styles, they need to pass 3:1 color contrast ratio otherwise they will fail SC 1.4.11 Non-text Contrast.

Hover Styles, What Are They Good For?

But what about hover? Is it critical that there is a style that shows what control is currently being hovered over? Is it anywhere near as important as providing a clear focus style (spoiler alert: no, it’s not even close, not even in the same league).

Providing a hover effect is little more than a nice-to-have, in my opinion. It can give page elements a lift, and provide a little extra hint that the thing that is under the mouse is interactive. But one would also hope that the designer has used long-standing conventions in interface design such that it’s already obvious which elements are interactive, which elements will let you change a setting, which elements will navigate you to another page. If that is indeed the case, a hover effect is not necessary, it’s a bonus. It’s reinforcement that the thing you thought might be clickable is, indeed, clickable. That said, some strange people like to add hover effects on things that are not interactive. Please, don’t do that.

Unlike the keyboard-only user that needs a clear focus indication to know where they are, the mouse user knows where they are on the page because, well, they are moving that mouse exactly where they need it to be. The question about ‘where will I end up next?’ that a keyboard-only user might have when pressing TAB does not apply here.

So with all that stated above, one question: should we fail elements that have poor outlines on hover? Should we fail elements that have just a slight hint of a background color change on hover?

OK, that was two questions. You got me. But it’s essentially the same issue: is there a problem if a hover style is not totally clear?

Nope.

And yet, the fact that it’s taken me this long to get to that point suggests that this is not generally well understood.

What’s the Bovver With Hover?

I have absolutely no problem with people providing hover styles. What I do take issue with is when a hover style that is applied to an element is flagged as a failure of SC 1.4.11 Non-text Contrast because it doesn’t meet 3:1 contrast ratios. As I’ve noted above, the requirement for a focus indicator is much more important than the visual effect when hovering over an element. But applying the same logic that a focus indicator should have 3:1 contrast to an element being hovered over is not correct.

I have seen this flagged as a problem when I have been QAing other people’s audit work, often enough that it has had me questioning myself: is this really a failure issue? Each time, I noted that the boilerplate content that we use internally for reporting focus indicator failures under 1.4.11 has been adapted slightly for reporting the hover issue. When 99% of the wording looks like content that you recognize as approved solution material, it’s very easy for that to slip through. The danger is that if this does happen, others will see examples of this being reported and think ‘oh yeah, we fail for poor hover styles’.

What does the actual WCAG SC say about this? The normative wording in 1.4.11 says that the “visual presentation of the following have a contrast ratio of at least 3:1 against adjacent color(s): … User Interface Components: Visual information required to identify user interface components and states“. The devil is in the details here, because if you are hovering your mouse over an element, visual information is not required to identify its state. You know its state, because you’re doing the hovering!

Maybe it’s a good point to work this through with some examples.

Button Up for Some Examples

The button below has poor text contrast, and the border does too. It fails SC 1.4.3 Contrast (Minimum), SC 1.4.11 Non-text Contrast as a result. There is a good focus indicator, and no hover style. This is your ‘control’ (strangely for me, no pun intended), something that you can easily spot issues with.

The next group of buttons don’t fail 1.4.3 and because there’s good text contrast, the low contrast border or background does not fail 1.4.11. Once again, there are no hover styles here, and the focus indicator is good.

Now let’s add in some hover styles to see how that changes your view:

The first of the group of two has a very slight color change on hover. The contrast of that background color against the white background is 1.12:1. Very low … but remember, this is not a focus indicator. If you have just used your mouse pointer to move it over this control, you know where you are on the page, so that color contrast change does not need to be over 3:1.

What about the second button in this group? Well, the background color has a good 5.74:1 contrast ratio against the page background but, again, it really is not important here. You don’t need that to contrast with the background. What you do need, though, is for the text to have good contrast and unfortunately when the button is hovered over, that darker background color causes the text to drop to 3.66:1 contrast ratio. If your ‘helpful’ hover effect causes a text contrast issue, that is a SC 1.4.3 Contrast (Minimum) failure.

Let’s look at a couple more examples. Both of the buttons below are clear in their default state (and also have good focus indication). But what happens on hover?

The first of these goes light gray (text and border), while the second just changes to a light gray border but keeping the text black. What would I fail these on?

The first button I’d fail for SC 1.4.3 Contrast (Minimum). I would not fail for 1.4.11 for the border. Why? Because as noted previously this is not a focus indicator and as a mouse user, I have evidently found that control’s boundary already (the default black outline is super clear); the fact that the border turns to a light gray is not important. The lower contrast text is the only real problem here.

The second button? Nothing to report here. No failure at all.

In summary, then …

  • Clear focus indicators are essential.
  • Hover styles may be useful and improve UX, but are not essential.
  • Hover styles should not be failed for the same reasons that you would fail poor focus indication.
  • There is no such thing as an ‘on-hover focus indication’.
  • If your hover style causes a text contrast issue, you will fail SC 1.4.3 Contrast (Minimum).
  • Hover styles never fail 1.4.11.
Categories: Technical
Tags: ,

About Ian Lloyd

Ian Lloyd (or 'Lloydi' as he prefers) is a Principal Accessibility Engineer at TPGi. He joined the company in 2020 and previously worked for Apple as an accessibility engineer. Prior to that, he spent what seems like a lifetime working for a financial services company, trying to promote accessibility with varying levels of success. In an alternate universe, he continued his early path of DJ-ing and producing to become a superstar DJ, but this universe had other ideas. Outside of work, he maintains a11y-tools ("A random collection of accessibility-focused tools that you might find at least partially useful").

Comments

In your examples, the mouse cursor changes to the hand icon (which your CSS is setting here explicitly), which provides visual feedback. What about cases where the mouse pointer *doesn’t* change? (Since there’s vocal proponents like https://medium.com/simple-human/buttons-shouldnt-have-a-hand-cursor-b11e99ca374b that will fight you to the death to say that you shouldn’t deviate from platform norms)

Ian Lloyd says:

Darnit. I completely forgot that this site’s CSS has that hand icon baked in and would automatically inherit that in my examples. That was not intentional.

I had intended to cover some of the feedback you get for free with the browser default. This paragraph was in an earlier draft:

“With no hover effect provided, it’s likely that you’ll have some feedback given for free by the browser, anyway. An example of this is that as you pass the mouse pointer over a block of text, it displays as a caret, indicating that you can select text, but when moving over a button, link or another form control, that caret turns into a pointer; it implies ‘you may click me!'”

But then I realised it was less that the cursor turns to an arrow for those interactive elements, more that the arrow is the default and caret for text selection is the exception.

As for the pointy hand CSS thing – I personally have no problem if it’s used. I think it *does* make buttons and links more obvious, especially given that the design of so many links. buttons and luttons often lacks obvious interactivity affordance. It’s not a hill I will die on arguing for or against, though.

Ian Lloyd says:

Actually, on further investigation, the pointer does NOT appear to be being set on hover by a WordPress CSS file. I disabled the CSS and it’s still there. Checked a bit more and it is showing as being provided by the user agent stylesheet, in Chrome/macOS at least:

a:-webkit-any-link {
color: -webkit-link;
cursor: pointer;
text-decoration: underline;
}

color and text-decoration are overridden by site CSS, the cursor:pointer is there by default.

odd, on Windows/Chrome, the style is definitely coming from _global.scss

“`
button, input[type=image], input[type=reset], input[type=submit] {
font-size: 1em;
cursor: pointer;
}
“`

In any case, something to keep in mind, as I *almost* understand those that start to worry about hover styles being necessary in order to understand something is a button (but then, there’s the usual other visual indicators, including spacing, positioning, context, wording of the control’s text, etc)

Ah, your snippet from user agent styles is for links. I was looking at the *button*s here in the post, where by default that style is to just keep the default mouse pointer rather than the hand.

Ian Lloyd says:

“Ah, your snippet from user agent styles is for links.” Yep. I picked the wrong day to give up sniffing glue … I mean, I picked the wrong element in DevTools. So, as you were – it’s set in the global CSS after all.

Anna Orlova says:

Quite confused why the 1st example fails both 1.4.3 and 1.4.11. My understanding is that it fails 1.4.3 only: “If a button with text also has a colored border, since the border does not provide the only indication there is no contrast requirement beyond the text contrast (1.4.3 Contrast (Minimum)).”

Ian Lloyd says:

It fails 1.4.3 because the text has low contrast, and it fails 1.4.11 because the border has low contrast. If the inner text content were over 4.5:1, it would not fail 1.4.3. And because it passes 1.4.3, it does not get its ‘get-out-of-jail-free’ card for 1.4.11.

That’s what I was going to write and leave it at that, but then I took a look at https://www.w3.org/WAI/WCAG21/Understanding/non-text-contrast.html

In Boundaries it says (and I have boldened the part you are referring to):

“This success criterion does not require that controls have a visual boundary indicating the hit area, but if the visual indicator of the control is the only way to identify the control, then that indicator must have sufficient contrast. If text (or an icon) within a button or placeholder text inside a text input is visible and there is no visual indication of the hit area then the Success Criterion is passed. If a button with text also has a colored border, since the border does not provide the only indication there is no contrast requirement beyond the text contrast (1.4.3 Contrast (Minimum)).

I have kept re-reading that and it’s making me question my statement. If the button text fails 1.4.3, and the border/outline/boundary is under 3:1, is it still a 1.4.11 failure because “there is no contrast requirement beyond the text contrast”?

I feel like I have to raise this question with the folks who write these documents to be sure. I will come back to this.