---
title: "Article"
description: "Wrap a page's content in Article to get a readable text column and automatic spacing between the sections inside it."
url: https://docs.systhema.app/components/article
version: unreleased (main)
docs_index: https://docs.systhema.app/llms.txt
---

`Article` is the page-level wrapper for your content. It renders an `<article>` that centres loose content in a readable column, lets sections and full-bleed figures span the page, and decides the spacing between them. Use one per page, inside `<main>`.

```tsx preview iframe bleed height=760 title="Article"
import { Article, Heading, Paragraph, Section } from '@systhemaui/next'

export default function Demo() {
  return (
    <Article>
      <Heading.h1>Field notes from the coast</Heading.h1>
      <Paragraph type="lead">
        Loose content in an article sits in a centred column at container width, minus the article
        padding.
      </Paragraph>
      <Paragraph>
        Headings, paragraphs and lists placed directly inside get the rich-text rhythm, so you never
        space them by hand.
      </Paragraph>
      <Section layoutBackground="alternative" padding={2}>
        <Heading.h2>A section spans the full width</Heading.h2>
        <Paragraph>
          Sections break out of the text column and carry their own grid. The article puts one
          section padding of space around them.
        </Paragraph>
      </Section>
      <Paragraph>Back in the article column after the section.</Paragraph>
    </Article>
  )
}
```

## Import

```tsx
import { Article } from '@systhemaui/next'
```

In a React app without Next.js, import it from `@systhemaui/react`.

## How it lays out its children

`Article` renders `<article class="article richtext">` and treats its direct children in two groups:

- **Loose content** (headings, paragraphs, lists, quotes) is centred and capped at `--container-width` minus twice `--article-padding-x`. It is spaced by the rich-text rhythm.
- **Bands** (`<section>` elements such as [`Section`](https://docs.systhema.app/components/section.md) and [`Feature`](https://docs.systhema.app/components/feature.md), and `Figure` with `width="screen"`) span the article's full width. `.columns`, `.stack`, cards and accordions keep their own width.

The article itself has `--section-padding-y` of block padding. A band that is the first or last child removes the article's padding on that side, so a page that starts with a full-bleed image has no gap above it.

## Examples

### Spacing between sections

Every section gets one section padding of margin, and two adjacent sections share it. Two neighbouring sections with neither a `theme` nor a `layoutBackground` also lose the padding between them, so they read as one band. Give one of them a background when they should read as two. Two adjacent sections that both set the same `theme` and `layoutBackground` merge into one band as well.

```tsx preview iframe bleed height=880 title="Spacing between sections"
import { Article, Heading, Paragraph, Section } from '@systhemaui/next'

export default function Demo() {
  return (
    <Article>
      <Section padding={2}>
        <Heading.h3>Plain section</Heading.h3>
        <Paragraph>No theme, no background.</Paragraph>
      </Section>
      <Section padding={2}>
        <Heading.h3>Another plain section</Heading.h3>
        <Paragraph>The padding between the two is removed: they read as one band.</Paragraph>
      </Section>
      <Section padding={2} theme="default" layoutBackground="alternative">
        <Heading.h3>A section with a background</Heading.h3>
        <Paragraph>A background starts a new band with its own padding.</Paragraph>
      </Section>
      <Section padding={2} theme="default" layoutBackground="alternative">
        <Heading.h3>Same theme and background again</Heading.h3>
        <Paragraph>
          Matching theme and background on adjacent sections merges them into one band.
        </Paragraph>
      </Section>
    </Article>
  )
}
```

The full rule set is on the [Spacing model](https://docs.systhema.app/concepts/spacing-model.md#section-padding) page.

### Theme and background

`theme` and `layoutBackground` work as on `Section`: `theme` sets `data-theme` for everything inside, `layoutBackground` paints the article with the `main` or `alternative` page background. A section inside that repeats the article's own theme and background merges into it instead of adding a second band.

```tsx preview iframe bleed height=480 title="Dark article"
import { Article, Heading, Paragraph } from '@systhemaui/next'

export default function Demo() {
  return (
    <Article theme="dark" layoutBackground="main">
      <Heading.h2>Night mode for one page</Heading.h2>
      <Paragraph>
        theme="dark" re-resolves every color below the article from the dark color-system mode.
      </Paragraph>
      <Paragraph type="small">With the default tokens, the modes are default and dark.</Paragraph>
    </Article>
  )
}
```

### Starting with a full-bleed image

```tsx preview iframe bleed height=620 title="Full-bleed figure first"
import { Article, Figure, Heading, Image, Paragraph } from '@systhemaui/next'

export default function Demo() {
  return (
    <Article>
      <Figure width="screen">
        <Image
          src="/demo-assets/coast.webp"
          alt="Waves breaking on a rocky coast"
          width={1800}
          height={1200}
          aspectRatio="21/9"
        />
      </Figure>
      <Heading.h2>No gap above the image</Heading.h2>
      <Paragraph>
        A screen-width figure as the first child removes the article's top padding.
      </Paragraph>
    </Article>
  )
}
```

## Props

All other props go to the `<article>` element.

<!-- generated:props @systhemaui/react ArticleProps -->

| Prop                            | Type                                       | Default | Description |
| ------------------------------- | ------------------------------------------ | ------- | ----------- |
| `theme`                         | `ColorSystem` (`dark`, `default`)          | -       |             |
| `layoutBackground`              | `LayoutBackground` (`main`, `alternative`) | -       |             |
| …and all `<article>` attributes |                                            |         |             |

<!-- /generated -->

## HTML and CSS

The same structure in plain HTML:

```html
<main id="main-content">
  <article class="article richtext">
    <h1 class="color-heading text-h1">Field notes from the coast</h1>
    <p class="text-body color-body">Loose content sits in the article column.</p>
    <section class="py-section bg-layout-alternative">
      <div class="grid-default container">
        <div class="richtext col-mx-2">…</div>
      </div>
    </section>
  </article>
</main>
```

The spacing rules are generated per color-system mode and layout background:

<!-- generated:utilities article -->

| Class                   | Styles                                                                                                                                                                                                                                                                                                                                                                               |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `article`               | `& { width: 100%; padding-block: var(--section-padding-y, 48px); }`<br>`&:has( > :first-child:is(section, .figure-w-full, .figure-w-screen)) { padding-top: 0px; }`<br>`&:has( > :last-child:is(section, .figure-w-full, .figure-w-screen)) { padding-bottom: 0px; }`<br>`&  > *:first-child { margin-top: 0px; }`<br>`&  > *:last-child { margin-bottom: 0px; }`<br>+ 20 more rules |
| `bg-layout-main`        | `background-color: var(--color-layout-bg-main);`                                                                                                                                                                                                                                                                                                                                     |
| `bg-layout-alternative` | `background-color: var(--color-layout-bg-alternative);`                                                                                                                                                                                                                                                                                                                              |

<!-- /generated -->

## Next.js

`@systhemaui/next` re-exports `Article` from `@systhemaui/react` unchanged. It is a server component.

## Accessibility

`<article>` has the `article` role, which is not a landmark. The page landmark is the `<main id="main-content">` around it, which the skip link targets. Use one `Article` per page and start it with the page's single `<Heading.h1>` (or a hero that renders it). See [Landmarks and the skip link](https://docs.systhema.app/concepts/accessibility.md#landmarks-and-the-skip-link).

## Related

- [Section](https://docs.systhema.app/components/section.md)
- [Spacing model](https://docs.systhema.app/concepts/spacing-model.md)
- [Themes and backgrounds](https://docs.systhema.app/concepts/themes.md)
- [Figure](https://docs.systhema.app/components/figure.md)
