Is the change of outline-offset, on pressing any keyboard key on anchor tag, the expected behaviour?

Viewed 215

In the following demo, click and hold the mousedown on the anchor tag, then drag your cursor away, while holding mousedown, and then finally let go of the click. You will see a red dotted outline around the anchor tag. Now if you press shift key the outline will get offset by a few pixels.

a:focus {
  outline: 1px dotted red;
}
<a href="#">Click+hold, then release, then press shift key</a>

The behaviour doesn't occur on pressing ctrl or fn keys etc, but does happen for most keys. This behaviour seems to be cross browser compatible, which leads me to ponder:

  • Is it a bug in the implementation of html by the broswers?
  • Or, is it the expected behaviour suggested by w3.org for some user experience issues?
2 Answers

By clicking an element and then pressing Shift, as you said, or in some other situations determined via heuristics, you are triggering both :focus and :focus-visible states. Browser will then apply its default styles for these states.

The result you are reporting can be reproducted in Chrome because of its default user agent stylesheet, but not in Firefox, for example. You can test this on your own by opening DevTools and forcing the states of the a element.

The following example reproduces Blink (Chrome's rendering engine) default styles so it can be seen in other browsers:

a:focus {
  outline: 1px dotted red;
}

a:any-link:focus-visible {
  outline-offset: 1px;
}

/* for non-Blink WebKit browsers */
a:-webkit-any-link:focus-visible {
  outline-offset: 1px;
}
<a href="#">Example link</a>

<!-- To see the result described in the question for sure, 
     please force :focus and :focus-visible states using DevTools -->

By default there is an animation set to this if outline-offset is not defined. You can see animation set on outline-width here in animation type in Formal Definition. A function is set on animation type which helps in animation. When animated, values of the data type are interpolated as real, floating-point numbers. The interpolation happens on the calculated value. The speed of the interpolation is determined by the timing function associated with the animation causing the outline-offset increase from 0px to 1px.

References: https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function https://developer.mozilla.org/en-US/docs/Web/CSS/length#interpolation https://www.w3.org/wiki/CSS/Properties/outline-width.

You can check and verify these thoroughly on these links.

Related