Utility classes
These utility classes can help avoid repeated CSS everywhere, and allow you to compose components with more flexibility.
Example: a component may not know much about the layout that it will be used inside, so the user of the component may want to add some margins. Margin utilities can be helpful for that purpose.
Note, the above example suggests a pattern of avoiding margins in your own component container elements. Our current Patient Portal CSS unfortunately does not follow that, as the code has grown. Newer components may do, however, such as alerts.
Margin and padding utilities
As the code base has grown organically, we have 2 types of margin/padding utilities:
em-based spacingrem-based spacing
rem-based will increasingly be used over the former.
The current design system has a spacing system based on multiples of 15px. The em-based
spacing utilities are scales of that.
em is also relative to the current font size of your container, so you might get
unexpected results. It was an oversight to use ems but we have decided not to try and change
it.
We have since introduced a rem-based set of margin and padding utilities. These are evolving
towards a spacing-based system based on multiples of 4px, where the rem-based utilities will be
more useful when the overall spacing system is changed to similar multiples.
em-based margin and padding utilities
Margin and padding utilities use the following convention:
{m or p}{direction}-{scale}
For example, mb-0 for margin bottom 0 or pl-3 for padding left 3.
Directions are
| Direction | Description |
|---|---|
| t | top |
| r | right |
| b | bottom |
| l | left |
Scales are
| Scale | Description |
|---|---|
| 0 | 0 |
| 1 | 0.25em |
| 2 | 0.5em |
| 3 | 1em |
| 4 | 1.5em |
| 5 | 3em |
rem-based margin and padding utilities
Margin and padding utilities use the following convention:
dr-{m or p}{direction}-{scale} and if you want all directions to get the same value, a
shortcut using dr-{m or p}-{scale} which omits the direction.
For example, dr-mb-0 for margin bottom 0 or dr-p-3 for padding scale 3 on all
sides.
Directions are
| Direction | Description |
|---|---|
| t | top |
| r | right |
| b | bottom |
| l | left |
Scales are
| Scale | Description |
|---|---|
| 0 | 0 |
| 1 | 0.4rem |
| 2 | 0.8rem |
| 3 | 1.2rem |
| 4 | 1.6rem |
| 5 | 2em |
| 6 | 2.4rem |
| 7 | 3.2rem |
| 8 | 4em |
| 9 | 4.8em |
Text alignment
Use text alignment utilities to control text alignment:
utilities: .text-left, .text-center,
.text-right
<div class="card__body dr-p-3 text-left">Left aligned text</div>
<div class="card__body dr-p-3 text-center">Center aligned text</div>
<div class="card__body dr-p-3 text-right">Right aligned text</div>
Gap utilities
Use gap utilities to control spacing between flex/grid items:
utilities: .gap-0, .gap-1, .gap-2,
.gap-3, .gap-4, .gap-5, .gap-6, .gap-7,
.gap-8, .gap-9. Also available: .gap-x-{0-9} for column-gap and
.gap-y-{0-9} for row-gap.
Gap values:
| Class | Spacing Value |
|---|---|
.gap-0 |
0 |
.gap-1 |
0.4rem |
.gap-2 |
0.8rem |
.gap-3 |
1.2rem |
.gap-4 |
1.6rem |
.gap-5 |
2rem |
.gap-6 |
2.4rem |
.gap-7 |
3.2rem |
.gap-8 |
4rem |
.gap-9 |
4.8rem |
Example:
<div class="grid grid-cols__3 gap-3">
<div class="card__body dr-p-2">Item 1</div>
<div class="card__body dr-p-2">Item 2</div>
<div class="card__body dr-p-2">Item 3</div>
</div>
Flexbox utilities
flex is powerful for 1 dimensional layout in CSS.
Prefer flex over float. Also prefer CSS grid over flex when you need
layout in two dimensions (rows and columns).
The basic use of flex is to simply add a class of flex on the container. This will use default
values.
Use any of the following classes as additional modifiers on the same element that
flex is used:
| Modifier | Description |
|---|---|
flex-align-items__start |
Align items to the start of the cross axis. |
flex-align-items__center |
Center items along the cross axis (i.e. usually along the vertical axis) |
flex-align-items__end |
Align items to the end of the cross axis. |
flex-align-items__stretch |
Stretch items to fill the cross axis. |
flex-justify-content__start |
Justify content at the start of the main axis (usually the horizontal axis). |
flex-justify-content__end |
Justifies content to sit at the end of the main axis (usually the horizontal axis). Similar to packing all child items to the right (CSS itself doesn't use left/right to account for internationalisation and different writing systems) |
flex-justify-content__center |
Center items along the main axis. |
flex-justify-content__space-between |
Will arrange items so they are evenly spread out, but the first and last items will not have spacing added to their outer edges. |
flex-justify-content__space-around |
Will arrange items so they are evenly spread out, with equal space around each item. |
flex-direction__row |
Set the main axis to run horizontally (default flex direction). |
flex-direction__column |
Set the main axis to run vertically. |
flex-wrap__wrap |
Allow flex items to wrap onto multiple lines. |
flex-wrap__nowrap |
Prevent flex items from wrapping (single line). |
Child elements of flex items can also have some modifiers:
| Modifier | Description |
|---|---|
flex-stretch |
Same as using CSS flex: auto to stretch items to fit their container |
flex-normal |
Resets the flex item to its initial width and height.
Note, a child element with a class of |
Example:
<div class="card__container">
<div class="card__body">
<p>Buttons are aligned to the right using <code>flex</code></p>
<div class="flex flex-justify-content__end">
<button class="button -primary mr-3">Primary button</button>
<button class="button -secondary">Secondary button</button>
</div>
</div>
</div>
To produce this:
Buttons are aligned to the right using flex
Grid utilities
grid is useful for 2 dimensional layout (rows and columns).
Add a class of grid to the container, then use a column modifier:
| Modifier | Description |
|---|---|
grid-cols__1 |
Single column layout (mobile-first). |
grid-cols__2 |
Two equal columns from tablet portrait and up. |
grid-cols__3 |
Three equal columns from tablet portrait and up. |
grid-cols__4 |
Four equal columns from tablet portrait and up. |
Example:
<div class="card__container">
<div class="card__body">
<p>Responsive grid using <code>grid</code> and <code>grid-cols__3</code></p>
<div class="grid grid-cols__1 grid-cols__3">
<div class="card__body dr-p-2">Item 1</div>
<div class="card__body dr-p-2">Item 2</div>
<div class="card__body dr-p-2">Item 3</div>
</div>
</div>
</div>
To produce this:
Responsive grid using grid and grid-cols__3
Skip link
A visually hidden link that becomes visible on keyboard focus. Placed as the first element in
<body>, it lets keyboard users jump past repeated navigation directly to the main content.
Usage
- Place
<a href="#main-content" class="skip-link">Skip to main content</a>as the very first child of<body>. - Add
id="main-content"to your<main>element. - Tab to it to see it appear — it hides itself off-screen until focused.
<body>
<a href="#main-content" class="skip-link">Skip to main content</a>
<nav>...</nav>
<main id="main-content">
<p>Page content here.</p>
</main>
</body>
To see the live example: tab into the box below using your keyboard — the skip link will appear.
[Tab into this box to reveal the skip link]
Separator dash
Inserts a - between adjacent .separator-dash elements using the CSS adjacent
sibling selector. Useful when items are conditionally rendered and you cannot know at template time how many
will be present.
Because the dash is added in CSS (not HTML), there is no risk of a trailing or leading dash appearing when some items are absent.
<!-- All three present: John Smith - 07700 900000 - Oncology -->
<span class="separator-dash">John Smith</span>
<span class="separator-dash">07700 900000</span>
<span class="separator-dash">Oncology</span>
<!-- Only one present — no stray dash -->
<span class="separator-dash">John Smith</span>
This will produce:
John Smith 07700 900000 Oncology
John Smith
Loading spinner
A circular CSS spinner that uses var(--theme-primary) for its rotating segment and
var(--theme-subtle) as the track. Centres itself with margin: auto.
Always include a role="status" and aria-label so screen readers announce that
content is loading.
<div class="loading" role="status" aria-label="Loading"></div>
This will produce:
Stretched link
Makes the nearest position: relative ancestor entirely clickable by expanding the
link's ::after pseudo-element to cover the container with inset: 0.
Usage
- Add
position: relativeto the card or container. - Add
.stretched-linkto the<a>inside it.
<div class="card__body" style="position: relative;">
<h3>Appointment on 12 June</h3>
<p>Cardiology — City Hospital</p>
<a href="/appointments/123" class="stretched-link">View appointment</a>
</div>
This will produce (hover anywhere on the card to see the cursor change):