A collection of Sass and JavaScript files for using as part of your application's frontend.
This project is not tied to a specific language and is designed to be used as a dependency in as many different languages as needed.
There's a Gemfile
and a package.json
in this directory, but they are only
for running tests and are not an indication that this project prefers
Ruby or Node.js.
We recommend you use the govuk_frontend_toolkit_gem and follow the installation instructions.
govuk_frontend_toolkit_npm is an NPM package that can be installed or included in your package.json.
If you are using a build tool that depends on Libsass then you
may need to upgrade to a more recent version to use the grid helpers. Minimal
compatible versions include node-sass
1.0.0, grunt-sass
0.16.0,
gulp-sass
1.2.0 and libsass
3.0.0.
govuk_frontend_toolkit_composer is an composer package that can be added to your composer.json
You can include the toolkit as a git submodule.
To add the submodule to your project run the following command substituting the path to a subdirectory in your project's assets directory:
$ git submodule add https://github.com/alphagov/govuk_frontend_toolkit.git ./path/to/assets/govuk_frontend_toolkit
We recommend you use https
rather than ssh
for submodules as they don't require key exchanges when deploying to remote servers.
If you clone a project with the toolkit submodule installed you will need to initialise the submodule with the following command:
$ git submodule init
To update the toolkit to the latest version you can use:
$ git submodule update
Tests for this project use Jasmine for the JavaScript and Ruby's scss
and scss-lint
to check the stylesheets.
The requirements are Node.js 0.8 or higher and PhantomJS, and Ruby:
bundle install
npm install
npm test
The test suite can be run by opening the ./spec/support/LocalTestRunner.html
file in a browser for a more detailed trace of errors.
The files for unit tests and any supporting JavaScript should be added to ./spec/manifest.js
file.
At the top of a Sass file in your project you should use an @import
rule
to include the file for the mixins you require, eg if you want the
conditionals and typography mixins you should add:
@import '_conditionals';
@import '_typography';
You may need to include the relative path to the toolkit if it is installed as a submodule:
@import '../toolkit/_conditionals';
If you are compiling Sass from the command-line tool, here are some options we recommend.
In development:
sass --style expanded --line-numbers --load-path [path to]/govuk_frontend_toolkit/stylesheets input.scss output.css
In production:
sass --style compressed --load-path [path to]/govuk_frontend_toolkit/stylesheets input.scss output.css
_grid_layout.scss
_conditionals.scss
_colours.scss
_css3.scss
_typography.scss
design-patterns/_buttons.scss
design-patterns/_alpha-beta.scss
Grid helpers to enable easy cross browser grids. The grids use absolute widths in older versions of IE or percentage based widths in modern browsers.
%site-width-container
creates a 960px wide elastic container for you site content block%grid-row
container for a row of columns@mixin grid-column($width, $full-width: tablet)
a mixin to create grid columns of fraction width
These three grid helpers are designed to be used together and aren't guaranteed to work or behave in a predictable way if used in isolation.
There is also an %outdent-to-full-width
selector which can be extended to
outdent and element and cause it to take up the edge gutters and butt up to the
edge of smaller screens.
#page-container {
@extend %site-width-container;
}
.grid-row {
@extend %grid-row;
.column-third {
@include grid-column( 1/3 );
}
.column-two-thirds {
@include grid-column( 2/3 );
}
}
.hero-image {
@extend %outdent-to-full-width;
}
<div id="page-container">
<div class="grid-row">
<div class="column-two-thirds">
Main content
</div>
<div class="column-third">
Sidebar
</div>
</div>
<div class="hero-image">
<img ...>
</div>
</div>
Media query and IE helpers. These make producing responsive layouts and attaching IE specific styles to elements really easy.
To use the IE conditionals you will need to add extra stylesheets for each IE which look like:
// BASE STYLESHEET FOR IE 6 COMPILER
$is-ie: true;
$ie-version: 6;
@import "application.scss";
Where application.scss
is the name of your base stylesheet.
@mixin media($size: false, $max-width: false, $min-width: false)
note: the parameters are mutually exclusive and the first one found will be used.
$size
size
can be one of desktop
, tablet
, mobile
. desktop
and tablet
should be used to add styles to a mobile first stylesheet. mobile
should be
used to add styles to a desktop first stylesheet.
It is recommended that you primarily use desktop
for new stylesheets to
enhance mobile first when serving to mobile devices.
$min-width
$max-width
These should be set to an absolute pixel value. They will get added directly to their respective @media queries.
$ignore-for-ie
Styles that would normally be wrapped in @media queries by this mixin will be instead
added to the main block if the $is-ie
variable is true.
Setting $ignore-for-ie
to true
means those styles will not be added.
div.columns {
border: 1px solid;
@include media(desktop){
width: 30%;
float: left;
}
@include media($min-width: 500px){
width: 25%;
}
@include media($max-width: 400px){
width: 25%;
}
}
Conditially send CSS to IE browsers less than or equal to the named version.
@include ie-lte($version)
$version
version
is an integer value. Possible values are 6
, 7
, 8
.
div.columns {
border: 1px solid;
@include ie-lte(7){
border: 0;
}
}
Send CSS to a named IE version.
@include ie($version)
$version
version
is an integer value. Possible values are 6
, 7
, 8
.
div.columns {
border: 1px solid;
@include ie(6){
border: 0;
}
}
A collection of colour variables.
$treasury
$cabinet-office
$department-for-education
$department-for-transport
$home-office
$department-of-health
$ministry-of-justice
$ministry-of-defence
$foreign-and-commonwealth-office
$department-for-communities-and-local-government
$department-for-energy-and-climate-change
$department-for-culture-media-and-sport
$department-for-environment-food-and-rural-affairs
$department-for-work-and-pensions
$department-for-business-innovation-and-skills
$department-for-international-development
$government-equalities-office
$attorney-generals-office
$scotland-office
$wales-office
$purple
$purple-50
$purple-25
$mauve
$mauve-50
$mauve-25
$fuschia
$fuschia-50
$fuschia-25
$pink
$pink-50
$pink-25
$baby-pink
$baby-pink-50
$baby-pink-25
$red
$red-50
$red-25
$mellow-red
$mellow-red-50
$mellow-red-25
$orange
$orange-50
$orange-25
$brown
$brown-50
$brown-25
$yellow
$yellow-50
$yellow-25
$grass-green
$grass-green-50
$grass-green-25
$green
$green-50
$green-25
$turquoise
$turquoise-50
$turquoise-25
$light-blue
$light-blue-50
$light-blue-25
$black
$grey-1
$grey-2
$grey-3
$grey-4
$white
$link-colour
$link-active-colour
$link-hover-colour
$link-visited-colour
$text-colour: $black
$secondary-text-colour
$border-colour
$panel-colour
$canvas-colour
$highlight-colour
$page-colour
.column {
background: $green;
}
A collection of font-mixins. There are two different types of font mixins.
- Heading and Copy styles which are the font with added paddings to ensure a consistent baseline vertical grid.
- Core styles which are base font styles with no extra padding.
The following heading and copy styles exist:
heading-80
heading-48
heading-36
heading-27
heading-24
copy-19
copy-16
copy-14
h2 {
@include heading-27;
}
The following core styles exist:
core-80
core-48
core-36
core-27
core-24
core-19
core-16
core-14
@include core-[size]($line-height, $line-height-640)
$line-height
and $line-height-640
are both optional. When used it is
recomended to pass a fraction in for readability.
h1 {
@include core-48;
}
h2 {
@include core-24($line-height: (50/24), $line-height-640: (18/16));
}
Tabular numbers have numerals of a standard fixed width. As all numbers have the same width, sets of numbers may be more easily compared. We recommend using them where different numbers are likely to be compared, or where different numbers should line up with each other, eg in tables.
$tabular-numbers
is an optional variable that may be passed to the heading, copy and core styles to use (or explicitly not use) tabular numbers. When no variable is passed, the default is non-tabular.
h1 {
@include core-48;
}
h2 {
@include core-24($tabular-numbers: true);
}
external-link-default
sets up the background image for all external links.
This should be included on the default link style for a project.
After setting the default, apply includes from the following for different font sizes:
external-link-12
external-link-12-no-hover
external-link-13
external-link-13-no-hover
external-link-14
external-link-14-bold-no-hover
external-link-16
external-link-16-bold-no-hover
external-link-19
external-link-19-no-hover
external-link-heading
is a unique style a background image for headings to groups of external links.
This uses the file-url
helper which will by default output an image-url
to
be used with Compass or Rails Asset Pipeline, if you want to use a static path
then set the $path
variable to point to the public location of the toolkit
image assets.
For a set style:
@include external-link-[style]
For a specific font size:
@include external-link-[size]-[weight]-[no-hover]
/* Default link style */
a[rel="external"] {
@include external-link-default;
@include external-link-19;
}
th.external-link {
@include external-link-heading;
}
.inner a[rel="external"] {
@include external-link-16;
}
.departments a[rel="external"] {
@include external-link-16-bold-no-hover;
}
CSS3 helpers to abstract vendor prefixes.
@mixin border-radius($radius)
$radius
a pixel value.
.column {
@include border-radius(5px);
}
@mixin box-shadow($shadow)
$shadow
a value set to pass into box-shadow
.
.column {
@include box-shadow(0 0 5px black);
}
@mixin translate($x, $y)
$x
and $y
are css values.
.column {
@include translate(2px, 3px);
}
This can currently only handle linear top to bottom gradients.
@mixin gradient($from, $to)
$from
and $to
are colour values.
.column {
@include gradient(#000, #fff);
}
@mixin transition($property, $duration, $function, $delay:0s)
Match up with the respective properties from transition
.
.column {
@include transition(left, 3s, ease);
}
@mixin box-sizing($type)
$type
is one of border-box
, content-box
and padding-box
.
.column {
@include box-sizing(border-box);
}
@mixin calc($property, $calc)
$property
the property to apply the calc to.
$calc
the calculation to.
.column {
@include calc(width, "300% - 20px");
}
A mixin for creating buttons in the GOV.UK style.
@mixin button($colour)
$colour
the background colour of the button (default is $green
).
.button{
@include button;
}
.button-secondary{
@include button($grey-3);
}
.button-warning{
@include button($red);
}
The button text colour is set by the mixin to either light or dark, depending on the button background colour.
If you're applying these styles to non form elements, adding a class of 'disabled' to the element will emulate the disabled button style.
A mixin to create a GOV.UK Phase banner, with alpha/beta tag inside.
@mixin phase-banner($state)
$state
is either alpha
or beta
.
$state
sets the background colour of the phase tag to the appropriate alpha or beta colour.
.phase-banner {
@include phase-banner(alpha);
}
<div class="phase-banner">
<p>
<strong class="phase-tag">ALPHA</strong>
<span>This is a new service – your <a href="#">feedback</a> will help us to improve it.</span>
</p>
</div>
.phase-banner {
@include phase-banner(beta);
}
<div class="phase-banner">
<p>
<strong class="phase-tag">BETA</strong>
<span>This is a new service – your <a href="#">feedback</a> will help us to improve it.</span>
</p>
</div>
A mixin to create an alpha/beta tag.
@mixin phase-tag($state)
$state
is either alpha
or beta
.
$state
sets the background colour of the phase tag to the appropriate alpha or beta colour.
.alpha-tag{
@include phase-tag(alpha);
}
<h2>
Apply using the new service <span class="alpha-tag">ALPHA</span>
</h2>
.beta-tag{
@include phase-tag(beta);
}
<h2>
Apply using the new service <span class="beta-tag">BETA</span>
</h2>
The gem also includes some JavaScript which by itself will have no effect on a page. It can be included with the asset_pipeline by adding the line:
//=require govuk_toolkit
There is a forked version of the Nomensa video player included and custom GOV.UK styles to be used with it. To use it you will need to include the script on your page and include the styles nested under an appropriate selector. For example:
@import "design-patterns/media-player";
.media-player {
@include media-player;
}
You will also need to create your own initalizer to target the links you want to turn into videos. There are examples of how this works in the Nomensa Accesible Media Player repository.
GOVUK.MultiVariateTest
runs split tests to display different content, layouts etc to users.
It randomly assigns a user a cohort on first execution by setting a cookie, and on every execution sets a session level custom variable on Google Analytics to mark which cohort a user is in. This can be used to segment users in GA.
A simple content replacement test can be done by defining a set of cohorts with content. E.g.:
var test = new GOVUK.MultivariateTest({
el: '.car-tax-button',
name: 'car_tax_button_text',
customVarIndex: 555,
cohorts: {
pay_your_car_tax: {html: "Pay Your Car Tax"},
give_us_money: {html: "Give Us Money Or We Will Crush Your Car"}
}
});
A more complex test can be done by defining callbacks for what to do when a user is in each cohort:
var test = new GOVUK.MultivariateTest({
name: 'car_tax_button_text',
customVarIndex: 555,
cohorts: {
pay_your_car_tax: {callback: function() { ... }},
give_us_money: {callback: function() { ... }}
}
});
If you want one cohort to appear 25% of the time then you can optionally weight that cohort:
var test = new GOVUK.MultivariateTest({
name: 'car_tax_button_text',
customVarIndex: 555,
cohorts: {
pay_your_car_tax: {weight: 25, callback: function() { ... }}, // 25%
give_us_money: {weight: 75, callback: function() { ... }} // 75%
}
});
If you have a complex test, it may be worth extending MultivariateTest with your own. Callbacks can be strings which will call a method of that name on the current object.
Takes these options:
el
: Element to run this test on (optional)name
: The name of the text (alphanumeric and underscores)customVarIndex
: The index of the custom variable in Google Analytics. GA only gives 50 integer slots to each account, and it is important that a unique integer is assigned to each test. Current contact for assigning a custom var slot for GOV.UK is: Ashraf Chohan [email protected]defaultWeight
: Number of times each cohorts should appear in an array the random cohort is picked from, to be used in conjunction with weights on individual cohorts.cohorts
: An object that maps cohort name to an object that defines the cohort. Name must be same format as test name. Object contains keys (all optional):html
: HTML to fill element with when this cohort is picked.callback
: Function to call when this cohort is chosen. If it is a string, that method on the test object is called.weight
: Number of times this cohort should appear in an array the random cohort is picked from, defaults to thedefaultWeight
of the test.
Full documentation on how to design multivariate tests, use the data in GA and construct hypothesis tests is on its way soon.
GOVUK.PrimaryList
hides elements in a list which don't have a supplied
selector, they will then be shown when the user clicks. GOVUK.primaryLinks
is
a helper to add this behaviour to many elements.
Example markup:
<ul id="primary-list">
<li class="primary-item">Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
To add it to all lists which have items with the class primary-item
use
something like:
GOVUK.primaryLinks.init('.primary-item');
Or to add it just to that list you could use:
new GOVUK.PrimaryList($('#primary-list'), '.primary-item');
GOVUK.stickAtTopWhenScrolling
tries to add a class to an element when the top
of that element would be scrolled out of the viewport.
The following would cause the element to stay when you scroll:
<div class="js-stick-at-top-when-scrolling">something</div>
.content-fixed {
position: fixed;
top: 0;
}
.shim {
display: block;
}
GOVUK.stickAtTopWhenScrolling.init();
If you also include the stopScrollingAtFooter
JavaScript this will also try
and stop the elements before they get to the bottom.
Script to support a design of radio buttons and checkboxes requiring them to be wrapped in <label>
tags:
<label>
<input type="radio" name="size" value="medium" />
</label>
When the input is focused or its checked
attribute is set, classes are added to their parent labels so their styling can show this.
To apply this behaviour to elements with the above HTML pattern, call the GOVUK.SelectionButtons
constructor with their inputs:
var $buttons = $("label input[type='radio'], label input[type='checkbox']");
var selectionButtons = new GOVUK.SelectionButtons($buttons);
You can also call GOVUK.SelectionButtons
with a selector:
var selectionButtons = new GOVUK.SelectionButtons("label input[type='radio'], label input[type='checkbox']");
This will bind all events to the document, meaning any changes to content (for example, by AJAX) will not effect the button's behaviour.
The classes that get added to the <label>
tags can be passed in as options:
var $buttons = $("label input[type='radio'], label input[type='checkbox']");
var selectionButtons = new GOVUK.SelectionButtons($buttons, { focusedClass : 'selectable-focused', selectedClass : 'selectable-selected' });
var selectionButtons = new GOVUK.SelectionButtons("label input[type='radio'], label input[type='checkbox']", { focusedClass : 'selectable-focused', selectedClass : 'selectable-selected' });
The returned instance object includes a destroy
method to remove all events bound to either the elements or the document.
Using any of the selectionButtons
objects created above, it can be called like so:
selectionButtons.destroy();
The previous method of calling selection buttons is now deprecated. If you need to call them using this method, you will need to define this function:
GOVUK.selectionButtons = function (elms, opts) {
new GOVUK.SelectionButtons(elms, opts);
};
This method will mean the destroy
method is not available to call.
Released under the MIT Licence, a copy of which can be found in the file LICENCE
.