Skip to content

Footer

Site footer chrome. Columns stay grid and stack.

To pin a direct-child <footer> to the bottom of the viewport, put af-body on <body>. That is the Body shell. Skip it when overlays append to body (Angular CDK).

<body class="af-body">
  <main id="main">…</main>
  <footer class="af-footer">…</footer>
</body>
<footer class="af-footer">
  <div class="af-container">
    <div class="af-grid-1 af-grid-2@sm af-grid-4@lg af-gap-lg">
      <div class="af-stack af-gap-sm">
        <p class="af-text-strong">Airframe</p>
        <p class="af-text-sm af-text-muted">Structural UI for teams that ship.</p>
      </div>
      <nav class="af-stack af-gap-sm" aria-label="Product">
        <p class="af-text-strong af-text-sm">Product</p>
        <ul class="af-stack-sm">
          <li>
            <a href="#" class="af-link">Features</a>
          </li>
          <li>
            <a href="#" class="af-link">Pricing</a>
          </li>
        </ul>
      </nav>
      <nav class="af-stack af-gap-sm" aria-label="Resources">
        <p class="af-text-strong af-text-sm">Resources</p>
        <ul class="af-stack-sm">
          <li>
            <a href="#" class="af-link">Docs</a>
          </li>
          <li>
            <a href="#" class="af-link">Guides</a>
          </li>
        </ul>
      </nav>
      <nav class="af-stack af-gap-sm" aria-label="Company">
        <p class="af-text-strong af-text-sm">Company</p>
        <ul class="af-stack-sm">
          <li>
            <a href="#" class="af-link">About</a>
          </li>
          <li>
            <a href="#" class="af-link">Blog</a>
          </li>
        </ul>
      </nav>
    </div>
    <div class="af-footer-meta">
      <p>© 2026 Airframe. MIT licensed.</p>
      <nav class="af-inline af-gap-md" aria-label="Legal">
        <a href="#" class="af-link">Privacy</a>
        <a href="#" class="af-link">Terms</a>
      </nav>
    </div>
  </div>
</footer>

af-footer-meta is the copyright / legal row. It draws the divider; you do not need a separate <hr>.