layout slop

Fourteen layout patterns that mark a page as rushed or machine-generated, each shown live next to the fix. The rule behind all fourteen: space and position carry grouping, and grouping is a decision. A layout that lets defaults decide (equal columns, uniform gaps, full-width text) tells the reader nobody weighed the blocks against each other. Pattern source: impeccable.style/slop; the reasoning, demos and samples are ours.

tiny numbered labels

A section gets a tiny "01" marker above its heading when nothing on the page depends on reading order. The rule: a number is a claim that order matters; it must be load-bearing or absent. The cost: the reader searches for the sequence (do I need section 1 first?), fails to find one, and learns the page decorates instead of structures.

A: numbers with no sequence

01

pricing

usage-based, billed per deploy and per build minute.

02

support

shared slack channel with a four-hour first response.

the sections are peers; the numbers imply a path that does not exist.

B: the heading stands alone

pricing

usage-based, billed per deploy and per build minute.

support

shared slack channel with a four-hour first response.

same content; the scroll already gives the order, so no marker is needed.

ruling
Number a label only when the reader must follow the order (steps, ranks, a ledger). Sections of a page are not a sequence; the scroll is.
<h3 class="text-base text-zinc-100">pricing</h3>
<p class="pt-2 text-sm text-zinc-400">usage-based, billed per deploy and per build minute.</p>

cards flush to the scroller edge

A horizontal scroller lets its first card sit exactly on the container edge, corner radius and all. The rule: content aligns with the layout's gutter even while it scrolls, and the next card peeks to promise more. The cost: the flush card looks broken against the rounded frame, and with no peek the reader cannot tell the row scrolls at all.

A: flush and clipped

integrationsconfigured
alertsconfigured
audit logconfigured
ssoconfigured

the first card sits on the edge; the last one is cut with no hint of more.

B: gutter inside, peek outside

integrationsconfigured
alertsconfigured
audit logconfigured
ssoconfigured

the scroller pads itself to the gutter; a full card plus a sliver of the next stays visible.

ruling
A scroller owns a horizontal gutter at least as wide as the layout's; its items stay clear of the frame, and the cut-off card at the edge is the affordance.
<div class="overflow-x-auto rounded-xl bg-zinc-900 px-4 py-4">
<div class="flex gap-3">
<article class="w-40 shrink-0 ...">...</article>
...
</div>
</div>

text under an overlay

A gradient or dimming layer is stacked on top of live text to make a background work. The rule: an overlay dims the image, never the words; text sits on a solid fill or outside the overlay entirely. The cost: contrast now depends on what the image happens to put behind each word, which the author does not control and the reader cannot fix.

A: the scrim crosses the text

ship on friday

freeze opens at noon and the rollback plan is one command.

the same sentence sits on image, on scrim, and on bright sky, depending on position.

B: the band carries the text

ship on friday

freeze opens at noon and the rollback plan is one command.

same content; the image keeps the top, and the caption sits on a solid fill below it.

ruling
Overlays belong to imagery. If words must sit on a photo, give them a solid band or a scrim that covers their whole line box, and check the contrast against the brightest part of the image.
<figure class="overflow-hidden rounded-xl">
<div class="h-20 bg-gradient-to-br from-sky-400 to-amber-300"></div>
<figcaption class="bg-zinc-900 p-4">
<h3 class="text-base text-zinc-100">ship on friday</h3>
<p class="text-sm text-zinc-400">freeze opens at noon...</p>
</figcaption>
</figure>

unbalanced columns

Content is split into equal columns without checking what each column holds, so one runs long and the other leaves a hole. The rule: column width follows column weight; a grid gives more track to the heavier side. The cost: the short column reads as missing content, and the long one wraps into a ribbon no one wants to read.

A: equal tracks, unequal content

Deploys are immutable and pinned by digest, so a rollback is a pointer move, not a rebuild. Builds run on the same image as production and keep the last ten artifacts warm at the edge.

rollbacksone click

the right column holds four words and a void below them.

B: tracks follow weight

Deploys are immutable and pinned by digest, so a rollback is a pointer move, not a rebuild. Builds run on the same image as production and keep the last ten artifacts warm at the edge.

rollbacksone click

same content; the text takes two thirds, the fact takes one, and nothing floats in a hole.

ruling
Split columns by measured weight, not by count. If a side only earns a line, it does not earn half the track.
<div class="grid grid-cols-3 gap-4 p-6">
<p class="col-span-2 text-sm text-zinc-400">...the heavy side...</p>
<div class="text-sm text-zinc-400">...the light side...</div>
</div>

heading closer to the previous section

A heading sits as far from its own content as from the section above it, so the eye binds it to the wrong block. The rule: a heading is closer to what it names than to what precedes it; space above a section must exceed the heading-to-content gap. The cost: the reader reaches a heading, guesses which block it owns, and guesses wrong.

A: one uniform gap

billing runs per build minute and per deploy, invoiced monthly.

retention

artifacts stay warm for ten builds, then fall back to cold storage.

the heading is equidistant from both paragraphs; ownership is a coin flip.

B: space groups, not items

billing runs per build minute and per deploy, invoiced monthly.

retention

artifacts stay warm for ten builds, then fall back to cold storage.

same content; the section break is double the heading gap, so the heading visibly belongs below.

ruling
Set the space above a section to twice the heading-to-content gap. If the heading cannot answer "whose am I" by position, the spacing is wrong.
<section class="flex flex-col gap-2 p-6">
<p>...previous section...</p>
<div class="flex flex-col gap-2 pt-6"> <!-- section break: pt-6 -->
<h3>retention</h3> <!-- heading gap: gap-2 -->
<p>artifacts stay warm...</p>
</div>
</section>

the hero metric

A display-size number ("10×", "99.99%") is set as the loudest thing on the page, stripped of its baseline and unit. The rule: a number is content, so it carries what it is measured against; emphasis never substitutes for that context. The cost: the reader either supplies a flattering baseline of their own or discounts the claim entirely, and both outcomes are failures.

A: loud, contextless

10×

faster deploys

10× than what, measured how, for whom? the type size made the question bigger, not the answer.

B: the claim carries its measurement

Deploys that took 14 minutes on our previous runner finish in 84 seconds on the cached path, measured across the last 200 builds of this repository.

same claim, at prose scale, with the baseline and the measurement in the sentence.

ruling
A metric appears at display size only with its unit, baseline and sample in the same view. Otherwise it stays at prose size inside the sentence that proves it.
<p class="text-sm text-zinc-400">
Deploys that took <strong>14 minutes</strong> on our previous runner finish in
<strong>84 seconds</strong> on the cached path, measured across the last 200 builds.
</p>

identical card grids

Every item in a grid gets the same card, size and weight, so the entry the reader should look at first is nowhere to be found. The rule: a grid communicates ranking; the primary item earns more track or a stronger fill, and the rest recede. The cost: the reader scans three equal boxes, absorbs none of the priority the author had in mind, and picks at random.

A: three equal boxes

scale

everything in team, plus sso and audit logs

team

unlimited projects and preview deploys

hobby

free for personal projects

the flagship plan and two footnotes carry identical weight.

B: the recommendation leads

team

unlimited projects and preview deploys. the plan most teams want.

scale: everything in team, plus sso and audit logs

hobby: free for personal projects

same content; the recommended plan takes two tracks and a fill, the others recede to a list.

ruling
Before rendering a card grid, name the item a reader should take. If there is one, weight it; if there is genuinely none, a plain list is the honest layout.
<div class="grid grid-cols-3 gap-3">
<div class="col-span-2 rounded-xl border border-emerald-500/60 bg-emerald-950/30 p-4">
<p>team: the recommendation</p>
</div>
<div class="text-xs text-zinc-500">the other two, as lines</div>
</div>

monotonous spacing

Every pair of blocks gets the same gap, so related and unrelated content sit at equal distances. The rule: spacing groups; the gap inside a group must be visibly smaller than the gap between groups. The cost: proximity stops meaning anything, and the reader parses one undifferentiated column instead of named clusters.

A: one gap everywhere

editortab sizeword wrapterminalscrollbackfont size

each setting is exactly as far from its group title as from the next group.

B: groups read as groups

editortab sizeword wrap
terminalscrollbackfont size

same content; the tight gap binds each pair to its title, the wide gap separates the groups.

ruling
Use two spacing steps and keep them far apart: tight inside a group, wide between groups. One middle value groups nothing.
<div class="flex flex-col gap-6"> <!-- between groups -->
<div class="flex flex-col gap-1"> <!-- inside a group -->
<span>editor</span>
<span>tab size</span>
</div>
</div>

nested cards

A card holds another card, which holds another, each with its own border and fill. The rule: depth is one fill step per level, not a border per level; a bordered box means a section boundary. The cost: the reader counts frames instead of reading, and every level of box-within-box spends attention on structure nobody meant.

A: a card in a card in a card

workspace

security

require two-factor for all members

three borders and three fills between the reader and one setting.

B: one surface, rules inside

workspace · security

require two-factor for all members

same content; one fill step, and inner structure is a divider plus indentation.

ruling
One border per view region. Inside a card, separate with dividers, indentation and a single fill step; open a new bordered box only for a new top-level region.
<div class="rounded-xl border border-zinc-700 bg-zinc-900 p-4">
<p>workspace · security</p>
<div class="mt-3 border-l border-zinc-700 pl-3">
require two-factor for all members
</div>
</div>

long lines

Prose runs the full content width, past ninety characters per line. The rule: comfortable reading ends around 45 to 75 characters; past that the eye loses the return path to the next line. The cost: rereads, skipped lines, and a page that reads twice as long as its word count.

A: full-width prose

Deploys are immutable and pinned by digest, builds reuse the production image so parity is structural, and the last ten artifacts stay warm at the edge nearest the visitor, which is why a rollback is a pointer move rather than a rebuild and why restores finish before the on-call finishes reading the page.

over a hundred characters per line at this width; the eye drops or doubles lines on the return.

B: measured to the reader

Deploys are immutable and pinned by digest, builds reuse the production image so parity is structural, and the last ten artifacts stay warm at the edge nearest the visitor, which is why a rollback is a pointer move rather than a rebuild and why restores finish before the on-call finishes reading the page.

same sentence, capped near 65 characters; the return sweep stays inside the eye's comfortable span.

ruling
Cap prose at a measure of 45 to 75 characters (about max-w-xl to max-w-prose). Wider tracks are for tables and code, which scroll instead of wrap.
<p class="max-w-xl text-sm text-zinc-400">
Deploys are immutable and pinned by digest...
</p>

overflow past the page

A wide element pushes past the viewport and takes the whole page with it into sideways scrolling. The rule: the page never scrolls sideways; a wide child scrolls inside the nearest panel that owns it. The cost: the reader's scroll wheel now scrolls the wrong axis, the header drifts off screen, and on touch devices the whole page rubber-bands.

A: the child drags the page

deploys

namestatuslatencyregiondigest

the wide table sits straight in the page body, so reading the last column drags the heading and every other block out of the frame.

B: the panel scrolls, the page stays

deploys

namestatuslatencyregiondigest

same columns; the table scrolls inside its own panel and the heading never moves.

ruling
Put overflow-x-auto on the smallest panel that owns the wide content, and give that panel's contents w-max or explicit widths. The document element never gains a horizontal scrollbar.
<div class="overflow-x-auto rounded-xl bg-zinc-900">
<table class="w-max text-sm"> <!-- w-max: the table, not the page, decides width -->
...
</table>
</div>

clipped popovers

A popover renders inside an ancestor with overflow-hidden or a transform, and the ancestor's frame cuts it. The rule: a floating layer must be able to leave every clipping ancestor, which is what portals are for. The cost: the menu works in the demo, breaks in the first container that clips, and the fix is a one-line style hunt through six ancestors.

A: the card clips the menu

usage

billing period closes in 4 days

actions

export usage csv

view per-project totals

close period now

overflow-hidden on the card (for its rounded cover) cuts the menu at the card's edge.

B: the popover leaves the card

usage

billing period closes in 4 days

actions

export usage csv

view per-project totals

close period now

same card, same menu; the portal renders the menu above the card's frame, so the clip never touches it and the last item survives.

ruling
Render floating layers through a portal to document.body and position them from the trigger's rect. An ancestor that needs overflow-hidden for its own design then costs nothing.
import { createPortal } from 'react-dom'
function Menu({ trigger }: { trigger: DOMRect }) {
return createPortal(
<div
className="fixed z-50 w-48 rounded-lg bg-zinc-800 p-2"
style={{ left: trigger.left, top: trigger.bottom + 4 }} // dynamic values only
>...</div>,
document.body,
)
}

cramped padding

Text and controls sit two or four pixels from their container's edge, and controls touch each other. The rule: a container insets its content on the 4px grid, and interactive siblings keep a gap of at least 8px; comfort is measured at finger size, not at design size. The cost: the reader reads crowding as low quality, and on touch screens the mis-taps are literal.

A: 4px walls, 2px seams

delete workspace

this removes every project and cannot be undone

the title hugs the frame and the two actions collide into one target.

B: 16px inset, 8px seams

delete workspace

this removes every project and cannot be undone

same content on the same grid; every element has air and every button is its own target.

ruling
Cards inset at 16px or 24px, controls keep 8px of separation, and nothing readable sits closer than 12px to a border. Tighten only inside dense data displays, never in dialogs.
<div class="rounded-xl border bg-zinc-900 p-4"> <!-- card: p-4 -->
<p>delete workspace</p>
<div class="flex gap-2 pt-3"> <!-- controls: gap-2 -->
<button class="px-3 py-1.5">cancel</button>
<button class="px-3 py-1.5">delete</button>
</div>
</div>

text touching the page edge

Content runs to the viewport edge with no gutter, so lines begin and end against raw screen. The rule: the layout owns side gutters (24px here) and every page keeps them at every width; edge to edge is for full-bleed fills, never for text. The cost: on notched phones and curved panels the first and last characters are physically hard to see, and at every size the page reads as unframed.

A: no gutter

billing runs per build minute, invoiced monthly with a hard cap you set.

the text starts at the pixel edge of its page; on a phone the first letter rides the curve.

B: the layout owns the gutter

billing runs per build minute, invoiced monthly with a hard cap you set.

same sentence; the page's px-6 keeps the line off the edge at every width.

ruling
Gutters belong to the layout shell, not to each page's good intentions: set padding-inline once on the content shell and no text can reach the edge again.
<!-- the shell, once -->
<main class="mx-auto max-w-[1280px] px-6">
<p>billing runs per build minute, invoiced monthly...</p>
</main>

Pattern source: impeccable.style/slop. Read design for the rest of the design bank.

search pages

go to any page