Article Layout

Page layout for long-form written content.

Why we rebuilt our onboarding from scratch

Long-form content flows in a single measured column, set for sustained reading rather than scanning.

Paragraph spacing, line length and a restrained type scale keep attention on the text itself.

html

<div class="article article--narrow">
  
  <nav class="article__toc" aria-label="Table of contents">
    <p class="article__toc-title">On this page</p>
    <ul><li><a href="#overview">Overview</a></li><li><a href="#details">Details</a></li><li><a href="#summary">Summary</a></li></ul>
  </nav>
  
  <article class="article__body">
    <h1 class="article__title" style="color:#241430;">Why we rebuilt our onboarding from scratch</h1>
    <p class="article__byline">By Jordan Ames &middot; 5 min read</p>
    <p>Long-form content flows in a single measured column, set for sustained reading rather than scanning.</p>
    <p>Paragraph spacing, line length and a restrained type scale keep attention on the text itself.</p>
  </article>
</div>
<style>
.article { display: flex; gap: 32px; font: 16px/1.7 system-ui, sans-serif; color: #241430; padding: 24px; }
.article--narrow .article__body { max-width: 52ch; }
.article--wide .article__body { max-width: 74ch; }
.article__toc { flex: 0 0 160px; font-size: 13px; }
.article__toc-title { font-weight: 700; margin: 0 0 8px; text-transform: uppercase; letter-spacing: .04em; color: #241430aa; }
.article__toc ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.article__toc a { color: #241430; text-decoration: none; }
.article__toc a:hover, .article__toc a:focus-visible { text-decoration: underline; }
.article__title { margin: 0 0 8px; font-size: 30px; font-weight: 800; }
.article__byline { margin: 0 0 20px; color: #241430aa; font-size: 14px; }
.article__body p { margin: 0 0 16px; color: #241430dd; }
</style>

tailwind

<div class="article-tw article-tw--narrow flex gap-8 font-sans text-[#241430] p-6">
  
  <nav class="flex-none w-40 text-[13px]" aria-label="Table of contents">
    <p class="font-bold m-0 mb-2 uppercase tracking-wide text-[#241430]/70">On this page</p>
    <ul class="list-none m-0 p-0 flex flex-col gap-1.5"><li><a href="#overview" class="text-[#241430] no-underline hover:underline focus-visible:underline">Overview</a></li><li><a href="#details" class="text-[#241430] no-underline hover:underline focus-visible:underline">Details</a></li><li><a href="#summary" class="text-[#241430] no-underline hover:underline focus-visible:underline">Summary</a></li></ul>
  </nav>
  
  <article class="article-tw__body">
    <h1 class="m-0 mb-2 text-3xl font-extrabold" style="color:#241430;">Why we rebuilt our onboarding from scratch</h1>
    <p class="m-0 mb-5 text-[#241430]/70 text-sm">By Jordan Ames &middot; 5 min read</p>
    <p class="m-0 mb-4 text-[#241430]/85">Long-form content flows in a single measured column, set for sustained reading rather than scanning.</p>
    <p class="m-0 mb-4 text-[#241430]/85">Paragraph spacing, line length and a restrained type scale keep attention on the text itself.</p>
  </article>
</div>
<style>
.article-tw--narrow .article-tw__body { max-width: 52ch; }
.article-tw--wide .article-tw__body { max-width: 74ch; }
</style>

react

export function ArticleLayout({
  title = "Why we rebuilt our onboarding from scratch",
  showToc = true,
  showByline = true,
  width = "narrow",
  accent = "#241430",
}) {
  const maxWidth = width === "wide" ? "74ch" : "52ch";
  return (
    <div style={{ display: "flex", gap: 32, font: "16px/1.7 system-ui, sans-serif", color: "#241430", padding: 24 }}>
      {showToc && (
        <nav aria-label="Table of contents" style={{ flex: "0 0 160px", fontSize: 13 }}>
          <p style={{ fontWeight: 700, margin: "0 0 8px", textTransform: "uppercase", letterSpacing: "0.04em", color: "#241430aa" }}>On this page</p>
          <ul style={{ listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: 6 }}>
            <li><a href="#overview" style={{ color: "#241430" }}>Overview</a></li>
            <li><a href="#details" style={{ color: "#241430" }}>Details</a></li>
            <li><a href="#summary" style={{ color: "#241430" }}>Summary</a></li>
          </ul>
        </nav>
      )}
      <article style={{ maxWidth: maxWidth }}>
        <h1 style={{ margin: "0 0 8px", fontSize: 30, fontWeight: 800, color: accent }}>{title}</h1>
        {showByline && <p style={{ margin: "0 0 20px", color: "#241430aa", fontSize: 14 }}>By Jordan Ames &middot; 5 min read</p>}
        <p style={{ margin: "0 0 16px", color: "#241430dd" }}>Long-form content flows in a single measured column, set for sustained reading rather than scanning.</p>
        <p style={{ margin: "0 0 16px", color: "#241430dd" }}>Paragraph spacing, line length and a restrained type scale keep attention on the text itself.</p>
      </article>
    </div>
  );
}