Lesson 37: Text and Typography
On this page
- The
@font-facerule - Change the typeface
- Use italic and oblique fonts
- Make text bold
- Change the size of text
- Change the space between lines
- Change the space between characters
- Change the space between words
fontshorthand- Change the case of text
- Add underlines, overlines, and through-lines to text
- Add an indent to your text
- Deal with overflowing or hidden content
- Control white-space
- Control how words break
- Change text alignment
- Control how text wraps
- Change the direction of text
- Change the flow of text
- Change the orientation of text
- Add a shadow to text
- Variable fonts
- Pseudo-elements
::first-letterand::first-linepseudo-elements::selectionpseudo-elementfont-variant- Resources
Text is one of the core building blocks of the web.
When you make a website, you don’t have to style your text. HTML has some pretty reasonable default styling on its own.
Even so, text will likely make up most of your website. That makes it worth adding some styling to spruce it up. By changing a few basic properties, you can make the reading experience much better for your users.
In this lesson, we’ll start with the @font-face rule, which lets you bring custom fonts into your webpages.
This makes sure you get the exact typography you need, no matter which fonts a user has installed.
After that, we’ll cover the main CSS font properties, including font-family, font-style, font-weight, and font-size.
These basics set the stage for shaping text for both style and readability.
We’ll also touch on paragraph properties like text-indent and word-spacing.
We’ll finish with more advanced topics such as variable fonts and pseudo-elements, which give you even more control over your type.
There are practical examples and tips throughout to help the ideas stick.
The @font-face rule
The @font-face CSS at-rule is a key tool in web design.
It lets you pick and use custom fonts to display text.
The nice thing about @font-face is how flexible it is.
It lets you load fonts from a remote server, or from a font installed on the user’s device.
Syntax
@font-face {
font-family: "Trickster";
src:
local("Trickster"),
url("trickster-COLRv1.otf") format("opentype") tech(color-COLRv1),
url("trickster-outline.otf") format("opentype"),
url("trickster-outline.woff") format("woff")
}Descriptors
ascent-override- Customizes the ascent metric, which is the space above the baseline.
descent-override- Adjusts the descent metric, which is the space below the baseline.
font-display- Controls how the font shows while it is still downloading.
font-family- Names the font so you can use it in font-related properties.
font-stretch- Sets the allowed horizontal scaling, as a single value or a range.
font-style- Defines the font style, with angle ranges for oblique styles.
font-weight- Sets the font’s weight, or the range of weights available.
font-feature-settings- Turns on access to OpenType font features.
font-variation-settings- Gives you fine-tuned control over variable font settings.
line-gap-override- Overrides the font’s default line gap.
size-adjust- Applies a scaling factor to the font’s outline and metrics.
src- Defines the font source, whether local or remote.
This is required for the
@font-facerule. Combiningurl()andlocal()in thesrcis a common trick. It uses a local font if one is available, and falls back to a remote font file if not. Browsers prioritize resources by the order you list them, solocal()should usually come beforeurl(). unicode-range- Limits which characters this font is used for.
Description
@font-face frees designers from the limits of “web-safe” fonts by letting them use custom typography.
The local() function can search for a font on the user’s device.
That offers a smooth experience that doesn’t always need an internet connection.
[!NOTE] For compatibility tips and more details on older browsers, see the
srcdescriptor docs. You can also nest@font-faceinside CSS conditional group rules.
Font MIME types
| Format | MIME Type |
|---|---|
| TrueType | font/ttf |
| OpenType | font/otf |
| Web Open Font Format | font/woff |
| Web Open Font Format 2 | font/woff2 |
[!NOTE] Web fonts follow the same-origin policy. You can set them up for cross-origin use with HTTP access controls.
[!NOTE] You can’t declare
@font-faceinside a CSS selector block.
The difference between @font-face and font-family
In CSS, @font-face and font-family are often mixed up, but they do different jobs.
As we’ve discussed, @font-face is a rule that defines any custom fonts you want to use in your web application.
It tells the browser where to download the font.
It tells the browser how to display the font while it loads, using the font-display property.
It also tells the browser which subset of characters to download, using the unicode-range.
In contrast, font-family is a CSS property used inside a CSS rule.
It assigns a font, or a list of fonts, to an element.
The fonts listed under font-family can be web-safe fonts, system fonts, or custom fonts defined with @font-face.
To sum up, @font-face declares a font and gives it a name.
The font-family property then applies that declared font to HTML elements.
Here’s an example of using both.
@font-face {
font-family: "CustomFont";
src: url("customfont.woff2") format("woff2");
}
body {
font-family: "CustomFont", Arial, sans-serif;
}In this example, @font-face defines “CustomFont” and tells the browser where to find it.
The font-family property then applies it to the body element, with Arial as a fallback if “CustomFont” isn’t available.
Change the typeface
Use font-family to change the typeface of your text.
The font-family property takes a comma-separated list of strings.
Each one refers to a specific or generic font family.
Specific font families are quoted strings, such as “Helvetica”, “EB Garamond”, or “Times New Roman”.
Generic font families are keywords such as serif, sans-serif, and monospace.
You can find the full list of options on MDN.
The browser displays the first available typeface from the list you give it.
[!NOTE] When the browser picks which font to display from your
font-familylist, it doesn’t stop at the first font it can use. Instead, it chooses fonts one character at a time. If a character isn’t in the first font in the list, the browser moves on to the next font, until it reaches the end of the list.
When you use font-family, you should name at least one generic font family.
That way you’re covered if the user’s browser doesn’t have your preferred fonts.
The fallback generic font family should usually be similar to your preferred fonts.
For example, if you use font-family: "Helvetica", which is a sans-serif font, your fallback should be sans-serif to match.
Use italic and oblique fonts
Use font-style to set whether text should be italic or not.
font-style takes one of these keywords - normal, italic, and oblique.
[!NOTE] What’s the difference between
italicandoblique? In fonts that support it,font-style: italicis usually a cursive version of the regular typeface.font-style: obliqueshows a slanted version of the regular typeface.
Make text bold
Use font-weight to set the boldness of text.
This property takes keyword values like normal and bold, relative keyword values like lighter and bolder, and numeric values from 100 to 900.
The keywords normal and bold are the same as the numeric values 400 and 700.
The keywords lighter and bolder are worked out relative to the parent element.
See MDN’s Meaning of Relative Weights for a handy chart that shows how this value is found.
[!NOTE] Most fonts, especially the “web-safe” ones, only support the weights
400(normal) and700(bold). When you import fonts with@font-faceor@import, you can pick the specific weights you want to pull in. Still, non-variable fonts only support numeric values forfont-weightin the 100s, like100,200,300, and so on. If you want to usefont-weight: 321, for example, you’ll have to use a Variable Font.
Change the size of text
Use font-size to control the size of your text elements.
This property takes length values, percentages, and a handful of keyword values.
On top of length and percentage values, font-size takes some absolute keyword values.
These are xx-small, x-small, small, medium, large, x-large, and xx-large.
It also takes a couple of relative keyword values, smaller and larger.
The relative values are relative to the parent element’s font-size.
[!NOTE] What’s the difference between
emandrem? In CSS,emis thefont-sizeinherited from the element’s parent. For example,font-size: 2emis the same as the parent’sfont-sizetimes two.remis similar, but it is thefont-sizeinherited from the root element, such as<html>.
Change the space between lines
Use line-height to set the height of each line in an element.
This property takes a number, a length, a percentage, or the keyword normal.
It’s usually best to use a number instead of a length or percentage to avoid issues with inheritance.
Change the space between characters
Use letter-spacing to control the horizontal space between characters in your text.
This property takes length values such as em, px, and rem.
Note that the value you set increases the natural space between characters.
In the demo below, try selecting a single letter to see the size of its letterbox and how it changes with letter-spacing.
Change the space between words
Use word-spacing to grow or shrink the space between each word in your text.
This property takes length values such as em, px, and rem.
Note that the length you set is for extra space on top of the normal spacing.
This means word-spacing: 0 is the same as word-spacing: normal.
font shorthand
You can use the shorthand font property to set many font-related properties at once.
The properties you can set are font-family, font-size, font-stretch, font-style, font-variant, font-weight, and line-height.
Check out MDN’s font article for how to order these properties.
Change the case of text
Use text-transform to change the capitalization of your text without changing the underlying HTML.
This property takes the keyword values uppercase, lowercase, and capitalize.
Add underlines, overlines, and through-lines to text
Use text-decoration to add lines to your text.
Underlines are the most common, but you can also add lines above your text or right through it.
The text-decoration property is shorthand for the more specific properties below.
The text-decoration-line property takes the keywords underline, overline, and line-through.
You can also list more than one keyword for more than one line.
The text-decoration-color property sets the color of all the lines from text-decoration-line.
The text-decoration-style property takes the keywords solid, double, dotted, dashed, and wavy.
The text-decoration-thickness property takes any length value.
It sets the stroke width of all the lines from text-decoration-line.
The text-decoration property is a shorthand for all the properties above.
[!NOTE] Use
text-underline-positionto offset the underline of atext-decoration: underlineby the amount you set. This property doesn’t work foroverlineorline-through.
Add an indent to your text
Use text-indent to add an indent to your blocks of text.
This property takes either a length, like 10px or 2em, or a percentage of the containing block’s width.
Deal with overflowing or hidden content
Use text-overflow to set how hidden content is shown.
There are two options.
The clip value, which is the default, cuts the text off at the point where it overflows.
The ellipsis value shows an ellipsis (…) at the point where it overflows.
Control white-space
The white-space property sets how whitespace in an element is handled.
For more details, check out the white-space article on MDN.
white-space: pre can be handy for rendering ASCII art or carefully indented code blocks.
Control how words break
Use word-break to change how words break when they would overflow the line.
By default, the browser won’t split words.
Using the keyword value break-all for word-break tells the browser to break words at individual characters if it needs to.
Change text alignment
Use text-align to set the horizontal alignment of text in a block or table-cell element.
This property takes the keyword values left, right, start, end, center, justify, and match-parent.
The values left and right align the text to the left and right sides of the block.
Use start and end for the start and end of a line of text in the current writing mode.
So start maps to left in English, and to right in Arabic script, which is written right to left (RTL).
These are logical alignments.
Learn more in our logical properties module.
Use center to align the text to the center of the block.
The value justify lays out the text and changes word spacing on its own.
That way the text lines up with both the left and right edges of the block.
Control how text wraps
Use text-wrap to change how text inside an element wraps.
The keywords for this property are wrap, nowrap, balance, and stable.
The default value is wrap, which keeps overflow to a minimum by wrapping text across lines at normal spaces and word breaks.
You can use the nowrap keyword to do the opposite and stop the text from breaking across lines, which can cause overflow.
To get the same amount of text on each line, for example in headings or headlines, use the balance keyword.
To keep things fast, browsers only apply this value to elements with six lines of text or fewer.
The stable keyword works much like wrap, but it is meant for contenteditable text.
With text-wrap: stable set, the lines above the content you are editing won’t shift around while you type.
Sometimes long strings with no clear breaking point can overflow their containers.
To control how this kind of text breaks, use overflow-wrap.
The keywords for this property are normal, break-word, and anywhere.
The default setting is normal, which won’t break text onto the next line unless it has spaces or natural break points.
The anywhere and break-word values add break points anywhere inside the string to prevent overflow.
The keywords differ in how they react to an intrinsic or explicit min-content size.
The anywhere keyword allows all of the soft breaking opportunities it can.
The break-word value doesn’t, and would make the text as long as the longest word.
Change the direction of text
Use direction to set the direction of your text, either ltr (left to right, the default) or rtl (right to left).
Some languages like Arabic, Hebrew, or Persian are written right to left, so you should use direction: rtl.
For English and all other left-to-right languages, use direction: ltr.
[!CAUTION] In general, you should favor the HTML attribute
diroverdirection. Check out this StackOverflow discussion for more details.
Change the flow of text
Use writing-mode to change the way text flows and is arranged.
The default is horizontal-tb.
You can also set writing-mode to vertical-lr or vertical-rl for text that you want to flow vertically.
Change the orientation of text
Use text-orientation to set the orientation of characters in your text.
The valid values for this property are mixed and upright.
This property only matters when writing-mode is set to something other than horizontal-tb.
Add a shadow to text
Use text-shadow to add a shadow to your text.
This property expects three lengths (x-offset, y-offset, and blur-radius) and a color.
Check out the text-shadow section of our module on Shadows to learn more.
Variable fonts
Usually, “normal” fonts need you to import different files for different versions of the typeface, like bold, italic, or condensed. Variable fonts are fonts that can hold many different variants of a typeface in one file. For example, Roboto Flex offers random combinations of width and weight.
Check out our article on Variable Fonts for more details.
Pseudo-elements
[!IMPORTANT] A pseudo-element is a part of an element that you can target with CSS keywords without adding more HTML. Check out our module on pseudo-elements for a deep dive into this subject.
::first-letter and ::first-line pseudo-elements
The ::first-letter and ::first-line pseudo-elements target a text element’s first letter and first line.
::selection pseudo-element
Use the ::selection pseudo-element to change how user-selected text looks.
When you use this pseudo-element, only certain CSS properties work.
These are color, background-color, text-decoration, text-shadow, stroke-color, fill-color, and stroke-width.
font-variant
The font-variant property is a shorthand for a number of CSS properties.
These let you pick font variants like small-caps and slashed-zero.
The CSS properties this shorthand includes are font-variant-alternates, font-variant-caps, font-variant-east-asian, font-variant-ligatures, and font-variant-numeric.
Check out the links on each property for more details about how to use it.
Resources
Here are some resources to learn more about styling text on the web.
- Font best practices covers importing fonts, rendering fonts, and other best practices for using fonts on the web.
- MDN Fundamental text and font styling.
Adapted from Learn CSS © Google and contributors, licensed under CC BY 4.0 (prose) and Apache 2.0 (code samples).