Modern reset.css
At the start of your project, you should always use a reset.css
to make sure your website looks the same in every browser. It removes default styles and gives you a clean base to work from.
reset.css
first. This ensures that your own styles don’t get overwritten or affected by inconsistent default browser styles.info
If you use Tailwind CSS, you have a built-in reset.css
called 'Preflight'.
Josh Comeau's reset.css
When it comes to reset.css
, my personal favorite is Josh Comeau's reset.css. It’s modern, thoughtfully crafted, and incorporates sensible best practices that align well with today’s web development needs.
box-sizing: border-box
-webkit-font-smoothing: antialiased
Eric Meyer's reset.css
On the other hand, the widely known Eric Meyer's reset.css is more old-school and, quite frankly, a bit too aggressive for most modern projects.
box-sizing: border-box
Code examples
/* 1. Use a more-intuitive box-sizing model */
*, *::before, *::after {
box-sizing: border-box;
}
/* 2. Remove default margin */
* {
margin: 0;
}
/* 3. Enable keyword animations */
@media (prefers-reduced-motion: no-preference) {
html {
interpolate-size: allow-keywords;
}
}
body {
/* 4. Add accessible line-height */
line-height: 1.5;
/* 5. Improve text rendering */
-webkit-font-smoothing: antialiased;
}
/* 6. Improve media defaults */
img, picture, video, canvas, svg {
display: block;
max-width: 100%;
}
/* 7. Inherit fonts for form controls */
input, button, textarea, select {
font: inherit;
}
/* 8. Avoid text overflows */
p, h1, h2, h3, h4, h5, h6 {
overflow-wrap: break-word;
}
/* 9. Improve line wrapping */
p {
text-wrap: pretty;
}
h1, h2, h3, h4, h5, h6 {
text-wrap: balance;
}
/*
10. Create a root stacking context
*/
#root, #__next {
isolation: isolate;
}
Fixing inconsistent font sizes
Without a systematic approach to font sizing, your typography becomes inconsistent and chaotic. You'll find yourself randomly picking sizes—making H2
headings 22px
, then 24px
, then 20px
—creating visual discord that feels unprofessional and hard to scan.
Typescales
A typescale solves this by creating consistent relationships between all your text elements.
Start with your base font size: 16px
or 18px
.
From this foundation, use mathematical ratios to generate harmonious size typography. Popular typescale ratios include:
- 1.125 (Major Second) - subtle, conservative
- 1.25 (Major Third) - balanced, versatile
- 1.414 (Augmented Fourth) - dynamic, bold
How does this work?
You start with a base font (like 16px), then multiply by the ratio to get each larger size, or divide by the ratio to get smaller sizes.
info
Tools like typescale.com can generate your complete typescale automatically. While also giving a preview.
Consistent Vertical Spacing
Vertical spacing is the art of controlling the space above and below your content to improve readability and create a professional design. It involves two key components:
line-height
: The space between lines within a paragraph (also known as "leading" by designers).margin
: The space between distinct elements like paragraphs, headings, and images.
Why Vertical Spacing Matters
When spacing is handled poorly, the reading experience suffers.
- Too little space makes text feel cramped and overwhelming, making it difficult for the reader to follow along.
- Too much space causes content to feel disconnected and fragmented, breaking the flow between related ideas. Well-executed vertical spacing guides the reader’s eye, makes content easier to scan, and gives your entire page a clean, organized feel.
line-height
Guidelines
The most important rule for line-height
is: the smaller the font size, the more generous its line-height needs to be.
Line-height is typically expressed as a unitless multiplier of the font size itself (e.g., a line-height of 1.5
on 16px
text results in a 24px
total line height).
Here are recommended starting points:
- Body Text:
1.4
–1.6
- Large Headings: (H1, H2):
1.0
–1.2
- Smaller Headings: (H3–H6):
1.2
–1.4
These are flexible guidelines, not rigid rules. Always trust your eye and adjust these values to best suit your specific typeface and design.
Vertical Margin Guidelines
warning
This following advice is only suitable for content-heavy typography like blog posts.
info
If you want to see a sample of those rules applied: https://play.tailwindcss.com/uAQvdQ1M5O?file=css
Here are our guiding principles for element spacing. Feel free to adapt them, as they are meant to demonstrate a consistent approach.
.container {
max-width: 100%;
width: 60ch;
margin: 0 auto;
}
h1 {
font-size: 4rem;
line-height: 1;
}
h2 {
font-size: 2rem;
line-height: 1.2;
}
h3 {
font-size: 1.2rem;
}
p {
line-height: 1.7;
}
img {
border-radius: .55em;
}
article {
padding-bottom: 5em;
color: rgb(34, 38, 70);
}
/* ───────────────────────────────
1. Design tokens
─────────────────────────────── */
:root {
/* base unit */
--space-base: 1.5rem;
/* semantic scale
(edit the factors only here) */
--space-xxs: calc(var(--space-base) * 0.25); /* 0.375 rem */
--space-xs: calc(var(--space-base) * 0.5); /* 0.75 rem */
--space-sm: calc(var(--space-base) * 0.75); /* 1.125 rem */
--space-md: calc(var(--space-base) * 1); /* 1.5 rem */
--space-lg: calc(var(--space-base) * 1.5); /* 2.25 rem */
--space-xl: calc(var(--space-base) * 2); /* 3 rem */
--space-2xl: calc(var(--space-base) * 2.5); /* 3.75 rem */
--space-3xl: calc(var(--space-base) * 3); /* 4.5 rem */
--space-4xl: calc(var(--space-base) * 4); /* 6 rem */
--space-5xl: calc(var(--space-base) * 6); /* 9 rem */
/* (optional) global font */
font-family: "Inter", sans-serif;
}
/* ───────────────────────────────
2. Vertical rhythm for .prose
─────────────────────────────── */
/* 2-a Base gap */
.prose > * + * {
margin-top: var(--space-md); /* 1 × base → “md” */
}
/* 2-b Headings need extra space */
.prose > :is(h1, h2, h3, h4) {
margin-top: var(--space-2xl); /* previously × 2.5 */
}
/* 2-c Heading after heading */
.prose > :is(h1, h2, h3, h4) + :is(h1, h2, h3, h4) {
margin-top: var(--space-md);
}
/* 2-d Tighter list items */
.prose li + li {
margin-top: var(--space-xs); /* 0.3 × base ≈ “xs” */
}
/* 2-e More breathing room for top-level images / figures */
.prose > img,
.prose > figure {
margin-block: var(--space-xl); /* top & bottom */
}
How does this work?
A single :root
rule defines reusable spacing variables.
:root {
/* the “atom” all other spaces are built from */
--space-base: 1.5rem;
/* multiply the atom to get semantic sizes */
--space-sm : calc(var(--space-base)*0.75); /* 1.125rem */
--space-2xl: calc(var(--space-base)*2.5); /* 3.75rem */
/* …etc… */
}
Edit only --space-base
(e.g. 2rem
) and the whole vertical rhythm scales automatically.
Every direct-child that follows another direct-child in .prose
gets a medium top margin.
HTML:
/* 2-a Base gap */
.prose > * + * {
margin-top: var(--space-md); /* 1 × base → “md” */
}
Result: a predictable, book-like rhythm for normal blocks.
Headings (h1
–h4
) need to stand out, so they receive a larger gap.
.prose > :is(h1,h2,h3,h4) {
margin-top: var(--space-2xl); /* 3.75 rem */
}
Two consecutive headings shouldn’t be too far apart.
.prose > :is(h1,h2,h3,h4) + :is(h1,h2,h3,h4) {
margin-top: var(--space-md); /* back to 1.5 rem */
}
info
For consistency, make sure that this is the same value as your base gap
.
Only siblings inside the same list are tightened.
.prose li + li {
margin-top: var(--space-xs); /* 0.75 rem */
}
Images or figures placed directly in .prose get generous vertical space.
.prose > img,
.prose > figure {
margin-block: var(--space-xl); /* 3 rem above & below */
}
info
The extra added margins won't be added towards the existing margins, but be replaced because of margin collapse where the bigger margin takes priority.
Why the >
child combinator matters
The selector .prose > *
means “only first-level children of .prose
”.
<Callout>
that internally contains its own elements. Because of >
, the outer rhythm rules don’t reach inside:export default function Callout({children}) {
return (
<aside className="callout">
<h3>Heads-up</h3> {/* NOT affected by .prose > h3 rule */}
<p>{children}</p> {/* NOT given extra top margin */}
</aside>
);
}
You can style <Callout>
with its own spacing tokens without fighting the global prose rules.
Conclusion
Good typography isn't about rigid rules—it's about creating systems that work consistently across your project. By establishing a CSS reset, implementing a mathematical typescale, and applying thoughtful vertical spacing, you've built a strong foundation that eliminates guesswork and creates visual harmony.