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.
<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
the first card sits on the edge; the last one is cut with no hint of more.
B: gutter inside, peek outside
the scroller pads itself to the gutter; a full card plus a sliver of the next stays visible.
<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.
<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.
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.
same content; the text takes two thirds, the fact takes one, and nothing floats in a hole.
<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.
<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.
<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.
<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
each setting is exactly as far from its group title as from the next group.
B: groups read as groups
same content; the tight gap binds each pair to its title, the wide gap separates the groups.
<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
three borders and three fills between the reader and one setting.
B: one surface, rules inside
workspace · security
same content; one fill step, and inner structure is a divider plus indentation.
<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.
<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
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
same columns; the table scrolls inside its own panel and the heading never moves.
<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.
import { createPortal } from 'react-dom'function Menu({ trigger }: { trigger: DOMRect }) {return createPortal(<divclassName="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.
<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.
<!-- 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.