Shell

The page skeleton: header on top, footer at the bottom of the viewport when the page is short, and a body row where nav and aside sit beside main while there is room.

Example

View Code
<body class="shell" data-width="xs">
    <header>Site header</header>
    <div>
        <nav aria-label="Section">Section navigation</nav>
        <main>
            <h1>Page title</h1>
            <p>The main content, which takes what is left.</p>
        </main>
        <aside>Related links</aside>
    </div>
    <footer>Site footer</footer>
</body>

When to use it

Every page has a skeleton, and most of them are this one: a header, a footer that should sit at the bottom of the screen even when the page is short, and a middle that may have navigation down one side or related material down the other. Put the class on body and the landmarks do the rest. Three regions share a row once the container is about four times data-width plus the gaps; two regions need about half that.

Built from primitives

A stack with data-fill is at least as tall as the viewport, and a footer carrying data-split drops to its bottom. In the middle, a sidebar puts the nav beside the main content until the content would fall below half the width. That is the whole page.

<body class="stack" data-fill>
    <header>Site header</header>
    <div class="sidebar" data-width="sm">
        <nav aria-label="Section">Section navigation</nav>
        <main>
            <h1>Page title</h1>
            <p>The main content, which takes what is left.</p>
        </main>
    </div>
    <footer data-split>Site footer</footer>
</body>

The one-class form adds the third region: an aside after main in the same body row takes the same width as the nav and sits at the end. The body row needs its own element, the div, because three regions cannot share a row with a header and footer above and below them without one; a page with only main may skip it.

Why this name

A shell is the part of the page that is there before any content is, and stays when the content changes. Foundation 6 readers built this with .grid-container and a sticky-footer snippet from the forums; the shell is both, with the landmarks as the API.

Attributes

Attribute Type Values Default Description
data-gap enum none, xs, sm, md, lg, xl, 2xl, 3xl, xs-sm, xs-md, xs-lg, xs-xl, xs-2xl, xs-3xl, sm-md, sm-lg, sm-xl, sm-2xl, sm-3xl, md-lg, md-xl, md-2xl, md-3xl, lg-xl, lg-2xl, lg-3xl, xl-2xl, xl-3xl, 2xl-3xl md Space between the rows, and between nav, main, and aside.
data-width enum 2xs, xs, sm, md, lg, xl, 2xl sm The preferred width of nav and aside. Three regions share a row once the container is about four times this width plus the gaps; two regions need about half that.

Children

  • > *: at least 1. In order: an optional header, the body (a div holding nav, main, and aside, in that source order, or a bare main when there are no side regions), and an optional footer.
  • > header: 0 to 1
  • > footer: 0 to 1
  • > main: 0 to 1
  • > div: 0 to 1. The body row. Its nav and aside take data-width; its main takes the rest and never drops below half.

Tokens

Token Description
--yeti-cover-height The shell's minimum block size; the viewport by default.
--yeti-space-md The default gap.
--yeti-width-sm The default nav and aside width.
Internal tokens (may change between minor versions) - `--_yeti-gap` - `--_yeti-width`

Accessibility

  • Meant for body or the page's outermost element. The landmarks do the work: one main; a label on nav when the page has more than one; aside for content that is complementary, not primary.

Browser support

  • Used without guards: flexbox gap, dvh units, :has()
  • Behind @supports: nothing

JavaScript

None. This component is CSS only.

Available since 7.0.0.