On this page
Styled inline and block text elements for body content
- Overview
- Rules and guidance
- Properties
- Styles
- Accessibility
When to use
- For body paragraphs and running prose
- For supplementary text at a smaller size, such as captions or legal disclaimers, using Small
- For inline emphasis within a sentence using Strong (bold) or Em (italic)
- For strikethrough text when showing a removed or superseded value using LineThrough
- For superscript and subscript notation using Sup and Sub
When not to use
- For page or section headings - use Heading (Heading1 through Heading4) instead.
- For list items - use List (Ul, Ol, Li) instead.
- For term-definition pairs - use List (Dl, Dt, Dd) or Summary List instead.
Anatomy
- Paragraph (P, the primary block-level text element)
- Small text (Small, reduced size, used inline or as a modifier on P)
- Inline emphasis (Strong, Em, LineThrough, used inside other text elements)
- Superscript / Subscript (Sup, Sub, used inline for notation)
Basic usage
Edit live code
<> <P>An example of body text.</P> <P> An example of <Em>emphasis</Em> </P> <P> An example of <Strong>strong text</Strong>. </P> <P> An example with <LineThrough>line through</LineThrough>. </P> <P> <Small>An example of small text.</Small> </P> <P> An example with superscript<Sup>1</Sup> and subscript<Sub>2</Sub>. </P> </>
Variants and features
Paragraph
P is the standard body text element. It renders a p tag with responsive font size and appropriate vertical margins. Use it for any block of prose content.
Edit live code
<> <P>Your direct debit is collected on the 1st of each month.</P> <P>If you want to change the amount, you can do this in your account settings.</P> </>
Small text
Small reduces the font size to the small scale from the design token system. It renders a small element and is typically used inline within a P or on its own for captions, legal text, or secondary information.
Edit live code
<P>Your estimated bill is £142. <Small>Based on average household usage.</Small></P>
Bold and semi-bold
Strong renders a strong element with fontWeights.bold. Use it to emphasise a word or phrase that is genuinely important within a sentence.
SemiStrong renders a strong element with fontWeights.semiBold. Use it for moderate emphasis, such as term labels within a sentence, where full bold would be visually heavy.
Note: SemiStrong is not exported from the Nebula public API. Use Strong for emphasis in application code.
Edit live code
<P>Your next payment of <Strong>£142.00</Strong> is due on 1 February 2025.</P>
Italic
Em renders an em element with italic styling. Use it for titles of works, technical terms introduced for the first time, or other cases where italic has semantic meaning. Do not use it for decorative effect.
Edit live code
<P>This tariff is known as <Em>Flex 12</Em>.</P>
Strikethrough
LineThrough renders a span with text-decoration: line-through. Use it to show that a value has been removed or replaced, such as an original price alongside a discounted price.
Edit live code
<P><LineThrough>£180.00</LineThrough> £142.00 per year</P>
Superscript and subscript
Sup and Sub render sup and sub elements at the small font size. Use for footnote markers, mathematical notation, or chemical formulae.
Edit live code
<> <P>Your tariff includes a standing charge<Sup>1</Sup>.</P> <P>Emissions are measured in CO<Sub>2</Sub>e.</P> </>
usage
- Body text should use Nebula Text components (P, Small, Strong, Em, etc.) rather than raw HTML elementsNebula text components apply responsive font sizes, spacing, and color from the design token system. Raw elements bypass these.Copy rule ID for text.no-raw-elements
- P should be used for any block of prose content that is not a heading or listCopy rule ID for text.p-for-prose
- P must not be used to visually style text to look like a headingApplying heading-like styling to a P element breaks document structure for screen reader users. Use a Heading component instead.Copy rule ID for text.no-heading-from-text
- Small should be used for supplementary text such as captions, legal disclaimers, or secondary labelsSmall text is harder to read at small viewport sizes. Reserve it for genuinely secondary content.Copy rule ID for text.small-for-secondary
- LineThrough should be accompanied by surrounding text or a visually hidden label that conveys the same meaning for screen reader usersThe CSS text-decoration line-through value is not announced by all screen readers.Copy rule ID for text.linethrough-accessible-context
- P should not have its color overridden outside the themeP color is set to colors.body. Overriding it may break contrast ratios against background tokens.Copy rule ID for text.color-not-overridden
content
- Strong should be used to emphasise genuinely important information, not for decorative stylingStrong maps to the strong HTML element, which has semantic weight. Overuse dilutes its meaning.Copy rule ID for text.strong-for-meaning
- Em should be used when italic has semantic meaning (titles, technical terms, stress emphasis), not for decorative effectEm maps to the em HTML element, which has semantic meaning for screen readers. Decorative use of italic is misleading.Copy rule ID for text.em-for-semantic-emphasis
- LineThrough should be used only to indicate that a value has been removed or superseded, not for decorationScreen readers may not convey strikethrough styling. A visually hidden label may be needed to communicate the meaning to screen reader users.Copy rule ID for text.linethrough-for-removed-value
composition
- Strong, Em, Small, LineThrough, Sup, Sub should be used inside a block-level element such as P rather than as standalone block elementsThese are inline elements. Using them as standalone blocks may produce unexpected layout and is semantically incorrect.Copy rule ID for text.inline-elements-inside-block
P
Also accepts all props from HTMLAttributes.
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
as | ElementType | — | No | Renders the component as a different element or component, e.g. `as="section"`. |
forwardedAs | ElementType | — | No | Like `as`, but passed on to the component being wrapped, for when a styled wrapper should keep its own element and change the one beneath it. |
Strong
Also accepts all props from HTMLAttributes.
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
as | ElementType | — | No | Renders the component as a different element or component, e.g. `as="section"`. |
forwardedAs | ElementType | — | No | Like `as`, but passed on to the component being wrapped, for when a styled wrapper should keep its own element and change the one beneath it. |
Em
Also accepts all props from HTMLAttributes.
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
as | ElementType | — | No | Renders the component as a different element or component, e.g. `as="section"`. |
forwardedAs | ElementType | — | No | Like `as`, but passed on to the component being wrapped, for when a styled wrapper should keep its own element and change the one beneath it. |
Small
Also accepts all props from HTMLAttributes.
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
as | ElementType | — | No | Renders the component as a different element or component, e.g. `as="section"`. |
forwardedAs | ElementType | — | No | Like `as`, but passed on to the component being wrapped, for when a styled wrapper should keep its own element and change the one beneath it. |
Sup
Also accepts all props from HTMLAttributes.
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
as | ElementType | — | No | Renders the component as a different element or component, e.g. `as="section"`. |
forwardedAs | ElementType | — | No | Like `as`, but passed on to the component being wrapped, for when a styled wrapper should keep its own element and change the one beneath it. |
Sub
Also accepts all props from HTMLAttributes.
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
as | ElementType | — | No | Renders the component as a different element or component, e.g. `as="section"`. |
forwardedAs | ElementType | — | No | Like `as`, but passed on to the component being wrapped, for when a styled wrapper should keep its own element and change the one beneath it. |
LineThrough
Also accepts all props from HTMLAttributes.
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
as | ElementType | — | No | Renders the component as a different element or component, e.g. `as="section"`. |
forwardedAs | ElementType | — | No | Like `as`, but passed on to the component being wrapped, for when a styled wrapper should keep its own element and change the one beneath it. |
Styles
p
font-family: ${fonts.body};
line-height: ${lineHeights.body};
font-weight: ${fontWeights.normal};
color: ${colors.body};
font-size: ${responsiveFontSizes.body[0]};
margin-top: ${space[1]};
margin-bottom: ${space[1]};
${mediaQueries.smallAndUp} {
font-size: ${responsiveFontSizes.body[1]};
margin-top: ${space[2]};
margin-bottom: ${space[2]};
}
&:first-child {
margin-top: 0;
}
&:last-child {
margin-bottom: 0;
}
small
font-size: ${responsiveFontSizes.small[0]};
${mediaQueries.smallAndUp} {
font-size: ${responsiveFontSizes.small[1]};
}
strong
font-weight: ${fontWeights.bold};
semi-strong
font-weight: ${fontWeights.semiBold};
em
font-style: italic;
line-through
text-decoration: line-through;
sup
vertical-align: super;
font-size: ${responsiveFontSizes.small[0]};
${mediaQueries.smallAndUp} {
font-size: ${responsiveFontSizes.small[1]};
}
sub
vertical-align: sub;
font-size: ${responsiveFontSizes.small[0]};
${mediaQueries.smallAndUp} {
font-size: ${responsiveFontSizes.small[1]};
}
In brief
Text is made of native text elements: p, small, strong, em, sup and sub. The words are what a screen reader reads, so the meaning has to be in them. LineThrough is a span with a line through it, which a screen reader does not announce.
What Nebula provides
- P, Small, Strong, SemiStrong, Em, Sup and Sub render native elements (SemiStrong is a strong with a lighter weight).
- The font sizes are smaller below the small breakpoint.
- Text is never a tab stop.
Accessible design
Put the meaning in the words, not in the style
Italics, a line through the text and a smaller size are only visual. A screen reader user does not hear a struck-through price as removed, so write "Was £10, now £8" and not a crossed-out £10 beside "£8".
WCAG: 1.3.1 Info and Relationships
Check the colour contrast at the mobile font size as well
The text is smaller below the small breakpoint, and the contrast ratio a text needs depends on its size.
WCAG: 1.4.3 Contrast (Minimum)
Accessible development
Use Strong and Em only for importance and stress
A strong or em element says the text is important or stressed. For appearance alone, use a style on a plain element, and use Sup and Sub only for real superscript and subscript.
WCAG: 1.3.1 Info and Relationships
Use one P for each paragraph
Line breaks inside one paragraph, or a div of loose text, give a screen reader user no paragraphs to move between.
WCAG: 1.3.1 Info and Relationships
Accessibility testing status
Reviewed on 9 October 2026 against v17.0.1.
| Test | Status | Tested with |
|---|---|---|
| Default state | Tested | axe-core via the Storybook test runner (CI) |
| Advanced states | Partially tested | axe-core via the Storybook test runner (CI) |
| Keyboard navigation | Manually tested | keyboard (reported by the owner) |
| Screen reader | Partially tested | VoiceOver with Chrome (reported by the owner) |
What these tests and statuses mean
The table records which checks were run on this component on its own. It is not a statement of WCAG conformance, and it does not cover how the component is used.
The tests
- Default state: The component as it first appears, before anything is clicked or changed.
- Advanced states: Every other state and variant: error, open, selected, each size and style, and hovering.
- Keyboard navigation: Whether every function can be reached and used with the keyboard alone, with a visible focus ring.
- Screen reader: Whether a screen reader announces what is on screen correctly: the name, the role and any state.
The statuses
- Tested: Every check in this row passed in an automated run that repeats on every pull request.
- Manually tested: Every check in this row was run once, by a person or with a tool they started, and all of them passed. It is not re-run on every change.
- Partially tested: Some checks in this row were run once and passed; the rest are still to do.
- Issue found: A check in this row failed. The ticket is shown beside the status.
- Not tested: No check in this row has been run yet.
- Not applicable: This row does not apply to the component, for the reason given beside it.