
Editorial Magazine Homepage
grid-template-areas plus one container query.Published
20 hand-coded CSS blog layouts for magazine homepages, news sites, personal archives, newsletter back-issues, recipe and podcast blogs, and long-form journalism. Covers full page templates — magazine grids, sticky year separators, Medium-style 65ch readers, drop caps and floated pull quotes, dev tutorials with a sticky code panel, photo essays, and sticky related-story sidebars. 12 are pure CSS with no JavaScript. Scoped under .bl-NN for no-collision pasting, prefers-reduced-motion guarded, framework-agnostic.
Related15 CSS Card Grid Layouts30 CSS Sidebar Layouts30 CSS Grid Layouts31 CSS Hero Sections

grid-template-areas plus one container query.Published

<marquee>), a five-region grid with a lead story, a most-read column, and a two-row wire feed. Eight lines of JS keep the clock ticking — everything else is CSS.Published

position:sticky — no scroll listeners, no IntersectionObserver, no library.Published

flex-direction instead of re-rendering the DOM.Published

aspect-ratio-locked so the grid reserves its space before a single byte of image downloads. Prep-time and difficulty badges float over the image, the metadata strip aligns across all cards, and each card is a real link region — the whole card is clickable without nesting anchors or faking it with JavaScript.Published

--h — no canvas, no audio-analyser, no 40kb wave library.Published

animation-timeline: scroll() ties a scale-x animation directly to the document's scroll position, so it runs off the main thread and costs nothing. Wrapped around it, a proper long-form page — full-bleed hero, breakout figures, a sticky chapter rail and a 68ch measure.Published

initial-letter with a hand-tuned ::first-letter fallback, pull quotes that float into the measure and let text wrap around them, small caps for the opening line, and hanging punctuation. Every effect is one CSS rule — no spans, no wrapper divs, no JS.Published

ch, line-height that scales with the measure, spacing set by the flow rather than per-element margins, and breakout media that escapes the column without a single negative margin. This is the baseline every article page should start from.Published

:checked + sibling selectors), line numbers are CSS counters, and the only JavaScript is a five-line clipboard copy. The sticky panel becomes a collapsible block on mobile instead of a squashed column.Published

<dl> — the semantically correct element for Q&A — with attribute-driven speakers so a three-way panel needs no new classes.Published

@property + a scroll-driven animation (yes, animated numbers with no JavaScript), a draggable before/after image comparison built on clip-path and a range input, and testimonials that don't look like a template.Published

<details>, and an up-next rail whose active row is driven by one data attribute. Selecting an episode swaps the poster, title and metadata in place — twelve lines of JavaScript, no framework, and the rail becomes a horizontal scroll-snap strip on mobile.Published

Published

Published

<details>, no JS), the article in the middle at a 72ch measure, an “on this page” rail on the right, and prev/next chapter cards at the foot that show where you are going, not just an arrow. Includes the details every docs site forgets — a version badge, a copy-anchor affordance on headings, and a note/warning callout system.Published

Published

scroll-snap and edge fade masks, live result counts, and an empty state. Filtering is fifteen lines of vanilla JS over the DOM, announced politely to screen readers — the accessibility half every filter UI skips.Published

:user-invalid so no error appears until you have actually finished typing, and shows a real success state driven by :valid — all without JavaScript.Published

scroll-snap-type: x mandatory doing the alignment. A scroll-driven progress bar tracks position in pure CSS, and the arrow buttons are eight lines of scrollBy for mouse users who want them.Published
max-inline-size: 65ch. The ch unit is the width of the digit zero in the current font, so it tracks your typeface rather than guessing a pixel value. Below about 45 characters the eye returns too often and rhythm breaks; above roughly 85 it loses the start of the next line. Pair it with a line height around 1.6-1.7 for body copy, tightening toward 1.2 for large headings, since generous leading helps at small sizes and looks slack at display sizes. For fluid sizing use clamp() rather than breakpoint steps: font-size: clamp(1rem, 0.95rem + 0.25vw, 1.125rem) scales smoothly without a jump at an arbitrary width. Two finishing touches that cost one line each: text-wrap: balance on headings so a title never leaves one orphaned word on its own line, and text-wrap: pretty on paragraphs to prevent single-word last lines. Demo 09 is the reference reader layout.grid-template-columns: [full-start] minmax(1rem,1fr) [content-start] min(65ch, 100% - 2rem) [content-end] minmax(1rem,1fr) [full-end]. Every child defaults to the content column via grid-column: content, and anything that should escape simply says grid-column: full or grid-column: breakout. No negative margins, no calc(50% - 50vw) hacks, and nothing breaks when the container is not the viewport. The older negative-margin technique still appears in tutorials and it fails in two common cases: inside a container with padding, and when a scrollbar makes 100vw wider than the actual content box, producing horizontal overflow. If you need to support it anyway, overflow-x: clip on the wrapper contains the damage. Demos 07, 14 and 19 use the named-grid approach for full-bleed heroes, photo essays and inline newsletter callouts respectively.position: sticky fails silently more often than any other CSS layout property, and it is almost always one of three causes. First, the sticky element's parent must be taller than the element — sticky positions within its containing block, so if the sidebar's parent is exactly as tall as the sidebar there is nowhere to travel. In a grid this bites when align-items: stretch makes the sidebar column full-height; set align-self: start on it. Second, any ancestor with overflow: hidden, auto or scroll silently makes itself the scroll port and the sticky stops working — use overflow-x: clip instead when you only meant to kill horizontal scroll. Third, sticky needs a threshold: top: 0 alone is fine, but if you have a sticky site header, offset by its height with top: calc(var(--header-h) + 1rem) or the sidebar will slide underneath it. For a related-stories rail that is taller than the viewport, make the rail itself scrollable with max-height: calc(100vh - 2rem); overflow-y: auto. Demo 15 implements the full pattern.<article>, and its heading is the page's single <h1>. Metadata goes in a <header> inside the article, with the publication date as a real <time datetime="2026-08-10"> so machines get an unambiguous value while humans read the formatted version. Section headings step down without skipping levels — an <h2> never jumps to <h4>, because screen reader users navigate by heading level and gaps read as missing content. Images that carry meaning use <figure> with <figcaption>, and decorative ones get an empty alt="" rather than being described. A related-posts rail is a <nav aria-label="Related stories">, not a bare div. Author details belong in the header near the byline rather than only in a footer bio. On the SEO side, this structure maps directly onto Article structured data — headline, datePublished, author, image — so you are not writing the same information twice in two formats.animation: grow linear both; animation-timeline: scroll(root block) with keyframes moving transform: scaleX(0) to scaleX(1). Because it runs off the main thread, the bar stays smooth even while JavaScript is busy. Scale rather than animating width — width triggers layout on every frame, transform does not. To track only the article rather than the whole page, give the article view-timeline-name: --article and point the bar at it, so progress starts at the first paragraph instead of the masthead. For browsers without scroll timelines, a rAF-throttled listener writing a single custom property is about fifteen lines and the visual CSS stays identical; gate it behind CSS.supports('animation-timeline', 'scroll()') so modern engines never run it. On accessibility: a progress bar that merely duplicates the scrollbar is decoration and should be aria-hidden; one that communicates something the scrollbar does not needs role="progressbar" with a live aria-valuenow. Demo 07 ships both paths.article, header, nav with a discernible label, figure and figcaption — so assistive technology gets structure rather than a soup of divs. Heading levels never skip. Every interactive control is a real button or a with a visible :focus-visible ring at 2px minimum and 3:1 contrast, and hit targets are at least 44 by 44 CSS pixels. All motion is guarded by prefers-reduced-motion: reduce. On performance, the layout choices matter more than any script: images carry explicit dimensions or a locked aspect-ratio so cumulative layout shift stays at zero, which is the single most common blog CLS failure. Fonts should use font-display: swap with a metric-compatible fallback so text is readable during load without reflowing. The sticky sidebars and progress bars animate compositor-only properties, never width or top. And because 12 of the 20 need no JavaScript at all, there is nothing to hydrate before a reader can start reading..astro file in src/layouts/ with a <slot /> where the content collection renders; the CSS drops in unchanged, and 12 of the 20 need no client directive at all because they ship no JavaScript. In Next.js App Router, the equivalent is layout.tsx for the shell plus a page component for the article body; only the reading progress, filter bar and a few interactive demos need 'use client'. For WordPress, the markup maps onto single.php and archive.php, or a block theme's templates/single.html; the scoped class names avoid collisions with whatever the parent theme already ships, which is the usual pain there. Ghost and Hugo follow the same shape with their own template syntax. For Tailwind v4, the grid track definitions and the named breakout columns are worth keeping as plain CSS in a @layer rather than translating to utilities — a grid-template-columns with named lines is far more readable as CSS than as an arbitrary-value class.15 hand-coded CSS aspect-ratio demos for video embeds, product galleries, IAB ad slots, native dialogs, and CLS-safe placeholders: 16:9 iframe YouTube embed with click-to-load facade + up-next rail, 21:9 full-screen hero video with min-height/max-height:100svh guardrails + Ken Burns drift, 1:1 Instagram-style square grid with 2×2 feature tile, 4:3 magazine card image cover, 9:16 vertical stories rail (TikTok/Reels/Shorts pattern) with scroll-snap + segment bars, 4:5 apparel product image gallery with radio-driven state + 1:1 thumbnails, 1:1 zoom thumbnail carousel with pointer-tracked --zx/--zy magnifier, prevent-layout-shift placeholder with live PerformanceObserver CLS meter (before/after side-by-side lab), dynamic content fallback with three policies (bend/strict/auto) via :has() toggle, IAB ad banner slots (728×90 leaderboard, 300×250 medium rectangle, 300×600 half-page, 320×50 mobile) with skeletons + container-query mobile swap, responsive modal dialog sized min(92vw, 88svh×16/9, 1080px) with @starting-style animation, responsive OpenStreetMap iframe wrapper with 16:9 → 1:1 container-query narrow swap, media query orientation live HUD + resize:both container-ratio playground, object-fit logo cloud with contain/cover/fill switcher via :has(), and side-by-side padding-top hack (height:0 + padding-top:56.25%) → modern aspect-ratio migration comparison with live ratio picker. 11 truly Pure CSS + 4 with a tiny optional vanilla JS snippet (facade swap, pointer magnifier, CLS meter, native dialog). Every demo is scoped under a unique .car-NN prefix so it drops into any project without CSS collisions, ships prefers-reduced-motion guards, and is framework-agnostic (works as-is in React, Vue, Svelte, Astro, Next.js, Remix, or plain HTML).
6 production CSS bento grid layouts with 12 hand-coded designs — Apple-style product showcase, SaaS feature value-prop matrix, analytics dashboard overview, creative portfolio, e-commerce category hub, and link-in-bio social hub. Each topic ships 2 sub-variants side-by-side so visitors see both a keynote aesthetic and a paper-doc variant at once. Container queries, CSS Grid, zero dependencies, copy-paste ready.
15 production CSS card grid layouts covering the most-searched grid patterns plus originals built for real use cases — auto-fit responsive blog archive grid, asymmetric bento-box feature grid, equal-height product grid, fluid Pinterest-style masonry, team directory face grid, 3D hover-flip card grid, stratified duotone bento, editorial tabloid bento with masthead and TOC, use-case showcase grid, SaaS pricing comparison with featured tier, Vercel-style testimonial wall with featured 2x2, Airbnb-style hero photo collage with location pills, SaaS stats dashboard with CSS-bar sparklines, editorial featured-article magazine grid with category-coded pills, and a Liquid Glass bento grid with per-tile refraction rims (Apple iOS 26 / macOS Tahoe aesthetic). Every layout scoped under .cg-NN, zero dependencies, copy-paste ready.