# Blog Magazine Layout — React Blog Section

> A newspaper-style front page: masthead, a serif lead story with drawn cover art, a column of hairline-ruled briefs and a numbered most-read list.

- Category: [Blog Sections](https://pixelpapa.com/components/blog.md)
- Tags: blog, magazine, editorial, serif, layout
- Dependencies: motion (plus React and Tailwind CSS v4)
- Last updated: 2026-11-13
- Live preview: https://pixelpapa.com/components/blog/blog-magazine-layout

## Install

```bash
npx shadcn@latest add "https://pixelpapa.com/r/blog-magazine-layout.json"
```

The file is written to `components/pixelpapa/blog-magazine-layout.tsx`. To install manually, run `npm install motion` and copy the source below into your project. It imports `cn` from `@/lib/utils`, which every shadcn project has.

## Source

```tsx
"use client";

import { motion } from "motion/react";

type Brief = { kicker: string; title: string; dek: string; minutes: number };

const ease = [0.22, 1, 0.36, 1] as const;

const briefs: Brief[] = [
  { kicker: "Cities", title: "The night bus is the most honest map of a city", dek: "Routes drawn for the people who clean, cook and close.", minutes: 6 },
  { kicker: "Craft", title: "A luthier in Cremona is 3D-printing the moulds, not the violins", dek: "Tradition, with a tolerance of 0.1 mm.", minutes: 9 },
  { kicker: "Work", title: "Four-day weeks, two years later", dek: "What stuck at the 61 firms that never went back.", minutes: 7 },
];

const mostRead = [
  "The last lighthouse keeper of Skerryvore",
  "How a village library became a seed bank",
  "Notes on learning to swim at forty",
  "Why trains in Japan depart on a melody",
  "The quiet economics of the corner shop",
];

function LeadArt() {
  return (
    <div className="relative aspect-[16/9] overflow-hidden rounded-sm" style={{ background: "linear-gradient(180deg, var(--chart-4), var(--chart-3) 55%, var(--chart-1))" }}>
      <svg viewBox="0 0 640 360" preserveAspectRatio="xMidYMid slice" className="absolute inset-0 size-full transition-transform duration-[1200ms] ease-out group-hover:scale-105" aria-hidden>
        <circle cx="450" cy="170" r="74" fill="white" fillOpacity="0.55" />
        <circle cx="450" cy="170" r="120" fill="white" fillOpacity="0.1" />
        <path d="M0 250c80-40 150-36 230-4s170 30 250-6 110-30 160-10v130H0Z" fill="black" fillOpacity="0.22" />
        <path d="M0 290c90-30 180-24 270 0s190 20 370-14v84H0Z" fill="black" fillOpacity="0.3" />
        <g fill="black" fillOpacity="0.55">
          <path d="M148 250h10l4-92h-18Z" />
          <path d="M140 158h26v-10h-26Z" />
          <path d="M146 148h14l-2-18h-10Z" />
        </g>
        <path d="M153 136 420 96M153 136 420 150" stroke="white" strokeOpacity="0.4" strokeWidth="1.5" />
      </svg>
    </div>
  );
}

export default function BlogMagazineLayout() {
  return (
    <section className="w-full bg-background px-6 py-16 text-foreground">
      <div className="mx-auto max-w-6xl">
        <header className="border-b-4 border-double border-foreground pb-4 text-center">
          <div className="flex items-center justify-between text-[11px] tracking-[0.18em] text-muted-foreground uppercase">
            <span>Vol. XII · No. 46</span>
            <span className="hidden sm:inline">Thursday, 12 November 2026</span>
            <span>Weekend edition</span>
          </div>
          <h2 className="mt-3 font-serif text-5xl tracking-tight sm:text-7xl">The Tidewater Post</h2>
        </header>
        <nav aria-label="Sections" className="flex flex-wrap justify-center gap-x-7 gap-y-1 border-b border-border py-2.5 text-xs font-medium tracking-[0.14em] uppercase">
          {["Cities", "Craft", "Work", "Science", "Letters", "Long reads"].map((s) => (
            <a key={s} href="#" className="text-muted-foreground transition-colors hover:text-foreground">
              {s}
            </a>
          ))}
        </nav>

        <motion.div
          initial="hidden"
          whileInView="shown"
          viewport={{ once: true, amount: 0.15 }}
          transition={{ staggerChildren: 0.12 }}
          className="mt-8 grid gap-8 lg:grid-cols-[1fr_2.1fr_1fr] lg:gap-0"
        >
          <motion.div variants={{ hidden: { opacity: 0, y: 16 }, shown: { opacity: 1, y: 0, transition: { duration: 0.7, ease } } }} className="lg:order-1 lg:pr-7">
            <ul className="divide-y divide-border">
              {briefs.map((b) => (
                <li key={b.title} className="py-5 first:pt-0">
                  <a href="#" className="group block">
                    <p className="text-[11px] font-medium tracking-[0.16em] text-primary uppercase">{b.kicker}</p>
                    <h3 className="mt-2 font-serif text-xl leading-snug decoration-1 underline-offset-4 group-hover:underline">{b.title}</h3>
                    <p className="mt-1.5 text-sm text-muted-foreground">{b.dek}</p>
                    <p className="mt-2 text-xs text-muted-foreground">{b.minutes} min read</p>
                  </a>
                </li>
              ))}
            </ul>
          </motion.div>

          <motion.article
            variants={{ hidden: { opacity: 0, y: 16 }, shown: { opacity: 1, y: 0, transition: { duration: 0.7, ease } } }}
            className="border-border lg:order-2 lg:border-x lg:px-7"
          >
            <a href="#" className="group block">
              <LeadArt />
              <p className="mt-2 text-right text-[11px] text-muted-foreground italic">Illustration: Odile Marchetti for the Post</p>
              <p className="mt-4 text-center text-[11px] font-medium tracking-[0.16em] text-primary uppercase">The long read</p>
              <h3 className="mx-auto mt-3 max-w-xl text-center font-serif text-4xl leading-[1.05] tracking-tight text-balance sm:text-5xl">
                The last lighthouse keeper of Skerryvore
              </h3>
              <p className="mx-auto mt-4 max-w-lg text-center text-muted-foreground">
                For thirty-one winters Callum Reid wound the lamp by hand. Then the satellites came, and nobody told the gulls.
              </p>
            </a>
            <div className="mt-6 gap-6 border-t border-border pt-5 text-sm leading-relaxed text-foreground/80 sm:columns-2">
              <p>
                <span className="float-left mr-2 font-serif text-5xl leading-[0.85] text-foreground">T</span>
                he boat only runs on Tuesdays, weather allowing, and the weather rarely allows. Reid meets it anyway, out of
                habit, with a flask and a list of things the mainland has forgotten to send.
              </p>
              <p className="mt-3 sm:mt-0">
                “People think it is lonely,” he says, coiling a rope that has not been needed since 1994. “It is the opposite.
                Out here everything talks to you.” <a href="#" className="font-medium text-primary">Continue reading →</a>
              </p>
            </div>
            <p className="mt-4 text-xs text-muted-foreground">By Isla Ferreira · 24 min read</p>
          </motion.article>

          <motion.aside variants={{ hidden: { opacity: 0, y: 16 }, shown: { opacity: 1, y: 0, transition: { duration: 0.7, ease } } }} className="lg:order-3 lg:pl-7">
            <h3 className="border-b border-foreground pb-2 text-[11px] font-medium tracking-[0.18em] uppercase">Most read this week</h3>
            <ol>
              {mostRead.map((title, i) => (
                <li key={title} className="border-b border-border">
                  <a href="#" className="group flex gap-4 py-4">
                    <span className="font-serif text-3xl leading-none text-foreground/25 italic transition-colors group-hover:text-primary">{i + 1}</span>
                    <span className="font-serif text-lg leading-snug">{title}</span>
                  </a>
                </li>
              ))}
            </ol>
            <div className="mt-6 rounded-sm bg-muted p-5">
              <p className="font-serif text-lg leading-snug">The Sunday letter</p>
              <p className="mt-1 text-sm text-muted-foreground">One essay and three recommendations, by post or by email.</p>
              <a href="#" className="mt-3 inline-block text-sm font-medium text-primary underline-offset-4 hover:underline">
                Subscribe for £4 a month
              </a>
            </div>
          </motion.aside>
        </motion.div>
      </div>
    </section>
  );
}
```

## AI prompt

```text
Add the "Blog Magazine Layout" component from PixelPapa UI to this project.

What it is: A newspaper-style front page: masthead, a serif lead story with drawn cover art, a column of hairline-ruled briefs and a numbered most-read list.
Category: Blog Sections. Depends on: motion.

1. Install it with the shadcn CLI:
   npx shadcn@latest add "https://pixelpapa.com/r/blog-magazine-layout.json"
   (If the CLI is unavailable, fetch that URL, write files[0].content to components/pixelpapa/blog-magazine-layout.tsx and install the listed dependencies.)
2. Import it from "@/components/pixelpapa/blog-magazine-layout" and place it where I describe below.
3. Keep its animation timings and accessibility attributes. Replace the demo copy and data with content that fits my product, and use my existing theme tokens (bg-background, text-foreground, bg-primary, border-border) rather than hard-coded colours.

Where to use it: <describe the page and position here>
```

## More blog sections

- [Blog Category Filter](https://pixelpapa.com/components/blog/blog-category-filter.md): Filter chips with a sliding active pill and live counts; the post grid reflows with shared layout animation as cards pop in and out.
- [Blog Changelog Feed](https://pixelpapa.com/components/blog/blog-changelog-feed.md) (Pro): A versioned changelog with a sticky date rail, colour-coded tags you can filter by, and entries that collapse out of the timeline with layout animation.
- [Blog Featured Plus Grid](https://pixelpapa.com/components/blog/blog-featured-plus-grid.md) (Pro): One large featured story beside its drawn cover, followed by a three-up grid; covers zoom and a reading arrow slides in on hover.
- [Blog List Hover Preview](https://pixelpapa.com/components/blog/blog-list-hover-preview.md): A typographic list of posts; a floating cover card trails the cursor on a spring, tilts with its speed and flips to the hovered post's artwork.
