CSS Typography
By Flavio
Learn how to style text with CSS typography properties like text-transform, text-decoration, text-align, line-height, letter-spacing, and text-shadow.
In this post I’ll talk about styling text with CSS, using the following properties:
text-transformtext-decorationtext-alignvertical-alignline-heighttext-indenttext-align-lastword-spacingletter-spacingtext-shadowwhite-spacetab-sizewriting-modehyphenstext-orientationdirectionline-breakword-breakoverflow-wraptext-wrap
text-transform
This property can transform the case of an element.
There are 4 valid values:
capitalizeto uppercase the first letter of each worduppercaseto uppercase all the textlowercaseto lowercase all the textnoneto disable transforming the text, used to avoid inheriting the property
Example:
p {
text-transform: uppercase;
}
text-decoration
This property is used to add decorations to the text, including
underlineoverlineline-throughblink(deprecated; browsers ignore it and do not blink the text)none
Example:
p {
text-decoration: underline;
}
You can also set the style of the decoration, and the color.
Example:
p {
text-decoration: underline dashed yellow;
}
Valid style values are solid, double, dotted, dashed, wavy.
You can do all in one line, or use the specific properties:
text-decoration-linetext-decoration-colortext-decoration-styletext-decoration-thicknessfor the line thickness (Chrome 89, Firefox 70, Safari 12.1)text-underline-offsetfor the gap between the text and an underline (Chrome 87, Firefox 70, Safari 12.1)
Example:
p {
text-decoration-line: underline;
text-decoration-color: yellow;
text-decoration-style: dashed;
}
text-align
By default text align has the start value, meaning the text starts at the “start”, origin 0, 0 of the box that contains it. This means top left in left-to-right languages, and top right in right-to-left languages.
Possible values are start, end, left, right, center, justify (nice to have a consistent spacing at the line ends):
p {
text-align: right;
}
vertical-align
Determines how inline elements are vertically aligned.
We have several values for this property. First we can assign a length or percentage value. Those are used to align the text in a position higher or lower (using negative values) than the baseline of the parent element.
Then we have the keywords:
baseline(the default), aligns the baseline to the baseline of the parent elementsubmakes an element subscripted, simulating thesubHTML element resultsupermakes an element superscripted, simulating thesupHTML element resulttopalign the top of the element to the top of the linetext-topalign the top of the element to the top of the parent element fontmiddlealign the middle of the element to the middle of the line of the parentbottomalign the bottom of the element to the bottom of the linetext-bottomalign the bottom of the element to the bottom of the parent element font
line-height
This allows you to change the height of a line. Each line of text has a certain font height, but then there is additional spacing vertically between the lines. That’s the line height:
p {
line-height: 0.9rem;
}
text-indent
Indent the first line of a paragraph by a set length, or a percentage of the paragraph width:
p {
text-indent: -10px;
}
text-align-last
By default the last line of a paragraph is aligned following the text-align value. Use this property to change that behavior:
p {
text-align-last: right;
}
word-spacing
Modifies the spacing between each word.
You can use the normal keyword, to reset inherited values, or use a length value:
p {
word-spacing: 2px;
}
span {
word-spacing: -0.2em;
}
letter-spacing
Modifies the spacing between each letter.
You can use the normal keyword, to reset inherited values, or use a length value:
p {
letter-spacing: 0.2px;
}
span {
letter-spacing: -0.2em;
}
text-shadow
Apply a shadow to the text. By default the text has no shadow.
This property accepts an optional color, and a set of values that set
- the X offset of the shadow from the text
- the Y offset of the shadow from the text
- the blur radius
If the color is not specified, the shadow will use the text color.
Examples:
p {
text-shadow: 0.2px 2px;
}
span {
text-shadow: yellow 0.2px 2px 3px;
}
white-space
Sets how CSS handles the white space, new lines and tabs inside an element.
white-space is now a shorthand for white-space-collapse and text-wrap-mode (CSS Text 4; Chrome 114/130, Firefox 124, Safari 17.4). The old single-keyword values still work.
Valid values that collapse white space are:
normalcollapses white space. Adds new lines when necessary as the text reaches the container endnowrapcollapses white space. Does not add a new line when the text reaches the end of the container, and suppresses any line break added to the textpre-linecollapses white space. Adds new lines when necessary as the text reaches the container end
Valid values that preserve white space are:
prepreserves white space. Does not add a new line when the text reaches the end of the container, but preserves line break added to the textpre-wrappreserves white space. Adds new lines when necessary as the text reaches the container endbreak-spacesis likepre-wrap, but trailing spaces can wrap onto a new line (Chrome 76, Firefox 69, Safari 13.1)
Near this sits text-wrap. text-wrap: balance evens out line lengths in headings (Chrome 114, Firefox 121, Safari 17.5, Baseline 2024). text-wrap: pretty avoids orphans (Chrome 117, Safari 26; Firefox does not support it yet).
I also have a CSS fonts post if you want the font side of this.
tab-size
Sets the width of the tab character. By default it’s 8, and you can set an integer value that sets the character spaces it takes, or a length value:
p {
tab-size: 2;
}
span {
tab-size: 4px;
}
writing-mode
Defines whether lines of text are laid out horizontally or vertically, and the direction in which blocks progress.
The values you can use are
horizontal-tb(default)vertical-rlcontent is laid out vertically. New lines are put on the left of the previousvertical-lrcontent is laid out vertically. New lines are put on the right of the previous
hyphens
Determines if hyphens should be automatically added when going to a new line.
Valid values are
none(default)manualonly add an hyphen when there is already a visible hyphen or a hidden hyphen (a special character)autoadd hyphens when determined the text can have a hyphen. This only works when the content language is set, for example<html lang="en">, because the browser needs that language’s hyphenation dictionary.
text-orientation
When writing-mode is in a vertical mode, determines the orientation of the text.
Valid values are
mixedis the default. It rotates horizontal-script characters 90 degrees and keeps vertical-script ones uprightuprightmakes all text be vertically orientedsidewayslays characters out as they would be horizontally, with the whole line rotated 90 degrees clockwise
direction
Sets the direction of the text. Valid values are ltr and rtl:
p {
direction: rtl;
}
word-break
This property specifies how to break lines within words.
normal(default) means the text is only broken between words, not inside a wordbreak-allthe browser can break a word (but no hyphens are added)keep-allsuppress soft wrapping. Mostly used for CJK (Chinese/Japanese/Korean) text.
Speaking of CJK text, the property line-break is used to determine how text lines break. I’m not an expert with those languages, so I will avoid covering it.
overflow-wrap
If a word is too long to fit a line, it can overflow outside of the container.
This property is also known as
word-wrap, although that is non-standard (but still works as an alias)
This is the default behavior (overflow-wrap: normal;).
We can use:
p {
overflow-wrap: break-word;
}
to break a long word so it does not overflow. overflow-wrap: anywhere (Chrome 80, Firefox 65, Safari 15.4) does the same break, but those break opportunities also count when the browser calculates the min-content size. That can shrink a box, for example a flex item or a table cell. break-word does not. No hyphens are added, in any case.
p {
overflow-wrap: anywhere;
}
This property is very similar to word-break. We might want to choose this one on western languages, while word-break has special treatment for non-western languages. word-break: break-word is deprecated. Use overflow-wrap: anywhere instead.
See also CSS inheritance for how text properties pass down to children.
Want me to talk about your product? You can sponsor this site.