CSS Properties to Control Web Typography

Maria Antonietta Perna
Share

Web typography has the advantage of drawing on the wealth of knowledge belonging to the centuries-old tradition of print typography. By the same token, that tradition carries with it standards of best practices and excellence that web typography is called on to live up to.

However, the web as a medium of communication comes with its own peculiarities. So much so that we’re led to think that a seamless move from print to web typography is a tough call. In his book On Web Typography, p.110, Jason Santa Maria explains:

Printed books are a static format. From the designer’s initial layout of the book to its trip to the press bed, the warehouse, the bookshelf, and your hands, the output of that book doesn’t change. It’s delivered exactly as the designer conceived it.

When it comes to the web, the very same site can be experienced very differently according to a number of factors, e.g., various kinds of devices, screen resolutions, personalized browser settings, etc. Some of these factors, as Jason further explains …

… may give us the impression that the type is too small, others may cause us to miss something important just off screen, and still others may make it nearly impossible to view the web page at all.

That said, it’s also true that “The web is the best place for text.”, as Tim Brown claims in his talk on Universal Typography. Text on the Internet can be “searched, copied, translated, linked to other documents, it can be printed, it’s convenient, it’s accessible”.

The flexibility of the web doesn’t mean relinquishing control. On the contrary, as web designers, we’re still expected to make informed choices about anything we put into our work, and text is no exception. The way text elements are laid out, their color, size, typeface, all this and more communicate a website’s core message and brand.

To manipulate the appearance of text on the web, our primary tool of choice is CSS.

The CSS properties I’m going to present in this post can be found in the CSS Text Module specification.

This module describes the typesetting controls of CSS; that is, the
features of CSS that control the translation of source text to
formatted, line-wrapped text.

In other words, The CSS Text Module deals with the display of characters and words in the browser, and how they’re spaced, aligned, hyphenated, etc., using CSS.

What constitutes a basic unit of text or word, as well as where exactly a word is allowed to break in a given piece of text, significantly depends on the rules of the language being used in a website. For this reason, it’s important to declare this information in the HTML document (usually in the lang attribute of the <html> element).

Here, I won’t be discussing the following two topics:

  • fonts, that is, the visual representations of characters, i.e. glyphs, and their properties;
  • features of CSS related to text decoration, such as underlines, text shadows, and emphasis marks.

If you’re curious, you’ll find the latest documentation on fonts and text decoration properties in the CSS Fonts Module Level 3 and the CSS Text Decoration Module Level 3 respectively.

Manipulating Letter Case

There can be times when text elements need to be displayed in capital letters, for instance first and last name. CSS gives us control on letter case with the text-transform property.

The default value of the text-transform property is none, that is, no effect on letter case is applied.

The capitalize Value

If you’d like the first letter of each word to be displayed in uppercase while leaving the appearance of all other letters unaffected (whatever their case in the HTML document), using the value capitalize will achieve this:

The HTML:

<h2>alice's adventures in wonderland</h2>

The CSS:

h2 {
  text-transform: capitalize;
}

text-transform capitalize example

Notice how capitalize doesn’t follow title case conventions: in fact, all first letters in the above example appear capitalized, including the word “in”. Authors who intend to follow a literary convention concerning titles will need to manipulate the letters manually in the source text.

The uppercase Value

If your goal is to have all letters displayed in uppercase, no matter their case in the HTML document, uppercase is the appropriate value to use:

The HTML:

<h2>alice's adventures in wonderland</h2>

The CSS:

h2 {
  text-transform: uppercase;
}

text-transform uppercase example

The lowercase Value

Using the value lowercase will cause all letters to be displayed in lowercase. Naturally, this won’t affect the appearance of letters that are already lowercase in the original source document.

The HTML:

<h2>Alice's Adventures in Wonderland</h2>

The CSS:

h2 {
  text-transform: lowercase;
}

text-transform lowercase example

The full-width Value

The specification has added a new value, full-width. This value constrains the character to appear inside a square as if it were an ideographic character, e.g., Japanese, Chinese, etc. This facilitates aligning Latin characters with ideographic characters.

Not all characters have a corresponding full-width form, in which case characters will not be affected by the full-width value.

The HTML:

<h2>Alice's Adventures in Wonderland</h2>

The CSS:

h2 {
  text-transform: full-width;
}

Here’s what characters look like in Firefox when full-width is applied:

text-transform full-width example

Further Remarks

Browser support for the text-transform property is excellent. In fact, all major browsers support it.

The only exception is the full-width value, which at present works only in Firefox. Perhaps understandably so, given the probability that full-width is at risk of being dropped at the Candidate Recommendation stage of the spec.

Further, I’ve noticed a small inconsistency between Firefox (v.39) and other major browsers in rendering the capitalize value on a hyphenated word.

Here’s what it looks like in Firefox:

first letter after a hyphen character is not turned into uppercase in Firefox when the capitalize value is applied

Notice how the first letter after a hyphen is not being capitalized. On the other hand, below is the same text displayed in Chrome:

first letter after a hyphen character is turned into uppercase in Chrome and all other major browsers when capitalize value is applied

In this instance, letters following a hyphen character are no exception; they are also being displayed with a capital letter. I’ve observed this same behavior in the latest release of all other major browsers except, as noted above, Firefox.

Finally, mind the cascade! If you set the text-transform property on a container element, its value is inherited by all its child elements. To avoid undesired results, reset the child elements’ text-transform property value to none.

View a demo for the text-transform property values.

How to Handle White Space

When you press the Tab key, the space key, or force some text to break to the next line (using the ENTER key or the <br> tag), you create white space in your source document.

By default, browsers collapse sequences of white space into a single space, line breaks are removed, and lines of text wrap to fit their container. This is convenient for us because it allows us to indent and separate chunks of text to keep our source document readable and maintainable without impacting how content is displayed in the browser.

However, what if this isn’t your goal? Let’s say, for instance, that you’d like to preserve the white space you create in the HTML document. A common scenario is when you write some text designed to be displayed as a properly indented code snippet. Or, you’d like some text to be displayed all on one line, without breaking.

On such occasions, when you intend to override the browser’s default behavior, the white-space property offers some interesting options.

The normal keyword resets the browser to its default behavior: all extra white space is collapsed into one character and lines wrap when they reach the edge of their container.

The pre Value

The pre keyword allows you to display text by preserving all the white spaces and forced new lines present in the source document. Text will not wrap into a new line when overflowing its container.

element {
  white-space: pre;  
}

Example of white-space set to the pre keyword

Example of source code styled with the pre keyword of the white-space property

If you use tabs to create white space, you can control their size with the tab-size property by setting it to an integer value.

element {
  white-space: pre;
  -moz-tab-size: 4;
  -o-tab-size: 4;
  tab-size: 4;
}

tab-size is a property with inconsistent browser support, but if you really can’t stand the default tab’s character length, here’s a polyfill to cover all your bases.

The pre-wrap Value

Let’s say you’d like white space in the source document to be preserved in the browser display. However, you’d also like to let lines wrap as they reach the edge of their container.

The pre-wrap keyword will help you achieve the desired result.

element {
  white-space: pre-wrap;  
}

Notice how each line displayed in the browser reflects the forced breaks in the source code, although the container has plenty of room to fit more text:

Example of pre-wrap keyword for the white-space property

Source code styled with the pre-wrap keyword of white-space property

However, shrink your browser screen and you’ll notice the lines wrapping to fit their container.

Small screen display of text formatted with the pre-wrap keyword of the white-space property

The pre-line Value

A final interesting value for the white-space property is pre-line. To the extent it collapses sequences of space into one space and allows wrapping, it behaves like normal. However, where a new line character or a <br> tag is present in the HTML document, these are preserved in the browser display.

element {
  white-space: pre-line;   
}

Example of text formatted with pre-line keyword of white-space property

Source code of the example for pre-line keyword of white-space property

Try out the CodePen demo for the pre, pre-wrap and pre-line keywords.

The nowrap Value

nowrap is perhaps the best known white-space value. Does your design require that a piece of inline content should never wrap? Using white-space: nowrap; on your element does the trick.

Louis Lazaris points to the following use case for this value.

Link with double arrow symbol as use case for the nowrap value of the white-space property

Above is a link followed by the » symbol. Having this character drop to the next line, for example in fluid web layouts, wouldn’t be desirable.

Link with double arrow symbol unseemly dropped to the next line

In this and similar circumstances (think of icons, for instance), the nowrap value is quite handy.

Another interesting use case is brought to us by Sara Soueidan in the Codrops CSS reference. Sara points out that the white-space property can be applied to any inline content, including images.

It is used with the value nowrap sometimes to create a horizontal list of images in a scrollable element, by preventing the images from wrapping and forcing them to be displayed on one single line inside their container.

I’ve enlarged on this suggestion by creating a basic jQuery carousel using white-space: nowrap. Here’s the demo:

See the Pen Using the word-wrap Property on an Image Carousel by SitePoint (@SitePoint) on CodePen.

Taking Control of Line Breaks Inside Words

Sometimes it happens that a design looks off because a long word fails to wrap to the next line, thereby overflowing its container. Long URLs or some user-generated long words in blog comments are common scenarios.

The following CSS properties are designed to give us some measure of control on handling long words on the web.

The word-wrap/overflow-wrap Property

The overflow-wrap property (previously called word-wrap, fully supported and working in all major browsers for legacy reasons) takes effect if the white-space property allows for text wrapping. It can have one of two values: normal and break-word.

By using the normal value, words break at allowed break points, e.g., spaces, hyphens, etc.

The break-word value permits arbitrary breaking points inside a word if the line can’t otherwise be broken at some other acceptable point.

The image below shows the display of a long word that overflows its container:

Example of long word overflowing its container

Let’s set the overflow-wrap property, and also, for legacy purposes, the word-wrap property, to the break-word value:

element {
  word-wrap: break-word;
  overflow-wrap: break-word;
}

… and the long word’s display is now broken into multiple lines to fit the available space.

word-wrap with break-word value

The hyphens Property

Breaking up long words is all well and good. However, the resulting text could be confusing to readers. A better option is to hyphenate the word as it breaks to the next line. This way, it’s immediately clear to readers they’re looking at one word wrapping onto multiple lines. To achieve this, CSS offers the hyphens property, which you can use in conjunction with word-wrap: break-word.

More specifically, the auto value of the hyphens property enables you to display a hyphen at the point where words break to the next line, if the document’s language rules allow it or hyphenation is present in the HTML source. For this to work, make sure you set the lang attribute to your desired language in the HTML document:

.break-word.hyphens-auto {
  -moz-hyphens: auto;
  -webkit-hyphens: auto;
  -ms-hyphens: auto;
  hyphens: auto;
}

hyphens auto browser display

You can also prevent the display of hyphen characters. In this case, set the hyphens property to none:

.break-word.hyphens-none {
  -moz-hyphens: none;
  -webkit-hyphens: none;
  -ms-hyphens: none;
  hyphens: none;
}

hyphens none browser display

Additionally, you can display hyphen characters on line breaks within words, if words are hyphenated in the markup and the text wraps to the next line. This is done with a value of manual:

.break-word.hyphens-manual {
  -moz-hyphens: manual;
  -webkit-hyphens: manual;
  -ms-hyphens: manual;
  hyphens: manual;
}

hyphens set to manual: browser display

Source code styled with hyphens set to manual keyword

Aided by vendor prefixes, browser support for the hyphens property is good on all major browsers, although not without some slight inconsistencies. The latest versions of Chrome (v.44) and Opera (v.30) at the time of writing don’t support the property value auto.

View the above examples on CodePen

Manipulating space between Words and Letters

What makes a piece of text more or less readable often depends on a number of factors. In some cases, increasing or decreasing the space between each word or each single letter, i.e. tracking, brings about huge improvements.

CSS offers the word-spacing and letter-spacing properties to control the appearance of spacing between words and letters respectively.

The word-spacing Property

Below are the values for the word-spacing property:

  • normal
  • <length>
  • percentage

normal displays the default space between letters. The amount of space depends on the font used or the browser.

.normal {
  word-spacing: normal;
}

<length> lets you add inter-word spacing in addition to the default spacing defined by the font or the browser.

.length {
  word-spacing: 0.5em;
}

percentage works the same way as <length> but using percentage values. I haven’t found any browser implementation for it and percentages are at risk of being removed from future drafts of the specification.

.percentage {
  word-spacing: 1%;
}

word-spacing values of normal and length

The letter-spacing Property

You can set the letter-spacing property to one of two values: normal or <length>.

Using normal leaves the default font spacing between letters. It also resets any letter-spacing length previously specified to its default value. For instance, if you specify a letter-spacing value of 1em on a parent element but wish to display the default value on child elements, normal is your friend.

element {
  letter-spacing: normal;
}

letter-spacing value set to normal

The <length> value is a unit of measurement, e.g. px or ems, whereby you can increase the spacing between letters in addition to the default spacing already provided by the font.

element {
  letter-spacing: 1em;
}

letter-spacing value set to a length of 1em

Further Details

word-spacing is not only applicable to words. You can use it on any kind of inline or inline-block content.

Also, you can animate both word-spacing and letter-spacing. However, using CSS transitions on letter-spacing shows that the normal value is not recognized by the current version of Firefox (v.39). To overcome this, simply replace normal with 0em.

Here’s a demo with animated text using word-spacing and letter-spacing:

See the Pen Animating the CSS letter-spacing and word-spacing Properties by SitePoint (@SitePoint) on CodePen.

Latest CSS Options for Text Alignment

The text-align property has been around for some time. It controls how inline content like text and images are aligned inside a block container. The kewords left and right align inline content to the left and right respectively. Setting text-align to center aligns the content to the center of its container. Finally, the justify keyword justifies content so that each line is of the same length (except for the last line, if it’s not sufficiently long to reach the edge of its container).

The spec adds two new values that could be quite useful on internationalized websites using right-to-left (RTL) language systems: start and end.

For left-to-right (LTR) readers, they correspond to left and right respectively. When a website uses a RTL language, start corresponds to right and end corresponds to left.

element {
  text-align: start;
}

start value of the text-align property

element {
  text-align: end;
}

end value of the text-align property

Applying text-align: match-parent to an inline child element ensures that the child inherits the same alignment as the parent. The inherited start or end value is calculated against the parent’s language direction resulting in an output of either left or right.

The text-align-last Property

New to CSS is also the text-align-last property. This property controls the alignment of the last line of justified text before the end of a paragraph or before a <br> tag. It has the same keyword values as text-align, except for auto, which is the default value. The auto value allows you to align the last line of text according to the value of the element’s text-align property, if set. If no text-align property is applied, the text defaults to a value of start.

At the time of writing, browser support for text-align-last is rather poor. Therefore, it’s my view that it should be used sparingly, if at all.

View a CodePen demo showing these features in action

Indenting Text

Indenting a line of text, usually the first line in a paragraph, is not something you often come across on websites. Instead, an empty line is placed as a common visual mark of separation between paragraphs.

Nonetheless, indenting the first line of a paragraph is sometimes used to create a classic look suitable to specific designs.

Indentation on the first line of a paragraph

If your design is enhanced by this technique, CSS offers the text-indent property. Let’s consider the possible values.

A value of length is commonly set using px or em units:

element {
  text-indent: 2em;
}

A percentage is set using a percentage value:

element {
  text-indent: 6%;
}

A value of each-line indents the appearance of the first line inside a block container as well as each line after a forced line break, that is, a line break caused by hitting the enter key or inserting a <br> tag in the HTML source. However, the display of the first line after a soft wrap break, that is, text that wraps to the next line to fit its container, is not affected.

A value of hanging causes all lines except the first line to be displayed as indented.

The each-line and hanging values are experimental values, not yet implemented in any browser at the time of writing.

View this demo to see text-indent in action

Conclusion

CSS has been making huge progress towards web text manipulation, although more is expected to be done. Besides sketchy browser support for some of the newest properties, it would be nice, for example, if CSS offered kerning capabilities, i.e., the opportunity to manipulate the distance between two letters in a given word.

In this post I delved into a number of CSS properties that control formatting, line wrapping, and alignment of text on the web. Feel free to experiment with these using the demos.

I look forward to your feedback!