diff --git a/app/views/examples/form-controls-states/index.njk b/app/views/examples/form-controls-states/index.njk
new file mode 100644
index 0000000000..280983dcf8
--- /dev/null
+++ b/app/views/examples/form-controls-states/index.njk
@@ -0,0 +1,310 @@
+{% extends "layout.njk" %}
+
+{% from "back-link/macro.njk" import govukBackLink %}
+{% from "checkboxes/macro.njk" import govukCheckboxes %}
+{% from "radios/macro.njk" import govukRadios %}
+
+{% block beforeContent %}
+ {{ govukBackLink({
+ "href": "/"
+ }) }}
+{% endblock %}
+
+{% block content %}
+
+
+
+
+ {{ govukCheckboxes({
+ fieldset: {
+ legend: {
+ text: "Display",
+ classes: "govuk-fieldset__legend--s"
+ }
+ },
+ idPrefix: "display",
+ name: "sort",
+ classes: "govuk-checkboxes--small",
+ items: [
+ {
+ value: "consultations",
+ text: "Consultations"
+ },
+ {
+ value: "guidance",
+ text: "Guidance"
+ },
+ {
+ value: "notices",
+ text: "Notices"
+ },
+ {
+ value: "reports",
+ text: "Reports"
+ }
+ ]
+ }) }}
+
+ {{ govukRadios({
+ fieldset: {
+ legend: {
+ text: "Include",
+ classes: "govuk-fieldset__legend--s"
+ }
+ },
+ idPrefix: "include",
+ name: "include",
+ classes: "govuk-radios--small",
+ items: [
+ {
+ value: "everything",
+ text: "Everything"
+ },
+ {
+ value: "something",
+ text: "Something"
+ },
+ {
+ value: "nothing",
+ text: "Nothing"
+ }
+ ]
+ }) }}
+
+
+ {{ govukRadios({
+ fieldset: {
+ legend: {
+ text: "Sort by",
+ classes: "govuk-fieldset__legend--s"
+ }
+ },
+ formGroup: {
+ classes: "govuk-!-margin-bottom-0"
+ },
+ idPrefix: "sort",
+ name: "sort",
+ classes: "govuk-radios--small govuk-radios--inline",
+ items: [
+ {
+ value: "relevance",
+ text: "Relevance"
+ },
+ {
+ value: "created",
+ text: "Created"
+ },
+ {
+ value: "title",
+ text: "Title"
+ }
+ ]
+ }) }}
+
+ {{ govukCheckboxes({
+ name: "grobulate",
+ classes: "govuk-checkboxes--small",
+ formGroup: {
+ classes: "govuk-!-margin-bottom-0"
+ },
+ items: [
+ {
+ value: "grobulate",
+ text: "Grobulate results"
+ }
+ ]
+ }) }}
+
+
+
+
Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit
+
+
Aenean lacinia bibendum nulla sed consectetur. Vestibulum id ligula porta felis euismod semper. Donec id elit non mi porta gravida at eget metus.
+
+
+
+
Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh
+
+
Cras justo odio, dapibus ac facilisis in, egestas eget quam. Maecenas sed diam eget risus varius blandit sit amet non magna.
+
+
+
+
Bibendum Commodo Ullamcorper Vulputate
+
+
Cras mattis consectetur purus sit amet fermentum. Curabitur blandit tempus porttitor.
+
+
+{% endblock %}
diff --git a/src/components/checkboxes/_checkboxes.scss b/src/components/checkboxes/_checkboxes.scss
index 22e19391a6..0ff04c3325 100644
--- a/src/components/checkboxes/_checkboxes.scss
+++ b/src/components/checkboxes/_checkboxes.scss
@@ -8,7 +8,10 @@
@import "../label/label";
@include govuk-exports("govuk/component/checkboxes") {
- $govuk-checkboxes-size: govuk-spacing(7);
+
+ $govuk-touch-target-size: 44px;
+ $govuk-checkboxes-size: 40px;
+ $govuk-small-checkboxes-size: 24px;
$govuk-checkboxes-label-padding-left-right: govuk-spacing(3);
.govuk-checkboxes__item {
@@ -20,7 +23,7 @@
min-height: $govuk-checkboxes-size;
margin-bottom: govuk-spacing(2);
- padding: 0 0 0 $govuk-checkboxes-size;
+ padding-left: $govuk-checkboxes-size;
clear: left;
}
@@ -31,25 +34,33 @@
}
.govuk-checkboxes__input {
- position: absolute;
-
- z-index: 1;
- top: 0;
- left: 0;
-
- width: $govuk-checkboxes-size;
- height: $govuk-checkboxes-size;
+ $input-offset: ($govuk-touch-target-size - $govuk-checkboxes-size) / 2;
cursor: pointer;
- // IE8 doesn’t support pseudoelements, so we don’t want to hide native elements there.
+ // IE8 doesn’t support pseudo-elements, so we don’t want to hide native
+ // elements there.
@include govuk-not-ie8 {
+ position: absolute;
+
+ z-index: 1;
+ top: $input-offset * -1;
+ left: $input-offset * -1;
+
+ width: $govuk-touch-target-size;
+ height: $govuk-touch-target-size;
margin: 0;
+
opacity: 0;
}
- // add focus outline to input element for IE8
@include govuk-if-ie8 {
+ margin-top: 10px;
+ margin-right: $govuk-checkboxes-size / -2;
+ margin-left: $govuk-checkboxes-size / -2;
+ float: left;
+
+ // add focus outline to input
&:focus {
outline: $govuk-focus-width solid $govuk-focus-colour;
}
@@ -62,17 +73,11 @@
padding: 8px $govuk-checkboxes-label-padding-left-right govuk-spacing(1);
cursor: pointer;
// remove 300ms pause on mobile
- -ms-touch-action: manipulation;
touch-action: manipulation;
}
- .govuk-checkboxes__hint {
- display: block;
- padding-right: $govuk-checkboxes-label-padding-left-right;
- padding-left: $govuk-checkboxes-label-padding-left-right;
- }
-
- .govuk-checkboxes__input + .govuk-checkboxes__label::before {
+ // [ ] Check box
+ .govuk-checkboxes__label::before {
content: "";
box-sizing: border-box;
position: absolute;
@@ -82,11 +87,13 @@
height: $govuk-checkboxes-size;
border: $govuk-border-width-form-element solid currentColor;
background: transparent;
-
- // padding-bottom: 1px;
}
- .govuk-checkboxes__input + .govuk-checkboxes__label::after {
+ // ✔ Check mark
+ //
+ // The check mark is a box with a border on the left and bottom side (└──),
+ // rotated 45 degrees
+ .govuk-checkboxes__label::after {
content: "";
position: absolute;
@@ -107,10 +114,16 @@
background: transparent;
}
+ .govuk-checkboxes__hint {
+ display: block;
+ padding-right: $govuk-checkboxes-label-padding-left-right;
+ padding-left: $govuk-checkboxes-label-padding-left-right;
+ }
+
// Focused state
.govuk-checkboxes__input:focus + .govuk-checkboxes__label::before {
- // Since box-shadows are removed when users customise their colours
- // We set a transparent outline that is shown instead.
+ // Since box-shadows are removed when users customise their colours, we set
+ // a transparent outline that is shown instead.
// https://accessibility.blog.gov.uk/2017/03/27/how-users-change-colours-on-websites/
outline: $govuk-focus-width solid transparent;
outline-offset: $govuk-focus-width;
@@ -132,6 +145,10 @@
opacity: .5;
}
+ // =========================================================
+ // Conditional reveals
+ // =========================================================
+
$conditional-border-width: $govuk-border-width-mobile;
// Calculate the amount of padding needed to keep the border centered against the checkbox.
$conditional-border-padding: ($govuk-checkboxes-size / 2) - ($conditional-border-width / 2);
@@ -154,4 +171,135 @@
margin-bottom: 0;
}
}
+
+ // =========================================================
+ // Small checkboxes
+ // =========================================================
+
+ .govuk-checkboxes--small {
+
+ $input-offset: ($govuk-touch-target-size - $govuk-small-checkboxes-size) / 2;
+ $label-offset: $govuk-touch-target-size - $input-offset;
+
+ .govuk-checkboxes__item {
+ @include govuk-clearfix;
+ min-height: 0;
+ margin-bottom: 0;
+ padding-left: $label-offset;
+ float: left;
+ }
+
+ // Shift the touch target into the left margin so that the visible edge of
+ // the control is aligned
+ //
+ // ┆What colours do you like?
+ // ┌┆───┐
+ // │┆[] │ Purple
+ // └┆▲──┘
+ // ▲┆└─ Check box pseudo element, aligned with margin
+ // └─── Touch target (invisible input), shifted into the margin
+ .govuk-checkboxes__input {
+ @include govuk-not-ie8 {
+ left: $input-offset * -1;
+ }
+
+ @include govuk-if-ie8 {
+ margin-left: $govuk-small-checkboxes-size * -1;
+ }
+ }
+
+ // Adjust the size and position of the label.
+ //
+ // Unlike larger checkboxes, we also have to float the label in order to
+ // 'shrink' it, preventing the hover state from kicking in across the full
+ // width of the parent element.
+ .govuk-checkboxes__label {
+ margin-top: -2px;
+ padding: 13px govuk-spacing(3) 13px 1px;
+ float: left;
+
+ @include govuk-media-query($from: tablet) {
+ padding: 11px govuk-spacing(3) 10px 1px;
+ }
+ }
+
+ // [ ] Check box
+ //
+ // Reduce the size of the check box [1], vertically center it within the
+ // touch target [2]
+ .govuk-checkboxes__label::before {
+ top: $input-offset - $govuk-border-width-form-element; // 2
+ width: $govuk-small-checkboxes-size; // 1
+ height: $govuk-small-checkboxes-size; // 1
+ }
+
+ // ✔ Check mark
+ //
+ // Reduce the size of the check mark and re-align within the checkbox
+ .govuk-checkboxes__label::after {
+ top: 15px;
+ left: 6px;
+ width: 9px;
+ height: 3.5px;
+ border-width: 0 0 3px 3px;
+ }
+
+ // Fix position of hint with small checkboxes
+ //
+ // Do not use hints with small checkboxes – because they're within the input
+ // wrapper they trigger the hover state, but clicking them doesn't actually
+ // activate the control.
+ //
+ // (If you do use them, they won't look completely broken... but seriously,
+ // don't use them)
+ .govuk-checkboxes__hint {
+ padding: 0;
+ clear: both;
+ }
+
+ // Align conditional reveals with small checkboxes
+ .govuk-checkboxes__conditional {
+ $margin-left: ($govuk-small-checkboxes-size / 2) - ($conditional-border-width / 2);
+ margin-left: $margin-left;
+ padding-left: $label-offset - ($margin-left + $conditional-border-width);
+ clear: both;
+ }
+
+ // Hover state for small checkboxes.
+ //
+ // We use a hover state for small checkboxes because the touch target size
+ // is so much larger than their visible size, and so we need to provide
+ // feedback to the user as to which checkbox they will select when their
+ // cursor is outside of the visible area.
+ .govuk-checkboxes__item:hover .govuk-checkboxes__input:not(:disabled) + .govuk-checkboxes__label::before {
+ box-shadow: 0 0 0 $govuk-hover-width $govuk-hover-colour;
+ }
+
+ // Because we've overridden the border-shadow provided by the focus state,
+ // we need to redefine that too.
+ //
+ // We use two box shadows, one that restores the original focus state [1]
+ // and another that then applies the hover state [2].
+ .govuk-checkboxes__item:hover .govuk-checkboxes__input:focus + .govuk-checkboxes__label::before {
+ // sass-lint:disable indentation
+ box-shadow: 0 0 0 $govuk-focus-width $govuk-focus-colour, // 1
+ 0 0 0 $govuk-hover-width $govuk-hover-colour; // 2
+ }
+
+ // For devices that explicitly don't support hover, don't provide a hover
+ // state (e.g. on touch devices like iOS).
+ //
+ // We can't use `@media (hover: hover)` because we wouldn't get the hover
+ // state in browsers that don't support `@media (hover)` (like Internet
+ // Explorer) – so we have to 'undo' the hover state instead.
+ @media (hover: none), (pointer: coarse) {
+ .govuk-checkboxes__item:hover .govuk-checkboxes__input:not(:disabled) + .govuk-checkboxes__label::before {
+ box-shadow: initial;
+ }
+
+ .govuk-checkboxes__item:hover .govuk-checkboxes__input:focus + .govuk-checkboxes__label::before {
+ box-shadow: 0 0 0 $govuk-focus-width $govuk-focus-colour;
+ }
+ }
+ }
}
diff --git a/src/components/checkboxes/checkboxes.yaml b/src/components/checkboxes/checkboxes.yaml
index f49b3918db..a3f9bf7e30 100644
--- a/src/components/checkboxes/checkboxes.yaml
+++ b/src/components/checkboxes/checkboxes.yaml
@@ -421,3 +421,122 @@ examples:
html: |