Sass is an extension language for CSS, it adds features to make maintaining large CSS codebases easier.
One feature in Sass is mixins.
“Some things in CSS are a bit tedious to write, especially with CSS3 and the many vendor prefixes that exist. A mixin lets you make groups of CSS declarations that you want to reuse throughout your site.”
In our case we have a group of CSS declarations for our focus style that we want others to reuse.
Here is an example of the Sass needed for things that look like links:
// When colours are overridden, for example when users have a dark mode,
// backgrounds and box-shadows disappear, so we need to ensure there's a
// transparent outline which will be set to a visible colour.
// Since Internet Explorer 8 does not support box-shadow, we want to force the user-agent outlines
@include govuk-not-ie8 {
outline: $govuk-focus-width solid transparent;
outline-offset: 0;
}
color: $govuk-focus-text-colour;
background-color: $govuk-focus-colour;
// sass-lint:disable indentation
box-shadow: -5px -1px 0 1px $govuk-focus-colour,
5px -1px 0 1px $govuk-focus-colour,
-3px 1px 0 3px $govuk-focus-text-colour,
3px 1px 0 3px $govuk-focus-text-colour;
// sass-lint:enable indentation
// When link is focussed, hide the default underline since the
// box shadow adds the "underline"
text-decoration: none;
Our users could copy and paste this, but it will be useful for them to be able to use this as a mixin.
@mixin govuk-focusable-fill {
// Previous CSS declarations go here...
}
Which allows them to use it in their code like this:
.link {
@include govuk-focusable-fill;
}
GOV.UK Frontend version 2.0.0 includes two mixins that help with the existing focus styles.
govuk-focusable
Provides an additional outline to clearly indicate when the target element is focussed. Used for interactive elements which themselves have some background or border, such as most form elements.
and
govuk-focusable-fill
Provides an additional outline and background colour to clearly indicate when the target element is focussed. Used for interactive text-based elements such as links.
The :focus
selector is baked into the mixin:
- limits it's use, as not all focus states are with the simple
:focus
selector
.link:not(:active):focus {
// @include govuk-focusable;
&:focus {
// Duplicate the declarations in the mixin, or have an additional mixin.
color: black;
background: yellow;
text-decoration: none;
}
}
- encourages undoing or overriding css, since convention is to have mixin at the top of a declaration block
.link {
@include govuk-focusable;
&:hover {
text-decoration: underline;
}
&:focus {
// Setting focusable again because the mixin is not included in the right place.
text-decoration: none;
}
}
This is explained in more detail in 'option 1'.
With this option we would update the existing mixins. Our release notes would explain how to review the current use of the mixins, and when to avoid using them, referencing the new guidance.
Things that look like an input:
@include govuk-focusable;
Things that look like a link:
@include govuk-focusable-fill;
Something else, you'll need to do non-text focus and use the following variables.
&:focus {
outline: $govuk-focus-width solid $govuk-focus-colour;
outline-offset: $govuk-focus-offset;
box-shadow: 0 0 0 3px $govuk-focus-text-colour;
}
Pros:
- Potentially the simplest for users, since their code will not blow up.
Cons:
-
The new focus styles are not a 1:1 replacement.
-
Mixins need reviewing and could be missed if code does not fail.
-
Many of the inputs have additional focus styles that feel inappropriate to include as part of the mixin.
-
Need an additional (possibly private?) mixin for styles that do not have a simple
:focus
selector for use in the accordions component. -
Feels like a coincidence that you can somewhat reuse these mixins since they were designed to be more abstract with wider use.
[Spike] Option 1: Replace existing mixins with new focus styles
With the exception of links, the new focus styles are complicated enough that they can't be abstracted without edge cases.
So rather than have people uninclude uses of the more generic govuk-focusable
mixin, we would remove them entirely and ask people to replace them with standard CSS with Sass variables.
We could include a new $govuk-focus-offset
variable, that is used whenever a user needs to avoid using the mixins.
Things that look like a link:
@include govuk-focused-text;
Something else, you'll need to do non-text focus and use the following variables.
&:focus {
outline: $govuk-focus-width solid $govuk-focus-colour;
outline-offset: $govuk-focus-offset;
box-shadow: 0 0 0 3px $govuk-focus-text-colour;
}
Pros:
- Forces a review of focus states
- Can't have bad mixins if mixins don't exist ;)
- The only abstraction that exists is one we're confident is useful
Cons:
- Requires replacing code if there are 1:1 replacements.
- Re-implementing some focus CSS might be done incorrectly if guidance isn't clear enough.
[Spike] Options 2: Remove existing mixins, and include a new mixin for links only.
Option 3: Remove existing mixins, include new mixins for inputs, input errors and links, with no generic focus mixin.
Things that look like an input:
&:focus {
@include govuk-focused-input;
}
&:focus {
@include govuk-focused-input-error;
}
Things that look like a link:
&:focus {
@include govuk-focused-fill;
}
Something else, you'll need to do non-text focus and use the following variables.
&:focus {
outline: $govuk-focus-width solid $govuk-focus-colour;
outline-offset: $govuk-focus-offset;
box-shadow: 0 0 0 3px $govuk-focus-text-colour;
}
Pros:
- Mixins are explicit for where they should used, so can't be used in the wrong circumstance
Cons:
- Requires replacing code if there are 1:1 replacements.
- Not clear if these abstractions are useful for other people, or just the code in GOV.UK Frontend
The new focus styles are more complicated from a design principle perspective so we wont be able to cover all bases with sass mixins.
We will be introducing new guidance on the Design System website to improve this, and is worth thinking about when considering what we do here.
Met with the team, and we went over the different options.
We agreed to go with option 2, but we are interested in the additional more scoped mixins in option 3 in the future.