CSS and Sass Style Guide
May 20, 2026 ยท View on GitHub
Sass modules
GOV.UK Frontend supports both @import and @use to include Sass files.
Our public API is prefixed with govuk- to ensure consistent naming and avoid
clashes with Sass elements in your application. You should @use govuk-frontend
modules without a namespace:
Bad:
@use "foo";
.bar {
color: foo.govuk-function("baz")
}
Good:
@use "foo" as *;
.bar {
color: govuk-function("baz")
}
Class naming convention
govuk namespacing
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.
Block Element Modifier (BEM)
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-pagination {}
.govuk-pagination__link-title {}
.govuk-pagination__link-title--decorated {}
Further reading:
Nesting
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.
Single Responsibility Principle
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.
Component modifiers
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.
Formatting and linting
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.
Running the lint task
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
Running the formatting task
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
Linting rules
We use the following rules when linting files:
Use soft tabs (2 spaces)
Write each property on its own line
Bad:
.selector {padding: 0; border: 0;}
Good:
.selector {
padding: 0;
border: 0;
}
Use variables for colours not HEX values in selectors rules, unless in variables.
Bad:
.selector {
color: #005ea5;
}
Good:
.selector {
color: $govuk-blue;
}
Colours defined as variables should be in lowercase and in full length
Bad:
$white: #FFF;
Good:
$white: #ffffff;
Avoid using ID selectors
Bad:
#content {
// ...
}
Good:
.govuk-wrapper {
// ...
}
Separate rule, function, and mixin declarations with empty lines
Bad:
p {
margin: 0;
em {
// ...
}
}
a {
// ...
}
Good:
p {
margin: 0;
em {
// ...
}
}
a {
// ...
}
Use no more than 3 levels of nesting
Bad:
.govuk-breadcrumb {
// ...
&__item {
// ...
}
}
Good:
.govuk-breadcrumb {
// ...
}
.govuk-breadcrumb__item {
// ...
}
Don't use extends, use mixins
Bad:
@extend %contain-floats;
Good:
@include clearfix;
Allow max 3-rule property shorthand if possible
Bad:
margin: 1px 2px 3px 2px;
Good:
margin: 1px 2px 3px;
Strings should always use double quotes
Bad:
@use 'foo';
$govuk-font-family-gds-transport: 'GDS Transport', arial, sans-serif;
.bar {
content: 'baz';
}
Good:
@use "foo";
$govuk-font-family-gds-transport: "GDS Transport", arial, sans-serif;
.bar {
content: "baz";
}
Files should always have a final newline
The basenames of @useed SCSS partials should not begin with an underscore and should not include the filename extension
Bad:
@use "_foo.scss";
@use "_bar/foo.scss";
Good:
@use "foo";
@use "bar/foo";
Properties should be formatted with a single space separating the colon from the property's value
Bad:
.foo {
content:"bar";
}
Good:
.foo {
content: "bar";
}
@if statements should be written without surrounding brackets
Bad:
@if ($foo == $bar) {
$baz: 1;
}
Good:
@if $foo == $bar {
$baz: 1;
}
@if statements comparing against null values should use not
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;
}
Omit length units on zero values
Bad:
.selector {
margin: 0px;
}
Good:
.selector {
margin: 0;
}
Property values and variable declarations should always end with a semicolon
Bad:
.selector {
margin: 0
}
$my-example-var: value
Good:
.selector {
margin: 0;
}
$my-example-var: value;
Write leading or trailing zeroes for numeric values with a decimal point
Bad:
.selector {
font-size: .50em;
}
Good:
.selector {
font-size: 0.5em;
}
Remove trailing whitespace
More write up on supported rules.
Comments
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.
SassDoc
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.