How To Lay Out Text with CSS

The author selected the Diversity in Tech Fund to receive a donation as part of the Write for DOnations program.

Introduction

The way text is presented on a web page determines how legible the content is and how willing the reader is to read the content. Web typesetting, the art of laying out text, is about controlling the content to present the reader with a pleasant and efficient reading experience.

This tutorial will teach you how to use the CSS properties that are most effective at laying out text content. You will use properties like line-height, letter-spacing, and text-transform with demo content to optimize for reading and define a content hierarchy by giving headings prominence. These concepts and approaches will help you better present content on your websites.

Prerequisites

  • An understanding of CSS’s cascade and specificity features, which you can get by reading How To Apply CSS Styles to HTML with Cascade and Specificity.
  • Knowledge of type selectors, combinator selectors, and selector groups, which you can find in How To Select HTML Elements to Style with CSS.
  • An empty HTML file saved on your local machine as index.html that you can access from your text editor and web browser of choice. To get started, check out our How To Set Up Your HTML Project tutorial, and follow How To Use and Understand HTML Elements for instructions on how to view your HTML in your browser. If you’re new to HTML, try out the whole How To Build a Website in HTML series.

Setting Up the HTML and CSS Files

In this section you will set up the HTML content that you will style throughout the tutorial. The purpose of the HTML in this tutorial is to provide various elements and situations to style. You will also create your CSS file and set a base style.

To begin, open index.html in your text editor and add the following HTML to the file:

index.html

<!doctype html> <html>     <head>     </head>     <body>     </body> </html> 

Next, in the <head> tag, you will add a meta tag for the character set for this page, a title element for the title of the page, a meta tag defining how the page should be handled on mobile devices, and the CSS files to load:

index.html

<!doctype html> <html>     <head>         <meta charset="UTF-8" />         <title>Text Layout</title>         <meta name="viewport" content="width=device-width" />         <link rel="preconnect" href="https://fonts.gstatic.com" />         <link href="https://fonts.googleapis.com/css2?family=Public+Sans:ital,[email protected],400;0,700;1,400;1,700&amp;family=Quicksand:[email protected]&amp;display=swap" rel="stylesheet" />         <link href="styles.css" rel="stylesheet" />     </head>     <body>     </body> </html> 

Notice that the CSS files include a couple of fonts from Google Fonts and the styles.css file you will create later in this section. If you’d like to learn more about how to use Google Fonts, check out How To Style Text Elements with Font, Size, and Color in CSS.

Now you will set up the HTML content contained within the page’s <body> tag. This content will be contained in an <article>, which will have an <h1> element, a couple each of <h2> and <h3> elements, and several <p> elements throughout. You will fill these tags with text content from the Cupcake Ipsum filler text generator. This filler content will provide all that is needed to apply visual styles for this tutorial.

Apply the HTML to your index.html, as shown in the highlighted sections of the following code block:

index.html

<!doctype html> <html>     <head>         ...     </head>     <body>         <article>             <h1>Sugar plum chupa chups chocolate bar cupcake donut</h1>             <h2>Tootsie roll oat cake macaroon</h2>             <p>Jujubes brownie candy. Dessert tootsie roll pie gummi bears danish cotton candy. Sugar plum <strong>I love fruitcake pastry</strong>. Jelly-o gummi bears muffin gummi bears marzipan cheesecake donut gingerbread I love. Cupcake wafer cake.</p>             <p>Cupcake donut topping <em><strong>chupa chups halvah</strong></em> chupa chups. Macaroon tootsie roll cupcake caramels chocolate fruitcake gingerbread jelly-o. Tiramisu I love marshmallow jelly-o I love jelly beans candy gummi bears.</p>             <h2>Jelly beans tiramisu pastry danish donut</h2>             <h3>Lemon drops pastry marshmallow</h3>             <p>I love marshmallow candy. <em>Sesame snaps</em> muffin danish. Chocolate cake cookie jelly-o tiramisu halvah brownie halvah chocolate chocolate cake. Jelly-o caramels jujubes bonbon cupcake danish tootsie roll chocolate bar. Macaroon I love muffin candy canes sweet roll I love. I love bonbon marshmallow croissant ice cream I love gummi bears.</p>             <p>Pie apple pie I love jujubes biscuit I love. Chocolate cake pastry tiramisu <strong>soufflé powder caramels</strong> I love ice cream. Dragée liquorice toffee jelly jelly beans. Sesame snaps candy canes soufflé. Biscuit donut bear claw jujubes halvah pastry macaroon lemon drops. Tootsie roll dragée cookie candy soufflé dragée cupcake liquorice.</p>             <h3>Apple pie pudding topping</h3>             <p>Powder dragée sesame snaps candy canes jelly-o. Halvah gingerbread cheesecake wafer. <strong><em>Wafer tootsie roll</em></strong> I love I love. Cake toffee I love. Cotton candy cotton candy jelly beans I love bonbon toffee. Chupa chups chupa chups caramels ice cream halvah candy chocolate cake. Marshmallow carrot cake jelly beans.</p>             <p>Chocolate cake sweet roll pudding chocolate cake fruitcake bear claw.</p>         </article>     </body> </html> 

Save all these additions to your index.html file and then open the file in your web browser. As you write your styles, have the index.html file loaded in your browser to check how your styles are applied to the content:

Content in a serif font with black text on a white background.

Next, create a file in the same directory as index.html called styles.css and open the new file in your text editor.

There are two font families that you will load from Google fonts. The first font will be the default font for the page, as it will be used by all content on the page.

Create a body type selector and add a font-family property with the font stack 'Public Sans', sans-serif to set this as the new default font:

styles.css

body {     font-family: 'Public Sans', sans-serif; } 

This applies the font to the body element. All the content in this example will inherit that font, without needing to be declared individually. The font name is Public Sans, and it will have a fallback font that uses the browser’s default sans-serif font. Fonts should always have a fallback font using a comma separated list called a font stack. Fallback fonts provide a readable option if the custom font doesn’t load or lacks a special character.

Next, the heading elements, h1, h2, and h3, will get a special font for the rest of the page called Quicksand. Create a group selector consisting of the three headers h1, h2, h3 and apply the same font stack setup as the body with Quicksand:

styles.css

body {     font-family: 'Public Sans', sans-serif; }  h1, h2, h3 {     font-family: 'Quicksand', sans-serif; } 

Save your changes to styles.css and return to your browser to reload index.html. The custom font will now load, as shown in the following image:

Content with black text on a white background with heading text in a rounded sans serif font and the paragraphs in sans serif font.

For the last part of setting up your files, return to your styles.css file in the text editor. Create singular type selectors for the h1, h2, h3, and p elements to define a font-size for each. Use the rem unit for value, setting the h1 to 2.5rem, the h2 to 1.875rem, the h3 to 1.5, and the p to 1.25rem:

styles.css

... h1, h2, h3 {     font-family: 'Quicksand', sans-serif; }  h1 {     font-size: 2.5rem; /* 40px */ }  h2 {     font-size: 1.875rem; /* 30px */ }  h3 {     font-size: 1.5rem; /* 24px */ }  p {     font-size: 1.25rem; /* 20px */ } 

The code block includes a comment that indicates what each rem value will return as a px unit. The rem unit gives the user more control over adjusting the font-size to a preferable ratio than the px value allows. For more on these units, read through How To Use Common Units in CSS.

Save your changes to styles.css and return to your browser to reload the index.html file. The text font sizes will adjust to look similar to the following image:

Content with black text on a white background with heading text in a rounded sans serif font and the paragraphs in sans serif font with various sized text.

In this section you set up your HTML content in index.html and created your styles.css file. You applied the Google Font typefaces to the CSS globally on the body element and specifically to the h1, h2, and h3 elements. You also set the font-size values for all the text elements on the page. In the next section you will use the width property to create more readable line lengths.

Improve Line Lengths Using width and max-width

In this section, you will use the width and max-width properties to set an appropriate line length for the text.

An often overlooked aspect of web typography is how long a line of text is presented. For both users in need of accessibility assistance and those without, the length of a line contributes significantly to the effort needed to read the text. The longer a line of text is the more likely the reader will have difficulty keeping track of the text. Shorter lines of text help the reader navigate and scan the content.

Open styles.css in your text editor and write an article type selector to apply a width of 90% and add a margin property with a value of 0 auto. This combination will make sure the content is set to be 90% of the screen’s width, and the auto value in the margin will keep the content block in the middle of the page:

styles.css

... article {     margin: 0 auto;     width: 90%; } 

Save these changes to styles.css and reload index.html in your browser. The text will be centered, but the lines of text will be very long. See the following image for how this will appear in your browser:

Text content in black taking up 90% of the width, with equal spacing on either side.

The ideal line length is between 45 and 75 characters, as explained by Clarissa Peterson in her talk on Responsive Typography. Longer than 75 characters and the reader can begin to lose track of what line they are reading. On the other hand, shorter than 45 characters and the readers eyes can become fatigued from the constant moving from line to line.

Setting a width based on a character count is possible with a unit called the character unit, represented by ch in code. The ch unit is determined by the size of the zero character (0) in the font. Since the ideal line length is between 45–75 characters, you can set a max-width value in that range, and the article element will stop growing once it has reached that size.

Return to the styles.css file in your text editor and, after the width property in the article type selector, add a max-width property and give it a value of 70ch:

styles.css

... article {     margin: 0 auto;     width: 90%;     max-width: 70ch; } 

This means that the maximum width the element is allowed to grow is the width of 70 zero characters of the font used in that space, which is the font set on the body element.

Save these changes to your styles.css file and reload index.html in your browser. You will find the content centered in the page at a maximum width of approximately 70 characters long. Try resizing the width of your browser to watch the article container transition from a 90% width to its maximum width, as shown in the following animation:

Animation showing a browser window with content growing in width with the window until the content reaches a maximum width.

Note: Chris Coyier, of CSS Tricks, created a handy bookmarklet tool that will highlight the range of characters between 45 and 75 to help find the best width to set your content.

In this section you learned that accessibility and legibility share a common ground with the line length of text content. You used the width property with the max-width property to set a size limiting the text length to 45–75 characters using the ch unit. In the next section, you will use the line-height property to set the appropriate spacing between lines of text.

Using the line-height Property to Help Readability

You will use the line-height property in this section to expand and contract the space between the lines of text. You may find that headings typically have less space between lines and that paragraph text tends to have more space. The goal for this spacing is to make the content easier to read. Similar to the width of lines of text, if the lines are too close together, the reader may be distracted by the line above or below. On the other hand, if the text is too far apart, the reader’s eyes can grow tired of jumping over the space between lines and find the text much harder to scan.

Open your styles.css file in your text editor and go to the body selector. Like the font-family, you will use line-height to set a default distance between lines for the whole document. Add the line-height property and give a value of 1.5. This value is a measurement of the distance between baselines, the line on which the bottom of text rests:

styles.css

body {     font-family: 'Public Sans', sans-serif;     line-height: 1.5; } ... 

The default for line-height is tied to the keyword value of normal, which is equal to 1.2 of the font size. This means if the font-size is 16px, then the line-height when set to normal is approximately 19.2px. This is a good median value; however, paragraph text usually needs a bit more space, while a heading sometimes needs a bit less.

Next, go to the group selector targeting h1, h2, h3 and set a line-height value to 1.15. This will bring the text between lines a bit closer together, and can help the presentation of long heading titles. Add the highlighted line in the following code block:

styles.css

... h1, h2, h3 {     font-family: 'Quicksand', sans-serif;     line-height: 1.15; } ... 

Save your changes to styles.css and return to the browser to reload index.html. You will find the length of the content expand as more space is placed between lines of text. See the following image for how this appears in the browser:

Text content in black on white with headlines closer together vertically and paragraph lines of text further apart.

The value for the line-height property can accept fixed unit values, as well as pixel (px) or rem, but it is better to leave no unit as the default behavior is to multiply the value by the font-size.

You used the line-height property in this section to make the content on the page more legible and easier to scan for the reader. In the next section, you will use the margin properties to set a defined amount of space between types of content as defined in the HTML.

Using the margin Properties for Spacing

In this section, you will use the margin property along with the adjacent sibling selector to apply different vertical spacing between the text elements. Where the line-height property gives control between lines of text in an element, margin can be used to adjust the spacing between content elements.

To begin, return to styles.css in your text editor and find the h3 selector. In this situation, you will add spacing to the element to have more space above the text and less space beneath. This will cause it to be farther from the content above and closer to the content below.

Add a margin property with a value of 2em 0 0.5em. This will apply spacing that is relative to the font-size value, meaning the top margin will be double the font-size at 48px and the bottom will be half the font-size at 12px:

styles.css

... h3 {     font-size: 1.5rem; /* 24px */     margin: 2em 0 0.5em; } ... 

Since the margin works on the outside of the element, each element’s margin properties will overlap. This means that even though the h3 margin on the bottom side is equivalent to 12px, the <p> element’s margin is larger and therefore defines the space between the <h3> and <p>. You can solve this problem by using the adjacent sibling combinator, which is defined by a plus sign (+) between two selectors, with styles applied to the latter in the sequence.

Create a new selector in styles.css in your text editor using the adjacent sibling combinator as h3 + p, then within the selector block add a margin-top property with a value of 0:

styles.css

... h3 {     font-size: 1.5rem; /* 24px */     margin: 2em 0 0.5em; }  h3 + p {     margin-top: 0; } ... 

The way the adjacent sibling combinator works, this means that when the browser has an <h3> element and immediately following it is a <p> element, then these styles are applied to only that <p> element. Other <p> elements are unaffected.

Save your changes to styles.css and load index.html in your browser. As shown in the following image, the space above the <h3> elements is now much larger and the space between the <h3> and first <p> after it is much closer.

Black text content with a large spacing between two headers.

In this section, you used the margin property to apply different spacing between the elements of the page. With the adjacent sibling selector, you set up conditionals that would apply a greater spacing amount if the <h3> element was preceded by a <p> element. In the next section, you will use the text-align property to adjust the placement of the text on a line.

Using text-align for Effective Content Presentation

You will now use the text-align property to change where the text is placed on a line. The property has four values: left, right, center, and justify. The default value for this property depends on the browser’s language setting. For languages that read from left to right, left is the default, while languages that read right to left have a default of right. The center property places the text in the center of the line of text and leaves an equal amount of blank space on either side of the line of text. Lastly, the justify value spreads the words out to the edges of the container, leaving visually inconsistent spaces between words.

Open styles.css in your text editor and find the h3 type selector. Add a text-align property with a value of center as shown in the highlighted portion of the following code block:

styles.css

... h3 {     font-size: 1.5rem; /* 24px */     margin: 2em 0 0.5em;     text-align: center; } ... 

Save your changes to styles.css and reload the index.html file in your browser. The content of the two h3 level headings are now centered above their respective sections. See the following image for how this appears in the browser:

Black sans serif text centered to the container.

It is best to keep the text-align property set to the default, as this is best for the user and their settings. However, changing the alignment value can help distinguish some text better or provide a better aesthetic.

You used text-align in this section to center text content within its container. You also learned how and when to use the other values available to the text-align property. In the next section, you will use the text-transform and letter-spacing properties to create visual personality while still keeping the text readable and maintaining efficient hierarchy.

Using letter-spacing and text-transform

Next, you will use the text-transform property and the letter-spacing property to adjust how the text of a headline appears. The text-transform property controls how text capitalization is formatted, providing options to change the text to uppercase, lowercase, or capitalize, which capitalizes the first letter of each word. The letter-spacing property is the value of space between each character. Together these two properties can create an aesthetic that is legible and stands out.

Begin with the text-transform property by opening styles.css in your text editor and go to the h1 type selector. Since this heading is the title of the whole article, it makes sense to have title-case formatting.

Add a text-transform property with a value of capitalize. This value will capitalize the first letter of each word, regardless of if it is capitalized in the HTML:

styles.css

... h1 {     font-size: 2.5rem; /* 40px */     text-transform: capitalize; } ... 

Save this addition to your styles.css file, then open index.html in your browser. The heading copy now has the first letter of each word capitalized, as shown in the following image.

Large black text in a rounded sans serif font, with the first letter of each word capitalized.

Next, return to the styles.css file in your text editor and find the h3 type selector. This time you will set up the h3 style to be all uppercase letters in each word by adding a text-transform property with a value of uppercase. Add the highlighted line for the following code block to your styles.css file:

styles.css

... h3 {     font-size: 1.5rem; /* 24px */     margin: 2em 0 0.5em;     text-align: center;     text-transform: uppercase; } ... 

After you have made this change, save styles.css and then refresh index.html in your browser. The h3 content will now be all uppercase, regardless of how it is written in the HTML. See the following image for how this appears in the browser:

Horizontally centered content in a black rounded sans serif font, all uppercase.

Note: When using CSS to apply uppercase styling to content, it can affect how screen readers interpret the content. For example, with Voice Over on macOS, a three-letter word that is set to uppercase by CSS will be read as an acronym instead of as a word. When using this styling approach, it is helpful to apply an aria-label attribute to the HTML element with how the content should be read.

Now that the text is all uppercase, visually the text feels a little bunched together for the aesthetic of the design. Next, use the letter-spacing property to add 0.125em spacing between each character. See the highlighted code in the following code block:

styles.css

... h3 {     font-size: 1.5rem; /* 24px */     margin: 2em 0 0.5em;     text-align: center;     text-transform: uppercase;     letter-spacing: 0.125em; } ... 

Using the em unit on a letter-spacing property allows the spacing between characters to be proportional to the font-size. The 0.125em keeps the spacing at one-eighth the height of the font.

Save your changes to styles.css and reload index.html in your browser to render the changes to the h3 content. See what this will look like in the following image:

Horizontally centered content in a black rounded sans serif font, all uppercase, with extra space between each characer.

In this section, you used the text-transform property to change the styles for the <h1> element to capitalize the first letter of each word. You also used the text-transform and letter-spacing properties to change the <h3> element to have all uppercase words with the characters spread apart. In the last section, you will use the font property to condense multiple properties into one.

Using the font Shorthand

In this last section, you will use the font property to condense multiple properties into a single property. The font property can be useful when defining several text-related values globally, and placed at a high level in the cascade. Be aware that using the font shorthand will overwrite the individual properties it contains.

To start, return to your styles.css file in your text editor and go to the body selector. Here the font-family and line-height properties can be condensed into the font shorthand property. However, the font shorthand requires that both a font-size and font-family value are present. This means adding a font-size value in addition to the line-height and font-family values. See the highlighted section of the following code block for how to write this out:

styles.css

body {     font: 1em/1.5 'Public Sans', sans-serif; } ... 

Notice that there is a forward slash (/) between the font-size value of 1em and the line-height value of 1.5. This is the only way to set a line-height value with the font shorthand property, and it must come after the font-size value. The font-size value is set to 1em since that is the least disruptive value and carries over the default font-size of the document regardless of its value. Additionally, the font property shorthand accepts values for the font-stretch, font-style,font-variant, and font-weight properties.

Be sure to save your changes to styles.css in your text editor. Reload the index.html in your browser and verify there are no visual changes. Since a shorthand property combines existing properties into a single property, there are no changes to the styles.

You used the font property in this last section of the tutorial to combine several properties into one, condensing the size of your CSS. This property, though very useful, must be used with consideration as it can require redefining properties due to its broad coverage.

Conclusion

Readable text layout can mark the difference between an effective and ineffective design. Laying out text is a subjective balance of providing sufficient space between text lines, words, and blocks to present the content in an unobtrusive manner. When working with text, poor layout can prevent readers from understanding the content. With these properties and their uses in mind, you will make well-read content.

If you would like to read more CSS tutorials, try out the other tutorials in the How To Style HTML with CSS series.