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* 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 hand | What happens |
|---|---|
:focus { outline: none; } | tabbing to the element shows nothing at all: no outline, no shadow |
a ring on :focus | it also appears on every mouse click, which is why people remove it |
a ring on :focus-visible | a mouse click on a button or a link does not show it; Tab does |
a box-shadow ring instead of an outline | looks the same, but forced-colors mode sets box-shadow to none |
Arguments
| Name | Type | Description |
|---|---|---|
$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) | color | The 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.
.btn-outline {
@include focus-ring;
}
.btn-primary {
@include focus-ring($color: #18181b);
}.btn-outline:focus-visible {
outline: 2px solid currentColor;
outline-offset: 2px;
}
.btn-primary:focus-visible {
outline: 2px solid #18181b;
outline-offset: 2px;
}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.
.input,
.textarea,
.select {
@include focus-ring(2px, 2px, #18181b);
}.input:focus-visible,
.textarea:focus-visible,
.select:focus-visible {
outline: 2px solid #18181b;
outline-offset: 2px;
}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.
.menu-item {
@include focus-ring(2px, -4px, #18181b);
}.menu-item:focus-visible {
outline: 2px solid #18181b;
outline-offset: -4px;
}