Embedded Fonts and Multicolumn Layouts - HTML5 & CSS3 FOR THE REAL WORLD (2015)

HTML5 & CSS3 FOR THE REAL WORLD (2015)

Chapter 9 Embedded Fonts and Multicolumn Layouts

We’ve added quite a lot of decoration to The HTML5 Herald, but we’re still missing some key components to give it that old-fashioned feel. To look like a real newspaper, the text of the articles should be laid out in narrow columns, and we should use some suitably appropriate fonts.

In this chapter, we’ll add to the look and feel of our website with @font-face and CSS3 columns.

Web Fonts with @font-face

Since the early days of the Web, designers have been dreaming of creating sites with beautiful typography. But, as we all know too well, browsers are limited to rendering text in just the fonts the user has installed on their system. In practical terms, this has limited most sites to a handful of fonts: Arial, Verdana, Times, Georgia, and a few others.

Over the years, web decelopers have come up with a number of clever workarounds for this problem. We created JPEGs and PNGs for site titles, logos, buttons, and navigation elements. When those elements required additional states or variants, we created even more images. We then converted our text images to image sprites to ensure the page stayed snappy and responsive. Whenever the design or text changed, all those images had to be recreated. By definition this was a bad idea, but it really caused problems when it came to site performance, accessibility, translations, and internationalization. For page elements that need to change frequently, or at all, and to maximize accessibility and minimize bandwidth usage, we were stuck with those same few fonts.

To fill this typographic void, a few font-embedding scripts were created such as the Flash- and JavaScript-based sIFR methods, and the canvas-based Cufón. While these methods were a useful stopgap measure, allowing us to include our own fonts, they had severe drawbacks. Sometimes they were tricky to implement. They required that JavaScript be enabled and, in the case of sIFR, the Flash plugin be installed. In addition, they significantly slowed the page’s download and rendering.

@font-face rule

Fortunately, there’s now a better way. @font-face is a pure CSS solution for embedding fonts—and it’s supported on every modern browser.

We’ll be including two embedded fonts on The HTML5 Herald site: League Gothic from The League of Movable Type, and Acknowledgement Medium by Ben Weiner of Reading Type. The two fonts are shown respectively in Figure 9.1 and Figure 9.2.

League Gothic

Figure 9.1. League Gothic

Acknowledgement Medium

Figure 9.2. Acknowledgement Medium

We’ll now look at how we can embed these fonts and use them to power any of the text on our site, just as if they were installed on our users’ machines. While including multiple fonts may improve a site’s appearance, it’s important that your typography choices don’t decimate your site’s performance.

Implementing @font-face

@font-face is one of several CSS at-rules, like @media, @import, @page, and the one we’ve just seen, @keyframes.

At-rules are ways of encapsulating several rules together in a declaration to serve as instructions to the browser’s CSS processor. We saw the @keyframes at-rule in the previous chapter. The @font-face at-rule allows us to specify custom fonts that we can then include with the font-familyproperty in other declaration blocks.

To include fonts using @font-face, you have to:

1. load the font file onto your servers in a variety of formats required by all the different browsers

2. name, describe, and link to that font in an @font-face rule

3. include the font’s name in a font-family property value in your CSS, just as you would for system fonts

You already know how to upload a file onto a server, so we’ll discuss the details of the various file types in the next section. For now, we’ll focus on the second and third steps so that you can become familiar with the syntax of @font-face.

Here are the rules that go into an @font-face block:

@font-face {

font-family: 'fontName';

src: source;

font-weight: weight;

font-style: style;

unicode-range: characters;

}

The font-family and src properties are required. The font-weight, font-style, and unicode-range are optional.

You need to include a separate @font-face at-rule for every font you include in your site. You’ll also have to include a separate at-rule for each variation of the font: regular, thin, thick, italic, black, and so on. The HTML5 Herald will require two imported fonts, so we’ll include two @font-face blocks:

@font-face {

}

@font-face {

}

The font-family declaration part of the @font-face at-rule declaration is slightly different from the font-family property with which you are already familiar. In this case, we’re declaring a name for our font, rather than assigning a font with a given name to an element. The font name can be anything you like—it’s only a reference to a font file, so it need not even correspond to the name of the font. Of course, it makes sense to use the font’s name, or an abbreviated version of it, to keep your CSS readable and maintainable. Whatever you decide to name your font, it’s best to settle on a convention and stick to it for all your fonts. For our two fonts, we’ll use camel case:

@font-face {

font-family: 'LeagueGothic';

}

@font-face {

font-family: 'AcknowledgementMedium';

}

Declaring Font Sources

Now that we have a skeleton laid out for our @font-face rules and given each of them a name, it’s time to link them up to the actual font files.

There are several different font formats, including EOT, OTF, TTF, WOFF, WOFF2, among others. EOT (Embedded Open Type) font is a proprietary format for Internet Explorer and the only file type understood by IE4 through IE8. TTF (TrueType Font) is an outline font that is the most common format for fonts on the Mac OS and Microsoft Windows operating systems. OTF (OpenType Font) is a scalable font built on TTF, with the same basic structure but added data structures for prescribing typographic behavior. The W3C recommendation is WOFF (Web Open Font Format), which is essentially an OpenType or TrueType font format with compression and additional metadata. The goal for WOFF was to improve performance, by minimizing the bandwidth needed to send the font file to the client. WOFF2 is the second W3C spec, improving compression and therefore performance.

The src property can take several formats. Additionally, you can declare more than one comma-separated source as the value of the source property.

Let’s add some formats to our League Gothic declaration:

@font-face {

font-family: 'LeagueGothicRegular';

src: url('../fonts/League_Gothic-webfont.eot?#iefix')

↵format('embedded-opentype'),

url('../fonts/League_Gothic-webfont.woff2') format('woff2'),

url('../fonts/League_Gothic-webfont.woff') format('woff'),

url('../fonts/League_Gothic-webfont.ttf') format('truetype');

}

There are four font sources listed in this code block. If the browser fails to locate or recognize the first source, it will try for the next one, and so on, until it either finds a source it supports (at which point it stops looking) or runs out of options.

The first declaration is the EOT font declaration for older versions of Internet Explorer.

Then we define WOFF2, which has the best compression but is yet to be well supported; then WOFF, which is a better-supported Web Open Font Format. We then declare the TTF (TrueType Font) and OTF (OpenType Font) fallback formats. We used to include an SVG (Scalable Vector Graphics) font file for the original iPhones. This format is being deprecated, but continues to be supported.

WOFF is supported in all newer browsers, so we could have simply included a single WOFF file; however, we have a new format in WOFF2, similar to WOFF but with better web font compression (leading to faster loading), and we still want to ensure some support for older Android browsers.

Here's a table showing current browser support for the various font formats.

Table 9.1. Browser support for font formats

IE

Safari

Chrome

Firefox

Opera

iOS

Android

@font-face

6

3.2

4

3.5

10

3.2

2.1

WOFF

9

5.1

5

3.6

11.1

5.1

4.4

WOFF2

36

35?

23

5[a]

OTF

9

3.1

4

3.5

10.1

4.3

2.2

TTF

9

3.1

4

3.5

10.1

4.3

2.2

SVG

3.2

4-37[b]

9.6

3.2

3.0

EOT

4

[a] starting with Android 5.0, the WebView will be updated so it will support WoFF2

[b] To be precise, “SVG fonts are no longer supported, except on Windows systems older than Windows 7. Note that while the feature works on those systems, it is considered deprecated.”

As you can see, WOFF is supported in all modern browsers. You may still want to provide fallbacks for older browsers, like we did with video in Chapter 5. Because of bandwidth issues, however, you may just want to include WOFF for newer browsers and EOT for IE8, and avoid forcing additional HTTP requests to older mobile devices. If a format hint is listed, browsers check to see if it is supported before downloading or advancing to the next format listed. If no format hint is included, the browser downloads the resource. While we list WOFF 2.0 for browsers that support it, WOFF for the majority of browsers, TTF for Android 4.4 and below, and EOT for IE8 and earlier, as long as we provide the format hint, only the font file the browser will use will be downloaded.

Adding these extra font formats ensures support for all browsers, but unfortunately it can cause problems in versions of IE older than IE9. They see everything between the first url(' and the last ') as one URL, so will fail to load the font. Fortunately, adding a query string to the end of the EOT URL is a quick fix, so no choice needs to be made between supporting IE or supporting all other browsers. This tricks the browser into thinking that the rest of the src property is a continuation of that query string, so it goes looking for the correct URL and loads the font:

@font-face {

font-family: 'LeagueGothicRegular';

src: url('../fonts/League_Gothic-webfont.eot?#iefix') format(' embedded-opentype'),

url('../fonts/League_Gothic-webfont.woff2') format('woff2'),

url('../fonts/League_Gothic-webfont.woff') format('woff'),

url('../fonts/League_Gothic-webfont.ttf') format('truetype');

}

Font Property Descriptors

Font property descriptors—including font-style, font-variant, font-weight, and others—can optionally be added to define the characteristics of the font face, and are used to match styles to specific font faces. The values are the same as the equivalent CSS properties:

@font-face {

font-family: 'LeagueGothicRegular';

src: url('../fonts/League_Gothic-webfont.eot?#iefix') format('embedded-opentype'),

url('../fonts/League_Gothic-webfont.woff2') format('woff2'),

url('../fonts/League_Gothic-webfont.woff') format('woff'),

url('../fonts/League_Gothic-webfont.ttf') format('truetype');

font-weight: bold;

font-style: normal;

}

You are not telling the browser to make the font bold; rather, you’re telling it that this is the bold variant of the font. This can be confusing, but there is a reason to use the font-weight or font-style descriptor in the @font-face rule declaration. You can declare several font sources for the same font-family name:

@font-face {

font-family: 'CoolFont';

font-style: normal;

src: url(fonts/CoolFontStd.woff);

}

@font-face {

font-family: 'CoolFont';

font-style: italic;

src: url(fonts/CoolFontItalic.woff);

}

.whichFont {

font-family: 'CoolFont';

}

Notice that both at-rules use the same font-family name but different font styles. In this example, the .whichFont element will use the CoolFontStd.woff font, because it matches the style given in that at-rule; however, if the element were to inherit an italic font style, it would switch to using the CoolFontItalic.woff font instead.

The Unicode Range Descriptor

Also available is the unicode-range descriptor, which is employed to define the range of Unicode characters supported by the font. If this property is omitted, the entire range of characters included in the font file will be made available.

Here’s an example of what it looks like:

unicode-range: U+000-49F, U+2000-27FF, U+2900-2BFF, U+1D400-1D7FF;

If you are including a Unicode range, it makes sense to create font files containing only the characters within your range to reduce bandwidth and memory consumption. Tools that convert your desktop fonts to EOT, WOFF, WOFF2, TTF, OTF, and SVG, such as Font Squirrel Generator, are capable of creating very small font resources containing only the characters you need; however, you have to take care to include all the characters that may be required. Furthermore, if you want to enable your content to be translated while maintaining the desired look and feel, you’ll likely need to include the characters for any translation. The process of creating these smaller files is described shortly. Unfortunately, this feature is yet to be well supported..

Applying the Font

Once the font is declared using the @font-face syntax, you can then refer to it as you would any normal system font in your CSS: include it in a font stack as the value of a font-family property. It's a good idea also to declare a fallback font or two in case your embedded font fails to load.

Let’s look at one example from The HTML5 Herald:

h1 {

text-shadow: #ffffff 1px 1px;

font-family: LeagueGothic, Tahoma, Geneva, sans-serif;

text-transform: uppercase;

line-height: 1;

}

Our two embedded fonts are used in a number of places in our stylesheet, but you get the idea.

Legal Considerations

We’ve included the markup for two fonts on our site, but we’re yet to put the font files themselves in place. We found both of these fonts freely available online. They are both licensed as freeware; that is, they're free to use for both personal and commercial use. Generally, this is the only kind of font you should use for @font-face, unless you're using a third-party service.

How is @font-face any different from using a certain font in an image file? By having a website on the Internet, your font source files are hosted on publicly available web servers. In theory, anyone can download them. In fact, in order to render the text on your page, the browser has to download the font files. By using @font-face, you’re distributing the font to everyone who visits your site. To include a font on your website, then, you need to be legally permitted to distribute the font.

Owning or purchasing a font doesn’t give you the legal right to redistribute it—in the same way that buying a song on iTunes doesn’t grant you the right to put it up on your website for anyone to download. Licenses that allow you to distribute fonts are more expensive (and rarer) than licenses allowing you to use a font on one computer for personal or even commercial use.

There are several websites that have free downloadable web fonts with Creative Commons,[11] shareware, or freeware licensing. Alternatively, there are paid and subscription services that allow you to purchase or rent fonts, generally providing you with ready-made scripts or stylesheets that make them easy to use with @font-face.

A few sites providing web font services include Typekit, Typotheque, Webtype, Fontdeck, and Fonts.com.

Google’s web fonts directory has a growing collection of fonts provided free of charge and hosted at Google’s servers. It simply provides you with a URL pointing to a stylesheet that includes all the required @font-face rules, so all you have to do is add a link element to your document and the font name in a font-family declaration in your CSS in order to start using a font.

When selecting a service, font selection and price are certainly important, but there are other considerations. Make sure any service you choose to use takes download speed into consideration. As has been mentioned, font files can be fairly large, potentially containing several thousand characters. Good services allow you to select character subsets, as well as font-style subsets, to decrease the file size. Bear in mind, also, that some services require JavaScript in order to function.

Creating Various Font File Types: Font Squirrel

If you have a font that you’re legally allowed to redistribute, there’ll be no need for you to use any of the font services mentioned. You will, however, have to convert your font into the various formats required to serve the most performant file format while supporting every browser on the market. So how do you go about converting your fonts into all of these formats?

One of the easiest tools for this purpose is Font Squirrel’s @font-face generator. This service allows you to select fonts from your desktop with a few clicks of your mouse and convert them to TTF, EOT, WOFF, WOFF2, SVG, SVGZ, and even a Base64 encoded version.[12]

By default, the Optimal option is selected for generating an @font-face kit; however, in some cases you can decrease the file sizes by choosing Expert and creating a character subset. Rather than including every conceivable character in the font file, you can limit yourself to those you know will be used on your site.

For example, on The HTML5 Herald site the Acknowledgement Medium font is used only in specific ad blocks and headings, so we require just a small set of characters. All the text set in this font is uppercase, so let’s restrict our font to uppercase letters, punctuation, and numbers, as shown in Figure 9.3.

Selecting a subset of characters in Font Squirrel’s @font-face generator

Figure 9.3. Selecting a subset of characters in Font Squirrel’s @font-face generator

Figure 9.4 shows how the file sizes of our subsetted fonts stack up against the default character sets. In our case, the uppercase- and punctuation-only fonts are 25 to 30% smaller than the default character sets. Font Squirrel even lets you specify certain characters for your subset, so there's no need to include all the letters of the alphabet if you know you won’t use them. Just remember, if there's the possibility that your text might be translated, you may need to include characters not in your original content.

File sizes of subsetted fonts can be substantially smaller

Figure 9.4. File sizes of subsetted fonts can be substantially smaller

For the League Gothic font, we’ll need a more expanded character subset. This font is used for article titles, which are all uppercase like our ads, so we can again omit lowercase letters; however, we should consider that content for titles may include a wider range of possible characters. Moreover, users might use in-browser tools or Google Translate to translate the content on the page—in which case other characters might be required. So, for League Gothic, we’ll go with the default Basic Subsetting—this will give you all the characters required for Western languages.

When employing @font-face, as a general rule minimize font file size as much as reasonably possible, while making sure to include enough characters so that a translated version of your site is still accessible.

Once you’ve uploaded your font for processing and selected all your options, press Download Your Kit. Font Squirrel provides an archive containing your font files with the extensions requested, a demo HTML file for each font face style, and a stylesheet from which you can copy and paste the code directly into your own CSS.

Tip: Font Squirrel’s Font Catalog

In addition to the @font-face generator, the Font Squirrel site includes a catalog of hand-picked free fonts whose licenses allow for web embedding. In fact, both the fonts we’re using on The HTML5 Herald can also be found on Font Squirrel, with ready-made @font-face kits to download without relying on the generator at all.

To target all browsers, make sure that you’ve created WOFF2, WOFF, TTF, and EOT font file formats, including SVG if you’re still supporting really old mobile. Once you’ve created the font files, upload the web fonts to your server. Copy and paste the CSS provided, changing the paths to point to the folder where you’ve placed your fonts. Make sure the font-family name specified in the @font-face rule matches the one you’re using in your styles, and you’re good to go!

Note: Font Failure

If your fonts are failing to display in any browser, the problem could very well be the path in your CSS. Check to make sure that the font file is actually where you expect it to be. Browser-based debugging tools—such as the Web Inspector in WebKit, Opera, and Chrome; F12 in Internet Explorer; or the Firebug Firefox extension—will indicate if the file is missing.

If you’re sure that the path is correct and the file is where it’s supposed to be, make sure your server is correctly configured to serve up the fonts. Windows IIS servers won’t serve up files if they’re unable to recognize their MIME type, so try adding WOFF to your list of MIME types (EOT and TTF should be supported out of the box):

.woff application/x-font-woff

Finally, browsers are supposed to require that font files are served from the same domain as the page they're embedded on: if your fonts fail to work in Internet Explorer or Firefox, make sure to set CORS configurations to enable fonts from different domains and CDNs.

Note: Developer Tools

Browsers come standard with tools to help save you time as a web developer. In most browsers you can right-click (or control-click on a Mac) and choose Inspect Element. A panel will open up at the bottom of your browser, highlighting the HTML of the element you’ve selected. You’ll also see any CSS applied to that element.

While Safari comes with this tool, it needs to be manually enabled. To turn it on, go to Safari > Preferences, and then click the Advanced tab. Be sure to check the Show Develop menu in the menu bar checkbox.

Firefox comes with inspection tools, but Firebug—a free Firefox plugin that provides the same functionality as the other browsers’ native debuggers—is more robust. You can download Firebug at http://getfirebug.com/.

Internet Explorer also has developer tools that you can access via F12, enabling you to inspect elements.

Other Font Considerations

Embedded fonts can improve performance and decrease maintenance time when compared to text as images. Remember, though, that font files can be big. If you need a particular font for a banner ad, it may make more sense (given the limited amount of text required) to create an image instead of including font files. At the minimum, if you’re only embedding a font for your company name or logo, send just the limited character set needed for your name to your visitors. Or, better yet, save your logo as an SVG image.

When pondering whether to include multiple font files on your site, consider performance. Multiple fonts will increase your site’s download time, and font overuse can be tacky. Furthermore, the wrong font can make your content difficult to read. For body text, you should almost always stick to the usual selection of web-safe fonts.

Another point worth considering is that browsers are unable to render the @font-face font until it has been downloaded entirely. Browsers behave differently in how they display your content before the download is complete: some will render the text in a system font, while others won’t render any text at all.

This effect is referred to as a “flash of unstyled text,” or FOUT, a term coined by Paul Irish. To try to prevent this from happening (or to minimize its duration), make your file sizes as small as possible, serve them gzipped, and include your @font-face rules in CSS files as high up as possible in your markup. If there’s a script above the @font-face declaration in the source, some versions of IE experience a bug whereby the page will fail to render anything until the font has downloaded—so be sure to declare your fonts above any scripts on your page.

Another option to mitigate @font-face’s impact on performance is to defer the font file download until after the page has rendered. This may be unviable for your designer or client, however, as it may result in a more noticeable FOUT, even if the page loads faster overall.[13]

Of course, we don’t want to scare you away from using @font-face, but it’s important that you avoid using this feature without regard for the consequences. Remember that there are trade-offs, so use web fonts where they’re appropriate, and consider the available alternatives.

CSS3 Multicolumn Layouts

Nothing says “newspaper” like a row of tightly packed columns of text. There's a reason for this: newspapers break articles into multiple columns because long lines of text are too hard to read. Browser windows can be wider than printed books—even as wide as some newspapers—so it makes sense for CSS to give us the ability to flow our content into columns.

You may be thinking that we’ve always been able to create column effects using the float property. But the behavior of floats is subtly different from what we’re after. Newspaper-style columns have been close to impossible to accomplish with CSS and HTML without forcing column breaks at fixed positions. True, you could break an article into divs, floating each one to make it look like a set of columns. But what if your content is dynamic? Your back-end code will need to figure out where each column should begin and end in order to insert the requisite div tags.

With CSS3 columns, the browser determines when to end one column and begin the next without requiring any extra markup. You retain the flexibility to change the number of columns, as well as their width, without having to go back in and alter the page’s markup.

For now, we’re mostly limited to splitting content across a few columns while controlling their widths and the gutters between them. As support broadens, we’ll be able to break columns, span elements across multiple columns, and more. Browser support for CSS3 columns is moderate: IE10 and Opera Mini are the only two browsers with full, unprefixed support. Opera mobile and desktop used to have full support, but reverted to quirky prefixed support when it switched to the Blink engine (in version 15). Firefox, Blink (Chrome) and WebKit (iOS) browsers have had support via vendor-prefixed properties for years, with some bugs still needing to be fixed.

Almost all the content on the main page of The HTML5 Herald is broken into columns. Let’s dig deeper into the properties that make up CSS3 columns and learn how to create these effects on our site.

The column-count Property

The column-count property specifies the number of columns wanted, and the maximum number of columns allowed. The default value of auto means that the element has one column. Our left-most articles are broken into three columns, and the article below the ad blocks has two columns:

.primary article .content {

-webkit-column-count: 3;

-moz-column-count: 3;

column-count: 3;

}

.tertiary article .content {

-webkit-column-count: 2;

-moz-column-count: 2;

column-count: 2;

}

This is all we really need to create our columns. By default, the columns will have a small gap between them. The total width of the columns combined with the gaps will take up 100% of the width of the element.

Still, there are a number of other properties we can use for more granular control.

The column-gap Property

The column-gap property specifies the width of the space between columns:

.primary article .content,

.tertiary article .content {

-webkit-column-gap: 10px;

-moz-column-gap: 10px;

column-gap: 10px;

}

Declare the width in length units, such as ems or pixels, or use the term normal. It’s up to the browser to determine what normal means, but the spec suggests 1em. We’ve declared our gaps to be 10px wide. The resulting columns are shown in Figure 9.5.

Our left-most content area has articles split over three columns

Figure 9.5. Our left-most content area has articles split over three columns

The column-width Property

The column-width property is like having a min-width for your columns. The browser will include as many columns of at least the given width as it can to fill up the element, up to the value of the column-count property. If the columns need to be wider to fill up all the available space, they will be.

.parent {

width: 400px;

column-count: 3;

column-width: 150px;

column-gap: 10px;

}

For example, if we have a parent that is 400 pixels wide, a 10-pixel column gap, and the column-width is declared as 150px, the browser can fit two columns:

(400px width – 10px column gap) ÷ 150px width = 2.6

The browser rounds down to two columns, making columns that are as large as possible in the allotted space; in this case, that’s 195px for each column—the total width minus the gap, divided by the number of columns. Even if the column-count were set to 3, there would still only be two columns, as there’s not enough space to include three columns of the specified width. In other words, you can think of the column-width as being the minimum column width and column-count property as specifying the maximum column count.

The only situation in which columns will be narrower than the column-width is if the parent element itself is too narrow for a single column of the specified width. In this case, you’ll have one column that fills the whole parent element.

It’s a good idea to declare your column-width in ems, ensuring a minimum number of characters for each line in a column. Let’s add a column-width of 9em to our content columns:

.primary article .content,

.tertiary article .content {

-webkit-column-width: 9em;

-moz-column-width: 9em;

column-width: 9em;

}

Now, if you increase the font size in your browser, you’ll see that the number of columns is decreased as required to maintain a minimum width. This ensures readability, as shown in Figure 9.6.

Declaring column-width in ems ensures a minimum number of characters on each line

Figure 9.6. Declaring column-width in ems ensures a minimum number of characters on each line

The columns Shorthand Property

The columns shorthand property is a composite of the column-width and column-count properties. Declare the two parameters—the width of each column and the number of columns—as previously described:

.primary article .content {

-webkit-columns: 3 9em;

-moz-columns: 3 9em;

columns: 3 9em;

}

The math of those two declarations may not give you what you’d expect. By default, there is a gap of 1em between every two columns. If our .content is less than 29 ems wide (three columns of 9ems each, plus two times the column-gap of 1em), say 25 ems, the browser will display only two columns:

(25em total width – 2em column gaps) ÷ 9em column width = 2.55

To have three columns fit, our parent would need to be at least 29 ems wide:

(29em total width – 2em column gaps) ÷ 9em column width = 3 columns

If the .content is equal to or greater than 29 ems, say 38 ems, the browser will show a maximum of three columns, displaying columns that are 12 ems wide:

(38em total width – 2em column gaps) ÷ 3 columns = 12 ems

Again, think of columns values as the maximum number of columns and minimum width per column. The only time a column will be less than 9em in this case is if .content is less than 9em wide.

Columns and the height Property

With the aforementioned declarations—and no height specified on the element—browsers will balance the column heights automatically so that the content in each column is approximately equal in height.

But what if a height is declared? When the height property is set on a multicolumn block, each column is allowed to grow to that height and no further before a new column is added. Depending on the browser, the columns may start with the first column and create as many columns as necessary, or just the one if there is minimal text. This is how Opera and Chrome currently handle columns but to ensure this effect in all browsers, include column-fill: auto;.

If you want to declare a height on your element, but would also like the content to be spread evenly across your columns, you can use the column-fill property. When supported and set to balance, the browser will balance the height of the columns as though there were no height declared. This is what happens by default in Safari and Firefox.

Finally, if too little space is allocated with the height property, the content will overflow from the parent—or be clipped if overflow: hidden; is set.

Note: Issues with Column Height

Even with a height declared, columns may still not appear to have exactly the desired height because of the bottom margins on paragraphs. Some browsers split margins and padding between columns, sometimes adding the extra spacing at the top of a column that follows. Others allow margins to go beyond the bottom of the box, rather than letting them show up at the top of the next column, which makes more sense.

As with column-width, you may also want to declare your height in ems instead of pixels; this way, if your user increases the font size, they are less likely to have content clipped or overflowing.

Other Column Features

Beyond the core count, width, and gap properties, CSS3 provides us with additional features for laying out multicolumn content.

The column-rule Property

Column rules are essentially borders between each column. The column-rule property specifies the color, style, and width of the column rule. The rule will appear in the middle of the column gap if there is content in the column to both sides of the rule. Similar to border, the column-ruleproperty is actually shorthand for the column-rule-color, column-rule-style, and column-rule-width properties.

The syntax for the values is exactly the same as for borders and the related border-width, border-style, and border-color properties. The width can be any length unit, just like border-width, including the key terms of medium, thick, and thin. And the color can be any supported color value:

-webkit-column-rule: 1px solid #CCCCCC;

-moz-column-rule: 1px solid #CCCCCC;

column-rule: 1px solid #CCCCCC;

Column Breaks

There are three column-breaking properties that, when supported, will allow developers to define where column breaks should appear. The break-before, break-after, and break-inside properties take a limited number of key terms as values to define whether a column break can and should occur before, after, or inside an element respectively. Rather than being applied to the same element on which we defined our primary column properties, they’re applied to other elements nested inside it. Unfortunately, only IE10+ supports these properties at the time of this writing.

The values available are the same as for page-break-after, page-break-before, and page-break-inside: auto, always, avoid, left, right, page, column, avoid-page, and avoid-column.

For example, you might want to avoid a column break occurring immediately after an h2 element in your content. Here’s how you’d do that:

.columns {

column-count: 3;

column-gap: 5px;

}

.columns h2 {

break-after: avoid;

}

Until Blink and WebKit support the standard properties, we can include vendor-specific syntax that behaves similarly. Note the addition of the word column to the property names in the non-standard prefixed syntax:

-webkit-column-break-after: always;

-webkit-column-break-before: auto;

-webkit-column-break-inside: never;

Spanning Columns

The column-span property will make it possible for an element to span across several columns. If column-span: all; is set on an element, all content that comes before that element in the markup should be in columns above that element. All content in columns appearing in the markup afterthe element should be in columns below the spanned element.

The h1s span all the columns. The text between the two headings is divided equally across three columns, with the column rules breaking for the second heading. The rest of the text—that which follows the second heading—is again divided across the three columns, with the column rules dividing the columns but not displayed behind the spanning text:

article {

columns: 3 12em;

column-rule: 1px solid #CCCCCC;

}

h1 {

column-span: all;

}

p {

margin-top: 0;

}

We included margin-top: 0 on the paragraphs to ensure paragraphs that start at the top of the column aren’t dropped by 1em.

For cross-browser compatibility, you would add the -webkit- prefix for Chrome, Opera, and Safari. Firefox doesn’t support column-span at all, and IE supports it without a prefix. Including this feature results in a very different appearance when there’s no support, so you may want to develop for browsers that don’t support it, and put the column-span: all; behind @media queries or @supports rules.

For example, for the first article on The HTML5 Herald, we could have applied the column properties to the article element rather than the .content div, and used column-span: all; to ensure that the video spanned across the full width of the article; however, this would appear badly broken in Firefox—so we instead opted to separate the video from the column content.

Other Considerations

If you’ve been following along with our examples, you might notice that some of your blocks of text have ugly holes in them, like the one shown in Figure 9.7.

“Rivers” appear in your text when your columns are too narrow

Figure 9.7. “Rivers” appear in your text when your columns are too narrow

This problem occurs when text with text-align: justify; is set in very narrow columns, as we’re doing for The HTML5 Herald. Browsers are yet to know how to hyphenate words in the same way that word processors do, so they space words out awkwardly to ensure that the left and right edges stay justified.

For The HTML5 Herald, we’ve used a JavaScript library called Hyphenator to hyphenate words and keep our text looking tidy. This may, however be unnecessary for your site—our columns are extremely narrow, as we’re trying to replicate a newspaper style.

If you prefer to use CSS instead of JavaScript to hyphenate, there is a solution. The character is an invisible or “soft” hyphen you include to suggest a location within a word where it would make sense to hyphenate if necessary. The hyphen is only shown if there is a word break at that point. This differs from the regular hyphen, which is displayed whether or not there is word break at that character.

Browsers are slowly gaining the ability to hyphenate words like word processors do. The experimental hyphens property—with possible values of none, manual, and auto—supports auto hyphenation in some spoken languages, as defined in the lang attribute in IE and Firefox with a prefix. Internet Explorer 10 and Firefox 6 both support the prefixed experimental hyphens: auto, if the browser has integrated the dictionary for the document’s declared language. See https://developer.mozilla.org/en-US/docs/Web/CSS/hyphens.

Few real-world sites would likely need justified columns that narrow, but if you ever come across this issue, it’s good to know that there are solutions available.

Progressive Enhancement

While columns still have limited browser support, there’s no harm in including them in your sites unless your designer is a stickler for detail. Columns can be viewed as a progressive enhancement: making long lines easier to read. Those using browsers without support for columns will be none the wiser about what they’re missing. For instance, The HTML5 Herald will have no columns when viewed in Internet Explorer 9, as Figure 9.8 shows. But the site certainly doesn’t look broken—it’s simply adapted to the capabilities of the browser.

Our site has no columns when viewed in IE9—but that’s okay!

Figure 9.8. Our site has no columns when viewed in IE9—but that’s okay!

If, however, columns are an important feature of your design that must be provided to all visitors, there are scripts that can help; for instance, there’s Columnizer, a jQuery plugin by Adam Wulf.

Up Next

There are many new features in CSS that progressively enhance a site, such as columns and fonts, with non-supporting browsers still rendering all the content.

When it comes to content, one size fits all. You want to send the same content to all your users no matter how they are accessing it. With browsers and devices of different sizes and resolutions, however, it’s far from being “one size fits all” when it comes to presentation. You’ll want to include fewer columns on a narrower screen than you would on a large screen. You may also want to include fewer fonts on a device with limited bandwidth.

Responsive websites are more than just “squishy” layouts. In the next chapter, we look at a few features that will help you send the right design to the right screen size, including flexbox, which—combined with media queries—enables on-the-fly changing of your layout.


[11] If you’re unfamiliar with Creative Commons licenses, you can find out more at http://creativecommons.org/.

[12] Base64 encoding is a way of including the entire contents of a font file directly in your CSS file. Sometimes this can provide performance benefits by avoiding an extra HTTP request, but that’s beyond the scope of this book. Don’t sweat it, though—the files generated by the default settings should be fine for most uses.

[13] For more on @font-face and performance, as well as an example of how to “lazy load” your font files, see http://www.stevesouders.com/blog/2009/10/13/font-face-and-performance/.