All class names start with a .govuk-
namespace to reduce the likelihood of
conflicting with existing classes in your application. It also helps to identify
where the styling for a particular element is coming from.
If you are building components for your own application or framework you should
use a different prefix, for example .app-
or the initials of your department.
GOV.UK Frontend uses the Block Element Modifier (BEM) methodology when naming CSS classes. This is designed to help developers understand how the different classes relate to each other.
The naming convention follows this pattern:
.block {}
.block__element {}
.block--modifier {}
.govuk-card {} // Block - the root of a component
.govuk-card__body {} // Element - a part of the block
.govuk-card--active {} // Modifier - a variant of the block
It uses double hyphens (--
) and underscores (__
) so that the block, element
or modifiers themselves can be hyphen delimited without causing ambiguity.
For example:
.govuk-phase-banner {}
.govuk-phase-banner__phase-tag {}
.govuk-phase-banner__phase-tag--light-blue {}
Break elements and modifiers outside of blocks rather than nesting using a
parent selector &
.
This makes the codebase easier to read, and makes it easier to search for a given class name. It also discourages excessive nesting.
Bad:
.govuk-breadcrumb {
// ...
&__item {
// ...
}
}
Good:
.govuk-breadcrumb {
// ...
}
.govuk-breadcrumb__item {
// ...
}
BEM stands for Block__Element--Modifier
, not Block__Element__Element--Modifier
.
Avoid including multiple elements when naming classes.
Each class has a single purpose, so you can be sure when making a change to a class - it will only affect the element that class is applied to.
Also when deprecating classes, all of the CSS for this class can be removed without affecting another component that had reused this css.
Why?
To ensure that styles can safely be added or removed without fear of breaking other components.
Keep all of the variants of a component in the same place.
.govuk-error-summary
modifies the .govuk-list
component.
Component modifiers use an extra class, scoped to the component:
.govuk-error-summary__list
This class is part of the component, rather than a parent of a component.
Why? This makes it easier to keep track of different contexts.
To ensure code quality and consistency in our Sass files we check that certain rules are followed. These rules are based on GDS Stylelint Config, but we also add our own custom rules with a project config file.
For consistent formatting we run Prettier.
See testing and linting for more information.
You can run the linter with npm run lint:scss
, or use linting in Visual Studio Code and other editors that support Stylelint.
To automatically fix Stylelint issues, add the --fix
flag:
npm run lint:scss -- --fix
You can run the formatter with npm run lint:prettier
, or use formatting in Visual Studio Code and other editors that support Prettier
To automatically fix Prettier issues in all supported files, add the --write
flag:
npm run lint:prettier -- --write
We use the following rules when linting files:
Bad:
.selector {padding: 0; border: 0;}
Good:
.selector {
padding: 0;
border: 0;
}
Bad:
.selector {
color: #005ea5;
}
Good:
.selector {
color: $govuk-blue;
}
Bad:
$white: #FFF;
Good:
$white: #ffffff;
Bad:
#content {
// ...
}
Good:
.govuk-wrapper {
// ...
}
Bad:
p {
margin: 0;
em {
// ...
}
}
a {
// ...
}
Good:
p {
margin: 0;
em {
// ...
}
}
a {
// ...
}
Bad:
.govuk-breadcrumb {
// ...
&__item {
// ...
}
}
Good:
.govuk-breadcrumb {
// ...
}
.govuk-breadcrumb__item {
// ...
}
Bad:
@extend %contain-floats;
Good:
@include clearfix;
Bad:
margin: 1px 2px 3px 2px;
Good:
margin: 1px 2px 3px;
Bad:
@import 'foo';
$govuk-font-family-gds-transport: 'GDS Transport', arial, sans-serif;
.bar {
content: 'baz';
}
Good:
@import "foo";
$govuk-font-family-gds-transport: "GDS Transport", arial, sans-serif;
.bar {
content: "baz";
}
The basenames of @import
ed SCSS partials should not begin with an underscore and should not include the filename extension
Bad:
@import "_foo.scss";
@import "_bar/foo.scss";
Good:
@import "foo";
@import "bar/foo";
Bad:
.foo {
content:"bar";
}
Good:
.foo {
content: "bar";
}
Bad:
@if ($foo == $bar) {
$baz: 1;
}
Good:
@if $foo == $bar {
$baz: 1;
}
Bad:
@if $foo == null {
$baz: 1;
}
Good:
@if not $foo {
$baz: 1;
}
Operators should be formatted with a single space on both sides of an infix operator. These include +, -, *, /, %, ==, !=, >, >=, <,
and <=
Bad:
.selector-1 {
margin: 5px+15px;
}
$foo: 1;
$bar: 3;
.selector-2 {
margin: $foo+$bar+"px";
}
$foo: 1+1;
$bar: 2-1;
@if $foo==$bar {
$baz: 1;
}
@if $foo!=$bar {
$baz: 1;
}
Good:
.selector-1 {
margin: 5px + 15px;
}
$foo: 1;
$bar: 3;
.selector-2 {
margin: $foo + $bar + "px";
}
$foo: 1 + 1;
$bar: 2 - 1;
@if $foo == $bar {
$baz: 1;
}
@if $foo != $bar {
$baz: 1;
}
Functions, mixins, variables, and placeholders should be declared with all lowercase letters and hyphens instead of underscores
Bad:
@mixin FONT_STACK() {
font-family: $govuk-font-stack;
}
Good:
@mixin font-stack() {
font-family: $govuk-font-stack;
}
Bad:
.selector {
margin: 0px;
}
Good:
.selector {
margin: 0;
}
Bad:
.selector {
margin: 0
}
$my-example-var: value
Good:
.selector {
margin: 0;
}
$my-example-var: value;
Bad:
.selector {
font-size: .50em;
}
Good:
.selector {
font-size: 0.5em;
}
More write up on supported rules.
For comments, you should normally use 2 slashes (//
) at the start of the line.
If you need to include the comment in the compiled CSS, use the multi-line ('loud') comment style, which starts with /*
and ends at the next */
.
Wrap comments at 80 characters wherever possible.
We document SCSS using SassDoc. This includes most of the settings, helpers and tools layers, with variables, functions and mixins being marked as private or public.
The SassDoc comments are used to generate the Sass API reference in the GOV.UK Frontend docs.
For SassDoc comments, use 3 slashes (///
) at the start of the line.
See _colour.scss
for an example of SassDoc syntax.