This is a fascinating deep dive by the people at Discord on their development of a focus ring component and all the problems they had to overcome:
Browsers implement default focus rings that apply to all elements, but the ability to style these is (currently) very limited. These rings, while they have recently improved greatly in Chrome and Edge, are also not very pleasant when integrated with the rest of Discord’s design, and other browsers like Firefox are almost entirely invisible in most cases due to the thinness and low contrast of their styles.
As such, we want to implement a custom focus ring style. At a glance, this seems relatively simple, but when dealing with the variety of use cases Discord has for these rings, the list of requirements quickly grows, and the options for implementations shrink.
Ideally, we want to match the browser’s focus ring behavior exactly. Within Discord, this means that a comprehensive focus ring implementation needs to:
- Perfectly map to the element that has focus (with exceptions listed below).
- Follow elements as they move when containers scroll.
- Follow elements as they animate and transition within the document.
- Not be clipped off when the focused element is bounded by
overflow: hidden
or other bounding techniques.- Respect occlusion of overlapping elements, but not be occluded by an element’s own z-index.
Additionally, to be able to implement pleasant and overall better focus styles for various elements in the app, we have additional requirements to be able to:
- Apply the focus ring on a different element than the actual focused element
- Provide positional offsets to adjust ring placement around the element.
- Adjust ring styles to match the look and feel of the surrounding context (could include changing border radius, color, shape, and more)
- Specify a style for when focus is within an element, for example to indicate the bounds of a widget.
See the source link for the rest.