CSS Text and Fonts: font-family, Size, Weight, Line Height
Style text with font-family, font-size, font-weight, line-height and web fonts, and see exactly which class or id styles which HTML element.
What you will learn
Most of the web is text, so text styling is where CSS pays off first. In this lesson you will learn the properties that control the font (font-family, font-size, font-weight, font-style), the spacing between lines (line-height), a few handy text properties, and how to use web fonts such as Google Fonts. Just as important, you will see exactly which class or id is attached to which HTML element, so you always know what a selector is pointing at.
The HTML we will style
Every example in this lesson runs against one small blog post. Read the HTML first, and notice the class and id attributes. Those are the “handles” that our CSS will grab.
<article class="post">
<p class="category">CSS Basics</p>
<h1 id="post-title">Why Typography Matters</h1>
<p class="byline">By Aisha Khan · 5 min read</p>
<p class="lead">Good text styling makes a page easier to read before anyone reads a single word.</p>
<h2 class="section-title">Pick readable fonts</h2>
<p>Body text should feel calm. Choose a clean font, a comfortable size and enough space between the lines.</p>
<p>Use <span class="highlight">one or two fonts</span> at most. Too many fonts make a page look messy.</p>
<blockquote class="quote">Readable text is the kindest thing you can give a visitor.</blockquote>
<p class="note">Tip: style the body text first, then the headings.</p>
</article>
Here is the map from selector to element:
| Selector | Matches this element | Its job |
|---|---|---|
.post |
the <article> |
wrapper around everything |
.category |
the first <p> |
small label above the title |
#post-title |
the <h1> |
the main title |
.byline |
the <p> with the author name |
small grey line |
.lead |
the first big <p> |
introduction paragraph |
.section-title |
the <h2> |
section heading |
.highlight |
the <span> inside a paragraph |
important words |
.quote |
the <blockquote> |
a pull quote |
.note |
the last <p> |
small tip at the end |
Two plain <p> elements have no class at all. You can still style them with the type selector p, or by targeting .post p.
font-family: choosing the typeface
font-family sets the typeface of the text.
/* Styles the <article class="post"> and, through it, everything inside */
.post {
font-family: Arial, Helvetica, sans-serif;
}
Notice that there is a list of fonts. The browser tries them left to right and uses the first one that is installed on the visitor’s device. This list is called a font stack. The last entry should always be a generic family, a safety net that every device understands:
| Generic family | Look | Typical use |
|---|---|---|
serif |
letters with small strokes at the ends (Times, Georgia) | books, articles, elegant headings |
sans-serif |
clean, no strokes (Arial, Helvetica) | websites, apps, body text |
monospace |
every letter the same width (Courier, Consolas) | code |
system-ui |
the visitor’s own operating system font | fast, native-looking interfaces |
cursive and fantasy |
decorative | rarely a good idea |
A few more rules:
- Font names with spaces should be in quotes:
"Times New Roman","Segoe UI". - Generic families are never quoted:
serif, not"serif". - Separate names with commas.
Inheritance: why we style .post, not every element
Here is a very useful idea. Text properties such as font-family, font-size, color and line-height are inherited. That means when you set them on a parent, all its children (the paragraphs, headings and spans inside) automatically use the same value, unless they have their own rule.
That is why setting font-family on the .post wrapper is enough to change the font of the whole article. You can then override it for one element:
.post {
font-family: Arial, Helvetica, sans-serif;
}
/* Only the <h1 id="post-title"> gets a different font */
#post-title {
font-family: Georgia, "Times New Roman", serif;
}
In real projects you usually set the base font once on body, and every element inherits it.
font-size: how big is the text?
/* the <p class="category"> */
.category {
font-size: 14px;
}
/* the <h1 id="post-title"> */
#post-title {
font-size: 40px;
}
/* the <p class="lead"> */
.lead {
font-size: 20px;
}
/* the <h2 class="section-title"> */
.section-title {
font-size: 28px;
}
For now we use px (pixels), which is easy to picture. The CSS Units lesson explains rem and em, which are usually a better choice. Some useful facts:
- Browsers make ordinary text 16px by default.
- Body text between 16px and 20px is comfortable to read. Avoid going below 14px for anything important.
- Headings are bigger because the browser gives them a larger default size, not because of their level number. You can change them at will.
font-weight: thin or bold?
/* the <span class="highlight"> inside the paragraph */
.highlight {
font-weight: bold;
}
/* the <p class="category"> */
.category {
font-weight: 700;
}
You can use the keywords normal and bold, or numbers from 100 to 900 in steps of 100:
400is the same asnormal.700is the same asbold.- Other numbers (
300light,600semi-bold,800extra-bold) only look different if the font actually includes that weight. Many fonts have only 400 and 700, so600may look exactly like700.
Headings are already bold by default. Write font-weight: normal if you want a lighter heading.
font-style: italic text
/* the <blockquote class="quote"> */
.quote {
font-style: italic;
}
The values are normal and italic. Use font-style: normal to remove italics from something the browser italicises by default.
line-height: the space between lines
line-height sets the height of each line of text. It is the single easiest way to make paragraphs look more professional.
.post {
line-height: 1.6;
}
Write it as a plain number with no unit. 1.6 means “1.6 times the font size” for every element, so a 40px heading gets a 64px line and a 14px note gets a 22px line. Guidelines:
- Body text: between
1.5and1.7. - Big headings: tighter, around
1.1to1.3, because large text with loose lines looks disconnected. - Below
1.2text becomes cramped and hard to read.
#post-title {
font-size: 40px;
line-height: 1.2;
}
Why no unit? With
line-height: 1.6emor24px, the value is calculated once on the parent and then handed down to children as a fixed length. A child with bigger text then gets lines that are too small and overlap. The unitless number is recalculated for every element, so it always fits.
Other useful text properties
A few properties you will use almost as often:
/* the <p class="category"> */
.category {
text-transform: uppercase;
letter-spacing: 2px;
}
/* the <blockquote class="quote"> */
.quote {
text-align: center;
}
/* the <span class="highlight"> */
.highlight {
text-decoration: underline;
}
/* the <p class="byline"> */
.byline {
color: gray;
}
text-alignaligns text inside its box:left,right,centerorjustify.text-transformchanges capital letters without touching the HTML:uppercase,lowercaseorcapitalize.letter-spacingadds space between letters. A little on small uppercase text looks polished.text-decorationaddsunderline,line-throughoroverline, or removes a line withnone(browsers underline links by default).
Web fonts: fonts that are not on the visitor’s device
Fonts like Arial only work because they are already installed. A web font is downloaded together with your page, so you can use any typeface and it looks the same everywhere. There are two ways to add one.
Option 1: Google Fonts (easiest)
- Go to Google Fonts, pick a font (for example Poppins) and choose the weights you need, such as 400 and 700.
- Copy the
<link>tags it gives you into the<head>of your HTML, before your own stylesheet:
<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;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
- Use the font name in your CSS, with a fallback in case the font fails to load:
.post {
font-family: "Poppins", Arial, sans-serif;
}
In the MyCodeNest editor: the preview may block requests to outside websites, so a Google Font might not appear there. Test web fonts in your own project on your computer.
Option 2: your own font files
If you have a font file (.woff2 is the best format), declare it with @font-face and then use it like any other font:
@font-face {
font-family: "MyFont";
src: url("fonts/myfont.woff2") format("woff2");
font-weight: 400;
font-display: swap;
}
.post {
font-family: "MyFont", Arial, sans-serif;
}
font-display: swap tells the browser to show the fallback font immediately and switch when the web font arrives, so text is never invisible while loading.
Web font good habits
- Use at most two font families on a site, and only the weights you really use. Each extra file makes the page slower.
- Always list a fallback font stack ending with a generic family.
- Make sure the font is readable at small sizes. Fancy fonts belong in headings, not body text.
Putting it together
Here is the complete stylesheet for the blog post. Compare each rule with the map table above:
/* <article class="post">: base text style, inherited by all children */
.post {
font-family: Arial, Helvetica, sans-serif;
line-height: 1.6;
color: #222;
}
/* <p class="category"> */
.category {
font-size: 14px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 2px;
color: royalblue;
}
/* <h1 id="post-title"> */
#post-title {
font-family: Georgia, "Times New Roman", serif;
font-size: 40px;
line-height: 1.2;
}
/* <p class="byline"> */
.byline {
font-size: 15px;
color: gray;
}
/* <p class="lead"> */
.lead {
font-size: 20px;
}
/* <h2 class="section-title"> */
.section-title {
font-size: 28px;
}
/* <span class="highlight"> */
.highlight {
font-weight: 700;
text-decoration: underline;
}
/* <blockquote class="quote"> */
.quote {
font-size: 22px;
font-style: italic;
text-align: center;
}
/* <p class="note"> */
.note {
font-size: 14px;
color: dimgray;
}
Common mistakes
- Forgetting the fallback fonts. If the first font is missing, the browser falls back to its default, which is usually a serif font. End every stack with
serif,sans-seriformonospace. - Quoting generic families (
"sans-serif") or forgetting the quotes around names with spaces. - Using
line-heightwith a unit such as24pxon a parent, which gives the wrong spacing to bigger children. - Writing
font-size: 20with no unit, ortext-color/font-colorinstead ofcolor. - Expecting
font-weight: 600to look different when the font has only 400 and 700. - Loading too many fonts and weights, which slows the page down.
- Setting the font on every element instead of once on a parent and letting it inherit.
- Low contrast, for example light gray text on white.
Practice
- Click Practice in Editor. Change the article font to
Verdana, Geneva, sans-serif, then change the heading font to a monospace stack such as"Courier New", Courier, monospace. - Add rules for
.category,.bylineand.leadso that the label is small, bold, uppercase and blue, the byline is small and gray, and the lead paragraph is 20px. - Change
line-heighton.postto1, then2, then1.6. Which is the most comfortable to read? - Make the
.quoteitalic and centred, and give the.highlightspan a bold weight. - Style the two plain paragraphs without adding any class, using the selector
.post p. Which other paragraphs does this selector change? (Hint: it matches every<p>inside.post, including the ones that also have a class.) - Add a Google Font of your choice to a page on your computer, and use it for the heading only, with a fallback.
Recap
font-familytakes a font stack: your first choice, backups, then a generic family (serif,sans-serif,monospace).- Text properties like
font-family,colorandline-heightare inherited, so set them once on a parent. font-size,font-weight(400normal,700bold) andfont-stylechange the look of the letters.- Use a unitless
line-heightof about1.5to1.7for body text. text-align,text-transform,letter-spacingandtext-decorationhandle the rest of everyday text styling.- Web fonts come from Google Fonts or
@font-face. Use few families and weights, and always add a fallback. - Next you will learn the different units that CSS uses for sizes.