---
title: Spacer
description: Vertical space on the scale, optionally with a rule and a label. Built for Markdown.
source: https://adamjurek.com/components/spacer
---

## Home


<!-- ::start:showcase demo="spacer" height="360" -->
<!-- ::end:showcase -->

## The argument against this component

Space should come from the things being spaced. A component that sets its own
bottom margin knows how far it sits from the next thing, and a separate element
whose only job is to be empty is usually a sign that something above it is
missing a rule.

Inside a component, that argument is right, and this is the wrong tool.

## Where this is used

| Where | What for |
| --- | --- |
| Any `.md` on this site | the `::start:spacer` block |
| `packages/ui/docs/nav-bar/index.md` | the labelled break before "Where it is used" |
| `templates/post.md` | in the template, so a new post starts with it available |


## Install

<!-- ::start:tabs -->

### TanStack

```shell
tanstack add https://adamjurek.com/r/tanstack/spacer.json
```

### shadcn

```shell
pnpm dlx shadcn@latest add https://adamjurek.com/r/shadcn/spacer.json
```

### pnpm

```shell
pnpm add @sushindustries/ui @sushindustries/atoms
```

<!-- ::end:tabs -->

## What you get

| | |
| --- | --- |
| Version | 0.1.0 |
| Category | layout · Page structure |
| Files | `spacer.tsx`, `grid.tsx` |
| Dependencies | None |
| Tags | markdown, spacing, no-deps |

> [!NOTE] No runtime dependencies
> It brings nothing with it beyond the stylesheet.

## Get Started


Install commands are on Home, attached from the registry - they are not written
here, because a second copy is a copy that goes stale. This tab starts after the
install worked.

## Use it

```tsx
import { Spacer } from "@sushindustries/ui";

export function Example() {
	return (
		<>
			<p>Above.</p>
			<Spacer size={6} label="Later" />
			<p>Below.</p>
		</>
	);
}
```

## What you should see

A gap between the two paragraphs, taller than the line-height around it,
with a hairline rule and the word "Later" sitting on it, centred. Drop the
`label` and `rule` props and the gap is still there but draws nothing -
`Spacer` with neither is deliberately invisible, so if you are checking that
it worked, add a `label` first and remove it once you trust the height.

## If nothing happens

A blank `<Spacer size={5} />` with no `rule` and no `label` is meant to look
like nothing changed - it is `aria-hidden` and unstyled beyond its height.
That is correct, not a sign the install failed; the height is still there in
the layout even though there is nothing to see.


## Guides


## Where it is right

Markdown. An author writing a post has no markup to hang a margin on. The
alternatives are an empty paragraph, a `<br>`, or a `---`, and `---` is a
semantic thematic break that merely looks like a line - using it for spacing
puts a section boundary in the document outline that the author did not mean.

Given that something is going to be written there anyway, it may as well take a
step on the scale rather than a number somebody picked, and it may as well be
able to draw the rule a writer was reaching for.

<!-- ::start:spacer size="6" label="Like this" -->
<!-- ::end:spacer -->

That gap is a spacer with a label. The rule sits in the middle of the space
rather than at its edge, so what is above and below stays symmetric and the
spacer keeps the height it declared.

## In Markdown

```text
<!-- ::start:spacer size="6" label="Later" -->
<!-- ::end:spacer -->

<!-- ::start:spacer size="5" rule="true" -->
<!-- ::end:spacer -->
```

`size` is a step from 1 to 7. A value outside that falls back rather than
throwing, because a bad attribute in a document should not take the page down.

## Accessibility

A spacer with no label is `aria-hidden`. A gap is not content, and announcing
one is noise in a screen reader for something a sighted reader experiences as
nothing.

A spacer with a label is not hidden, because at that point it is a caption.


## API


<!-- generated:api -->

## Props

| Prop | Type | Default | Does |
| --- | --- | --- | --- |
| `size?` | `Space` | `5` | A step on the spacing scale. |
| `rule?` | `boolean` | - | Draw a hairline in the middle of the gap. |
| `label?` | `string` | - | An optional caption sitting on the rule. Implies `rule`. |

<!-- /generated:api -->

## Notes

`label` implies `rule` - passing a `label` draws the hairline whether or not
`rule` is also set, because a caption with nothing to sit on reads as a
mistake. There is no way to show a label without the rule underneath it.
`rule={true}` with no `label` draws a plain hairline and no text, which is
the setting a Markdown `---` reaches for without meaning a document
section break.


## Examples


Examples are the tab where the component is shown doing a job, not
demonstrating a prop. The API tab already lists the props.

<!-- ::start:showcase demo="spacer" height="420" -->
<!-- ::end:showcase -->

Press Compare. The frames are real viewports, so a layout that breaks at 320
breaks here too rather than in somebody's hands.

## In a page

```tsx
import { Spacer } from "@sushindustries/ui";

export function Article({ intro, body }: { intro: string; body: string }) {
	return (
		<article className="prose">
			<p>{intro}</p>
			<Spacer size={6} label="Later" />
			<p>{body}</p>
		</article>
	);
}
```

## What this example is not

This is the JSX form, for the rare case of composing `Spacer` directly
inside a hand-written page. Its home is Markdown - the
`<!-- ::start:spacer size="6" label="Later" --><!-- ::end:spacer -->` block
this site's own posts and docs pages use - because that is where there is
no markup left to hang a margin on.
