It has been suggested that beautiful and usable websites are created on a foundation of beautiful and usable typography. I’ve even read an article that suggests that the web is actually comprised of 95% typography. I’m not convinced that there is any empirical evidence for this figure, but I think that the point is a good one. And, that makes typography a pretty important element that you will want to look at very carefully.

Create Beautiful CSS3 Typography
Fortunately, CSS offers a variety of styling options that allow you a great deal of control over how your present your content to your viewers and users.
I’ve actually been meaning to prepare an article about typography for a while now, and I’ve finally gotten around to it in the form of this tutorial. Today we’re going to take a detailed look at how to create a beautiful and attractive typographic design using a variety of awesome CSS3 rules (many of which were also available in CSS2).
Starting with Mark-Up
Before we can get started with any kind of styling, we need to begin by creating some content, all nicely marked up as HTML. No need to waste a lot of time on this. Here is the basic markup that we will be using:
<h1>
Web Typography
<span>A Demo For Beautiful Typography on the Web</span>
</h1>
<div class="meta">An <span>Article</span> by <span>Matt Ward</span></div>
<div class="body">
<p>It has been suggested that beautiful and usable websites are created on a foundation of beautiful and usable typography. That makes it a pretty important element that you will want to look at very carefully.</p>
<p>Fortunately, CSS offers a variety of styling options that allow you a great deal of control over how your present your content to your viewers and users. This demo - which is entirely driven by CSS - is built to demonstrate the step by step development of attractive typography, moving from basic HTML to fully styled content. You can use the buttons at the top of the page to view the content in various stages of styling, from completely unstyled to the completed design. Please feel free to have a bit of fun by working through the various stages.</p>
<date>Created: May 13, 2010</date>
</div>
Basically, we have a heading (and sub-heading, as distinguished by a <span> tag), followed by some meta information about the author, some paragraphs and a creation date. When we look at this content unstyled, it looks something like this:

Unstyled content
Aside from the coloured background, this is basically just the way that the browser renders the content without any styles. It doesn’t look horrible, but, with a bit of love, we can make it a whole lot better.
Step 1
The first thing that we want to handle is the title itself. We’re going to change the colour, the typeface, the size and the tracking. Here’s the full style rule.
h1{
font-size: 2.5em;
font-family: Georgia;
letter-spacing: 0.1em;
color: rgb(142,11,0);
text-shadow: 1px 1px 1px rgba(255,255,255,0.6);
}
After applying these styles, we now have a nice bold heading, as shown in this screenshot:

Content after Step 1
Now, let’s take a look at some of what we did in the CSS. First, we increased the font size up to a full 2.5em, and mixed a nice dark red colour using the rgb() colour definition.
Next, we changed the typeface of the entire title to Georgia, which is a web-safe serif font that looks really nice. Of course, with wide support for @font-face these days, we don’t really need to restrict ourselves to web-safe fonts anymore, but Georiga still works really nicely, so I’ll just stick with it.
Personally, however, I find that the default tracking on the Georgia font is a little tight, so I open it up just a little, using the letter-spacing property. Because I am using the proportional em unit, we want to keep the number relatively low. Otherwise, the tracking will become overdone.
Lastly, we applied a subtle letterpress effect by using a thin, white drop shadow, which actually ends up looking more like a highlight.
Step 2
The title looks good now. However, we also want to break out the main title and the subtitle. This is why we marked up the subtitle into a <span> tag, which will allow us to apply these different styles:
h1 span{
display: block;
margin-top: 0.5em;
font-family: Verdana;
font-size: 0.6em;
font-weight: normal;
letter-spacing: 0em;
text-shadow: none;
}
We create a logical break between the heading and the sub heading by converting the inline <span> into a block level element, and established visual differentiation by lowering the text size, reducing the weight (removing the bold) and changing the typeface from Georgia to the sans serif Verdana. Notice, however, that we do nothing with the colour. Because of CSS inheritance, the original colour rules for the heading are maintained by the sub heading.

Content after Step 1
This works nicely to maintain a level of continuity within the title. Even though we want some differentiation between the title and the subtitle, we don’t want to separate them too much.
We also want to remove the letterpress effect by eliminating the drop shadow, and reset the tracking by reducing the letter spacing back down to 0.
Step 3
The next two steps involve working on the meta data line. For this one, I want to create a very strong differentiation from the title, without changing the typography completely. So, here is the CSS that we’re going to use:
.meta{
font-family: Georgia;
color: rgba(69,54,37,0.6);
font-size: 0.85em;
font-style: italic;
letter-spacing: 0.25em;
border-bottom: 1px solid rgba(69,54,37,0.2);
padding-bottom: 0.5em;
}
Keeping with the Georgia font helps to maintain some nice typographical unity within the design. Changing to either another serif or sans serif font would likely just cause typographical confusion, and changing all of the other properties helps to create enough of a difference between the meta information line and the title.

Content after Step 3
You may also notice that I use the rgba() colour definition rather that just the regular rgb(). This is definitely one of my absolute favourite parts of CSS3, since it adds a fourth dimension to the definition: an alpha channel that allows us to control opacity. When using rgba(), the fourth property (a number between 0 and 1) actually defines the level of transparency to be applied to that particular colour! It may not seem like much, but it’s an incredibly powerful tool. It’s not fully supported in IE yet, but it’s pretty easy to build in some graceful degradation.
Step 4
Next, we want to make one more quick change to the meta line. You may notice that I surrounded both the term “articles” and my name in <span> tags in the markup. This is because I want to add in a very slight typographical variation on these bits of text. I can accomplish it with just a few lines of code:
.meta span{
text-transform: capitalize;
font-style: normal;
color: rgba(69,54,37,0.8);
}
The text-transform property is an awesome way of dealing with case in your designs. In this instance, I made everything uppercase, but sometimes it’s also useful to reduce everything to lowercase too.

Content after Step 4
I also removed the italic styling and reduced the overall transparency (making the text more opaque), in order to establish further contrast between these snippets of text and the rest of the line.
Step 5
Historically, creating columns in CSS has been something of an arduous process, involving a division of the content into different block level containers, along with floats or other positioning magic. It was certainly better than using tables, but still not necessarily ideal. Fortunately, with the new typographic elements introduced in CSS3, creating columns has become simpler than ever.
We’re going to use some of this new typographical goodness in our next step, by creating two columned paragraphs.
.body p{
font-family: Verdana;
-moz-column-count: 2;
-moz-column-gap: 1em;
-webkit-column-count: 2;
-webkit-column-gap: 1em;
column-count: 2;
column-gap: 1em;
line-height: 1.5em;
color: rgb(69,54,37);
}
The rule is a little long and just a tiny bit redundant, since we need to use Mozilla and Webkit specific properties to make sure that the styling is actually applied across as many browsers as possible. Eventually, I’m sure that they will both accept the standard property, but for now it’s best to keep all the declarations, just to make sure that it renders like this:

Content after Step 5
With these properties, you can set the number of columns that you want to use, and the space gap between the columns, which is great because it can allow you to keep a design tightly aligned to an underlying grid.
Also, while in this case I simply applied the column properties to the paragraph, you can also apply them to a higher, container-level element such as a <div> and have all the child paragraphs flow nicely into the proper structure.
The other thing we want to note about this styling rule is that we changed the main paragraph text to Verdana, matching it typographically to the sub title. Again, the rest of the properties are different enough to maintain a strong visual difference, but the use of the same font helps keep everything tied together.
Step 6
We are going to maintain this continuity in the sixth step too. We actually have two paragraphs in our markup, and based on the way we applied the columns, the order of the copy is actually somewhat disjointed. I did this on purpose, though, as I want to add a some different styling to the first paragraph.
.body p:first-child{
font-size: 1.25em;
font-family: Georgia;
font-style: italic;
-moz-column-count: 1;
-webkit-column-count: 1;
column-count: 1;
letter-spacing: 0.1em;
}
.body p:first-child:first-line{
font-weight: bold;
}
There are a couple of things that you should notice about this code. First, we are using the first-child pseudo-class to target any paragraph that is the first child of an element with the class of “body”. This is a handy little selector that allows you to build in some nice visual variation to the beginning of a block of text.

Content after Step 6
In this case, I want to add extra emphasis to this first paragraph, thereby giving more weight and significance to its content. I also want to stretch it across the two columns and change the font back to Georgia, again for emphasis.
Getting rid of the columns is actually pretty easy. All I have to do is replicate the column-count properties, and reduce it back down to 1.
Next, I can change the font family, and again I increase the letter spacing just a tad to help everything breath a bit better in Georgia. Then, for just an little bit of extra emphasis, I set the whole font style to italic.
You’ll also notice that this is the only step in this tutorial that actually includes two CSS rules. The second one is just a short little snippet that combines both the first-child pseudo-class and the first-line pseudo-class, allowing me to actually bold the first line of the first paragraph!
Step 7
Our typographic styling is pretty much complete. The only thing left to do now is add some styles to the date.
date{
font-family: Georgia;
color: rgba(69,54,37,0.6);
font-size: 0.75em;
font-style: italic;
letter-spacing: 0.25em;
border-top: 1px solid rgba(69,54,37,0.2);
display: block;
padding-top: 0.5em;
margin-top: 2em;
}
The rule here is pretty similar to the rule for the line of meta information. The only real difference is that I reduced the font size a little bit, to help establish a better visual hierarchy. I also flipped the border-based rule from the bottom to the top.

Content after Step 7
Because the <date> tag creates an inline element by default, I changed the display mode to block. Finally I extended the top margin to improve the overall balance.
Typographical Summary
So there you have it: we’ve created what I think is an attractive typographical design using nothing by HTML and CSS. No images are used at all. To wrap this article up, I would just like to make a few quick notes about the typography itself.
- Despite only using two fonts in the entire design, I was able to create a wide range of styles, simply by altering the size, weight, colour and other properties of the type. This is a great way to generate typographical interest without having to rely on a lot of fonts. As I’ve already mentioned a couple times, it also helps to maintain unity within the design.
- Tracking (letter spacing) and leading (line spacing) are two elements of typography that are often overlooked when working with type on the web. However, while it may not have all the precession control of InDesign or Quark, CSS does provide some basic tools that allow use to make adjustments in these areas, resulting in more beautiful type.
- The art of typography is not just about picking fonts, colours and sizes. It’s not even just about leading, tracking and kerning. These are all just concepts used to describe and modify type. The real purpose of typography, however, is to help create and convey meaning through words. One of the ways to do this is through visual hierarchy – making typographical choices that reflect the relative importance of each and every element.
- Lastly, every element matters. Good typography takes nothing for granted. Instead, it makes a careful consideration of each and every element, no matter how insignificant it may seem. Ultimately, an element may be allowed to inherit a default value, but that should always be a conscious choice rather than an oversight.
Of course, there is always more that could be said about typography. Still, while I am no master of the craft, these are some of the things that I’ve learned through the process of my own work. I hope you find them, and this tutorial to be of some use!
Step by Step Demo
To accompany this tutorial, I have also put together a step by step demo, which allows you to use the links in the bar along the top and examine the design in its various stages of development. Move from unstyled to fully completed and back again, and have some fun along the way:
What do you think? I would love to hear your thoughts and opinions on both the tutorial itself and the demo, so please feel free to drop me a line.



This is how you write a proper tutorial. I was able to understand it completely. Great article!
Yes I complete agree with you, This is what we want to see in tutorial. Simple and step by step tutorial
@Matt Ward(author), Please keep it up.
I don’t know if this is normal but when I am looking at the vertical blue line going down the left side of your site it is running through text. Also when I type in the comment box it is putting the characters underneath the box. I don’t know if this is normal or not and this is what I have going on during the first load of this site. When you say we do not have to restrict ourselves to web-safe font’s what do you mean? Not all computers have all the font’s in the world.
Hi Jason. Thanks for the comment. The blue line was the result of an unclosed tag in the content. All fixed up. As for not having to be restricted to web-safe fonts, these days we are able to use @font-face construct. Check out this article over at A List Part for more information
Congratulations! This is really well done, nice and informative. I’m gonna try it out soon. Thanks a lot
Hi Matt,
very nice and a good in-depth article .., cheers for that. But I wondered if you’ve seen the outcome of your code in IE?
Not nice .. as 40-50% still use this browser, the probability you’ll going to get a f*cked-up layout in IE is very big! We’ll have to wait for IE10, I guess ..
Nevertheless, thanks for sharing a good article, Cheers & Ciao ..
Fantastic tutorial. I’ve never thought about this way to style the text. Now I have something to play with. Thanks
Great article, neat and clear…. as usual ;)
I(ve a question though, what about justifying the text? It’s quite never used and I don’t understand why imho it looks clearer but i must be wrong.
Anyway thanks for sharing, and have a good one.
Cheers
Ross
Great article, thanks. It would be even better if it weren’t reverse text on black. Too hard to read!
Wonderful and inspiring article :)
I’ve just added it to my bookmarks!
Thanks for sharing!
very nice step by step tutorial, impressive result, thanks!
Going between the “Unstyled” and the “Step 7″ in the demo is a really quick way to see just how important typography is on the web. How many sites have we seen that closely resemble “Unstyled” with maybe a font change? Too many.
madebyross: no browser is doing justification right. It will in almost all cases (with some exceptions still requiring manual rewriting to force usable word lengths) produce really yucky and unreadable text. When you see justification in printed materials, you almost never see oddly-spaced words. On the web, you almost always do!
Sorry, poorly researched, in the sense that you missed the biggest step of all!
When dealing with CSS3 and “beautiful topography”; you first need to load and then enable the fonts you’ve chosen (so they display in the clients browser)!
If you don’t do this first, no matter how hard you try, site visitors will not be able to display the Georgia font; if you don’t use CSS3 to load it for them – prior to beautifying.
(Remember, not everyone has the Georgia font installed).
I would expect someone who tauts themselves as a Graphics Design Specialist and a Creative Director, to be cognizant of such basic CSS3/HTML coding
Hi Rama. Thanks for your perspective. I have to disagree though. In all my research both Georgia and Veranda are listed as web safe fonts, since they come pre-installed on both Windows and Mac machines, meaning that the vast, vast majority of all users will have it installed on their machines. The article was already getting long enough and I didn’t want get into using @font-face.
Besides, it seems rather redundant to load web safe fonts from the server when virtually every visitor will already have it installed. That will just result in an extra and unnecessary request, adding to the overall overhead.
In retrospect, however, I probably should have added a font stack so that for those incredibly few people who might not have these fonts could at least get serif and sans serif fonts in the right places. So I do apologize for that. Overall, however, I just don’t feel that @font-face is necessary in this context.
Okay, I see where you’re coming from. @font-face does come into play (thankfully) when we want to really spice things up with fonts not in a web safe font stack.
In your case, I can appreciate how you had to take the length of the post into consideration, that’s wise.
Great article. I’m just curious why you chose to use a SPAN tag within the H1 tag instead of splitting it up into an H1 and H2 tag? If someone were viewing it with a screen reader, or their own style sheet enabled, the sub-head would appear as part of the title and not be grammatically correct.
Hi Jeff. Great question. I looked at it both ways and came to this conclusion: The entire title of the demo is “Web Typography: A Demo For Beautiful Typography on the Web”. From my perspective, though there is a title and sub title, it all comprises one main heading. Given that, breaking it into two separate heading tags just didn’t seem semantically correct.
Madebyross: When you justify text, you might have a mice straight line at the right edge of the text – but the space between the words varies a lot, making it hard to read. When you look at the text as a block, you can also see that variable wordspacing gives the effect of putting big holes in the block.
So instead of a nice block of flush-left, ragged right text of even color, you have a rectangular block of text with more holes than a pound of Swiss cheese! Delicious in omelets and quiche maybe, but hard to read for more than a paragraph.
Oh Mary THank you SO much for your reply, I was beginning
to be desperate :)
And your explanation is really what i needed to understand the concept perfectly!
Thank you again.
Ross
This was a well written and enjoyable tutorial, well done.
I have invested in a couple of font collections and found them to lift my work a little and give it that something extra that you just can’t achieve with the free fonts you get in the operating system, I have also found quite a few supprisingly attractive free fonts out there too. I think a little left of normal is always good.
Very nice typography. Thanks for sharing a great tutorial.
Hi Matt,
Thanks for taking the time to write this article. It is always interesting to see what can be done with just a few different techniques and a disciplined, consistent approach. Regards.
Apart from CSS columns all the rest has been achieveable for years using CSS2.1 (your use of rgba isn’t really necessary in this instance).
I don’t know why you’ve used a “date” element either – it’s not defined in any existing HTML specification.
True. The rgba() wasn’t strictly necessary, but I wanted to talk about it anyhow, because I love the idea. As for the date element – that is weird. I was obviously writing from a false memory. I really thought there was an element… Will have to update the post later.
The devil is in the details! I wasn’t aware of the first-line pseudo selector. Thank you for the article :)
Wonderful! Will try it soon! very informative!
The only issue I see is that when dividing paragraphs it doesn’t flow properly like a regular top to bottom right to left brochure would. You sort of fix this by styling the first paragraph differently, but what if there were a third one? When I read columns I’m expecting to move down and right not right and down. Unfortunately it’s just going to be one of those things that you have to plan for and only break elements up into columns that read properly.
Hey Derek. Thanks for the comment and observation. I see your point, and tried to address this when I wrote
“Also, while in this case I simply applied the column properties to the paragraph, you can also apply them to a higher, container-level element such as a <div> and have all the child paragraphs flow nicely into the proper structure.”
Since I only had the two paragraphs, I elected not to add in an extra structural element and just apply the columns to the paragraphs themselves and then fix the issue by restyling the first paragraph.
If I had use more paragraphs, I would have approached things differently. Perhaps I should have been a bit more clear on this point. Or, perhaps there is another way of approaching it that I am not quite aware of?
The problem with adding the style to the div container is that the styling of the first paragraph as full-width then breaks. A solution to that is obviously to have p.first outside the div container, but that kinda’ puts a wet blanket on the idea of separating content from presentation (and also breaks the simple usecase of having non-html users putting in text in a standard textarea in common CMS). Of course this problem can be solved by some tinkering, but it would be nice if there was a css solution to get the p columns to flow down.
Great tutorial! thanks for post
This post was great, I was able to follow it and will apply to my blog! Thanks alot for the Tut…
Very useful post. I’m guessing some browsers, i.e. FF, Safari will display this sort of typography better than I.E.
Hi, thanks for the well written article. I like the ‘column-count’ css property and I’m going to use it in my current projects.
And, one thing. Try to fix the height of the text area in this website’s Feedback Form (FYI: I was using a webkit browser while browsing through this website). I was initially struggling to click the text area to write a comment. I think the use of background-images for styling text and input fields (particularly to style borders) is NOT a good idea as it breaks more often during, particularly when resizing the textarea via browser, thereby making the form fields look ugly and not accessible, as in this case.
Anyway, I really enjoyed reading your article. Thanks again for the post :)
Thanks for a well written tutorial . In particular I liked the way you used <span> to break up the long title.
I will definitely be using that method in the future.
Wonderfully written article!!! I learnt a lot. Thanks.
Hi,
I ported the JS script to Mootools 1.2.
Example on JSFiddle :
http://www.jsfiddle.net/vgjTh/
While working on it, I devised a Scroll example :
http://www.jsfiddle.net/U6v37/
Thanks for the CSS.
Already use some tips from here. Thanks for the great post Matt. Btw, its sad we need to use webkit and all this features because this features are not included on standards. In IE all the beauty you may try to do using this stuff goes away :/
Hi, I’m beginning to learn css program. Write your thank you letter will help me a lot of work.
I just want to thank you for your great tutorials! I am new to design with a brand new degree and still feel incredibly overwhelmed and unprepared. Your tutorials cover practical need-to-know topics that you just don’t necessarily get in the classroom. Keep them coming!
Thanks for post! I find it really useful.Like always things are not so complicated as they look, of course if know what to do. =)
This is so fantastic! I’m trying to spruce up on my CSS3 and this is a great help. I love the simplicity of the columns.