A quick guide to choosing the right fonts, sizing them for readability, and pairing them like a pro.
Every font falls into a category. Knowing the difference helps you make smart choices.
In CSS, the font-family property tells the browser which typeface to use. Fonts are grouped into families based on their visual style. The three you'll use most on the web are serif, sans-serif, and monospace.
/* CSS font-family with fallback stack */ body { font-family: 'Inter', 'Helvetica Neue', Arial, sans-serif; } h1, h2, h3 { font-family: 'Playfair Display', Georgia, serif; } code, pre { font-family: 'Source Code Pro', 'Courier New', monospace; }
Size matters — too small and users squint, too large and it feels like a children's book.
The recommended base font size for body text on the web is 16px (the browser default). Many modern sites use 17–20px for improved readability. Headings should follow a clear size hierarchy so readers can scan the page easily.
This text is set at 11px with tight line-height. It's difficult to read on screens, especially on mobile devices. Users will leave your site before reading this.
This text is set at 17px with comfortable line-height (1.7). It's easy to read on any device and keeps users engaged with your content.
rem units: They scale with the user's browser settings, improving accessibility./* Recommended base sizing */ html { font-size: 100%; } /* = 16px default */ body { font-size: 1.0625rem; /* 17px */ line-height: 1.7; max-width: 680px; /* keeps line length readable */ } h1 { font-size: 2.5rem; } /* 40px */ h2 { font-size: 1.75rem; } /* 28px */ h3 { font-size: 1.25rem; } /* 20px */
These are tried-and-true choices used on millions of websites.
All of these are available free on Google Fonts. They load fast, render well on every device, and cover a wide range of styles.
These fonts stand out visually while still being easy to read on screens.
Not every project calls for a plain, neutral font. Sometimes you need something with character — a font that gives your site a unique feel without sacrificing readability. These fonts strike that balance beautifully, and they're all free on Google Fonts.
The golden rule: contrast without conflict. Pair a heading font with a body font that complements it.
A great website typically uses two fonts — one for headings and one for body text. The key is to create visual contrast (e.g., serif + sans-serif) while keeping the overall feel harmonious. Here are proven pairings:
A step-by-step guide to loading and applying custom fonts from Google Fonts.
Google Fonts is a free library of 1,700+ font families. It's the easiest way to add professional-quality fonts to any website. There are two main methods to load them — here's how both work:
Visit fonts.google.com and browse or search for a font you like (e.g., "Poppins").
Click on the font, then click "Get Font" → "Get embed code". Select the weights you need (Regular 400, Medium 500, Bold 700, etc.). Only pick what you'll actually use — more weights = slower load time.
Google gives you a <link> tag. Copy it and paste it into the <head> section of your HTML file, before your CSS stylesheet link.
<!-- Paste this in your <head> BEFORE your own CSS --> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap" rel="stylesheet">
Now use the font-family property in your CSS to apply it. Always include a fallback.
body { font-family: 'Poppins', sans-serif; } /* Want two fonts? Load both in the same <link> tag: */ /* ...css2?family=Poppins:wght@400;600&family=Playfair+Display:wght@700 */ h1, h2, h3 { font-family: 'Playfair Display', serif; } p, li, a { font-family: 'Poppins', sans-serif; }
On the Google Fonts embed page, switch to the "@import" tab instead of the link tab. Copy the code.
Place the @import statement at the very beginning of your CSS file — before any other rules.
/* At the VERY TOP of your style.css file */ @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap'); /* Now use it normally */ body { font-family: 'Poppins', sans-serif; }
The <link> method is faster because the browser starts loading the font immediately. @import waits until the CSS file itself loads. Use @import if you only have access to the CSS file (e.g., in CodePen or a CMS).
On Google Fonts, click "Get Font" → "Download all". You'll get a .zip with .ttf files. For web use, convert them to .woff2 format using a free tool like CloudConvert.
Create a /fonts folder in your project and place the .woff2 files there.
your-project/
├── index.html
├── css/
│ └── style.css
└── fonts/
├── Poppins-Regular.woff2
├── Poppins-SemiBold.woff2
└── Poppins-Bold.woff2
Tell the browser where to find the font files using @font-face rules.
@font-face { font-family: 'Poppins'; src: url('../fonts/Poppins-Regular.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; } @font-face { font-family: 'Poppins'; src: url('../fonts/Poppins-Bold.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; } body { font-family: 'Poppins', sans-serif; }
Self-hosting is best when you need fonts to work offline, want full control over caching, or have strict privacy requirements (no third-party requests). For most student projects, the <link> method is easier and works great.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>My Website</title> <!-- Step 1: Load fonts from Google --> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Poppins:wght@400;600&display=swap" rel="stylesheet"> <!-- Step 2: Your CSS (can be external or inline) --> <style> body { font-family: 'Poppins', sans-serif; font-size: 17px; line-height: 1.7; color: #333; max-width: 700px; margin: 0 auto; padding: 40px 20px; } h1, h2, h3 { font-family: 'Playfair Display', serif; } </style> </head> <body> <h1>Welcome to My Site</h1> <p>This text uses Poppins for the body and Playfair Display for the heading.</p> </body> </html>
display=swap in the Google Fonts URL — this shows a fallback font while the custom font loads, preventing invisible text.preconnect links — they speed up the font download by telling the browser to connect to Google's servers early.sans-serif or serif — in case the font fails to load.Experiment with different fonts, sizes, and weights to see how they look in real time.
Good typography is invisible — readers notice the content, not the font. Bad typography makes people leave. Your job is to pick fonts that get out of the way and let your content shine.
Pin this to your wall while you're learning!
rem units so text scales accessibly.font-family with a generic like sans-serif or serif.