Gerillass 2.0.0 is out. It renames every utility function and replaces two mixins with one, so read the migration guide before you upgrade.

Gerillass

v2.1.1

Focus Ring

Type: Mixin
@include focus-ring();

* You can call mixins with or without the gls- namespace (e.g. @include gls-focus-ring();).

The Focus Ring Sass mixin draws the ring a keyboard user follows around the page. It writes an outline on :focus-visible, with a width, an offset and a colour.

That is two declarations, and both halves of the selector matter. The usual ways of doing this by hand either take the ring away from keyboard users or draw one that disappears in high contrast mode.

What goes wrong by hand

Measured in Chrome 152, on buttons, a link and a text input:

Written by handWhat happens
:focus { outline: none; }tabbing to the element shows nothing at all: no outline, no shadow
a ring on :focusit also appears on every mouse click, which is why people remove it
a ring on :focus-visiblea mouse click on a button or a link does not show it; Tab does
a box-shadow ring instead of an outlinelooks the same, but forced-colors mode sets box-shadow to none

Arguments

NameTypeDescription
$width (2px)number (with unit)The thickness of the ring.
$offset (2px)number (with unit)The gap between the element and the ring. A negative value draws the ring inside the element.
$color (currentColor)colorThe colour of the ring. The default follows the text colour of the element, which is right for text and outlined controls and wrong for a filled button with light text, where the ring would come out white. Pass a colour there.

The values are written straight into outline and outline-offset, so anything CSS accepts there works, including var().

Examples

Buttons. The outlined button keeps the default, because its text is dark. The filled button has light text, so currentColor would draw a white ring, and it is given a colour instead. Click an empty spot in the result, then press the Tab key on your keyboard: a click on a button itself does not show the ring, which is the point of :focus-visible.

Sass
.btn-outline {
  @include focus-ring;
}

.btn-primary {
  @include focus-ring($color: #18181b);
}
CSS
.btn-outline:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

.btn-primary:focus-visible {
  outline: 2px solid #18181b;
  outline-offset: 2px;
}
Result

Form fields. Click into any of them: form fields show the ring on a click as well as with the Tab key. Measured in Chrome 152 on the input, the select and the textarea.

Sass
.input,
.textarea,
.select {
  @include focus-ring(2px, 2px, #18181b);
}
CSS
.input:focus-visible,
.textarea:focus-visible,
.select:focus-visible {
  outline: 2px solid #18181b;
  outline-offset: 2px;
}
Result

A menu inside a card that clips its content. The items fill the card edge to edge, so the ring is drawn 4px inside each of them. Click an empty spot in the result, then press the Tab key on your keyboard.

Sass
.menu-item {
  @include focus-ring(2px, -4px, #18181b);
}
CSS
.menu-item:focus-visible {
  outline: 2px solid #18181b;
  outline-offset: -4px;
}
Result