Getting fancy: CSS Transformations

One of the most intriguing things we can do with text is change its position and the way it looks on the screen with nothing but CSS in browsers that support it. The good news is that all browsers except IE8 and Opera Mini support transformations so we won’t have to do workarounds.

Example of what you can do with transitions and shapes
An example of what is possible with CSS shapes and transformations (taken from A List Apart’s article CSS Shapes 101 by Sara Soueidan.)

We’ll start with rotating the header of our content 90 degrees and move it down the column.

[codepen_embed height=”373″ theme_id=”2039″ slug_hash=”ZGJJvy” default_tab=”result” user=”caraya”]See the Pen CSS Content Rotation – Take 1 by Carlos Araya (@caraya) on CodePen.[/codepen_embed]

It looks good but I think it can look better. When we move it sideways the text looks very small and when we make the font larger it forces the text into 2 rows… and that’s not what I want… I want the larger text to stay in one column.

What I realized was that I had to change the design. Rather than keep the heading inside the content area, it would work better if we move the h2 element outside the content area and style it separately.

Transformations are very dependent on the dimensions of the content you’re working with. The codepen below shows the heading in the smallest media query I set up for the demo (800px wide). The heading is not rotated but displayed in above the text as in a regular page.

[codepen_embed height=”830″ theme_id=”2039″ slug_hash=”MwvWYd” default_tab=”result” user=”caraya”]See the Pen CSS Content Rotation Using Media Queries by Carlos Araya (@caraya) on CodePen.[/codepen_embed]

But if you look at a screenshot below, you’ll see what the code work when you set the screen as wide as possible.


Media queries would be the best solution to accommodate for all screen sizes. You will have to decide if Media Queries and Vendor prefixes is worth the effort and how many media queries you would have to create for your code to look good in your target device(s). It’s not a perfect solution, it requires tons of work and needs to be adjusted for all your target breakpoints and devices.

This is just the beginning of what you can do. Mozila Developers Network (MDN) provides a very good overview of CSS transformations to show what you can do.

Because this is dependent on screen resolution (when is a pixel is not a pixel) you must test in your target devices. Also : Just because you can it doesn’t mean you should. As great as transformations are they take time and may detract from your audience’s attention.

Links and Resources

Technology Typography

Using SASS maps in media queries

Version 3 of SASS introduced the map data type. If you’ve done work in any other programming type you’ll problbly be familiar with maps as associate arrays or hashes; SASS uses the same principle: maps are a collection of key-value pairs.

How does this affect typography? Simple: We can build a map to store media query breakpoints and associated font sizes and use those in our code without having to remember what rules we set up and how we


Sass script maps are a list of one or more key-value pairs assigned to a variable. We can use the map with looping functions to get one result for each key-value pair on the map when running the loop. Let’s use a basic set of colors for our social media profiles as an example:

$sm-profiles: (
  facebook: #3b5998,
  flickr: #0063db,
  github: #4183c4,
  googleplus: #dd4b39,
  linkedin: #007bb6,
  twitter: #00aced,
  vimeo: #aad450,
  youtube: #b00

We then create a function that loops through our map and, for each profile value, we make the background equal to the value of the profile key. The code to do that is show below:

@each $profile, $bgcolor in $sm-profiles {
  .profile-link--#{$profile}:hover {
    background: $bgcolor;

And the result for Vimeo (using the $sm-profiles map and the function discussed above) looks like this:

.profile-link--vimeo:hover {
  background: #aad450;

Applying maps to typography

$breakpoints: (
  small : 480px,
  medium: 700px,
  large : 1024px

$p-font-sizes: (
  null  : (15px, 1.3),
  small : 16px,
  medium: (17px, 1.4),
  900px : 18px,
  large : (19px, 1.45),
  1440px: 20px,

Although line-height values can be defined using any valid CSS unit (percentages, pixels, ems, etc.), “unitless” values are recommended and preferred.

We then modify the mixin to include line height when generating the CSS. We do it using the nth SASS function as it allow us to get a given element in a list, in this case the second element that correspond to line-height.

In order to make sure that there is a value for our line-height attribute, we test if the element in the map has more than one value (its length is greater than 1) and only add line-height if this is true.

@mixin font-size($fs-map, $fs-breakpoints: $breakpoints) {
  @each $fs-breakpoint, $fs-font-size in $fs-map {
    @if $fs-breakpoint == null {
      @include make-font-size($fs-font-size);
    @else {
      // If $fs-font-size is a key that exists in
      // $fs-breakpoints, use the value
      @if map-has-key($fs-breakpoints, $fs-breakpoint) {
        $fs-breakpoint: map-get($fs-breakpoints, $fs-breakpoint);
      @media screen and (min-width: $fs-breakpoint) {
        @include make-font-size($fs-font-size);

// Utility function for mixin font-size
@mixin make-font-size($fs-font-size) {
  @if type-of($fs-font-size) == "list" {
    font-size: nth($fs-font-size, 1);
    // If $fs-font-size is a list, include
    // both font-size and line-height
    @if (length($fs-font-size) > 1) {
      line-height: nth($fs-font-size, 2);
  @else {
    font-size: $fs-font-size;

The mixin checks to see whether the value of the key in the font-sizes map is a list as opposed to a font-size value. If it’s a list, then it gets the correct value from the list by index value, with the help of the nth function. It assumes that the first value is the font size and the second is the line height. Let’s see it in action:

p {
  @include font-size($p-font-sizes);

The result looks like this:

/* line 52, /Users/carlos/code/docs/maps-typography.scss */
p {
  font-size: 15px;
  line-height: 1.3; }

  @media screen and (min-width: 480px) {
    p {
      font-size: 16px; }

  @media screen and (min-width: 700px) {
    p {
      font-size: 17px;
      line-height: 1.4; }

  @media screen and (min-width: 900px) {
    /* line 52, /Users/carlos/code/docs/maps-typography.scss */
    p {
      font-size: 18px; }

  @media screen and (min-width: 1024px) {
    /* line 52, /Users/carlos/code/docs/maps-typography.scss */
    p {
      font-size: 19px;
      line-height: 1.45; }

  @media screen and (min-width: 1440px) {
    /* line 52, /Users/carlos/code/docs/maps-typography.scss */
    p {
      font-size: 20px; }

/*# */

Moving forward

In and of itself these maps are pretty good. To enhance them we can do one of the following

  • Add other attributes to the p-font-size map to represent attributes like word or character spacing, font stretching and other attributes that we want to change for media queries
  • Add other maps equivalent to p-font-size for other elements that need to change based on media queries
  • Build more complex maps that would include values for all the elements we want to change in a media query (such as paragraph, headings, line height and others) and then modify the mixin to handle the new values and, maybe, define the mixin at the top of the style sheet

Links and resources


Multicolumn layouts

CSS 3 allows you to create multi column layouts without cheating. According to the feature is supported to some degree by all browser vendors. We’ll explore some of the things you can do with columns and where the limitations are.

Please note that these examples use -moz and -webkit prefixes (for Chrome). To make sure the column examples work when you make changes you have to change all three values (prefixed and unprefixed.) This PITA makes columns another great candidate for autoprefixer or a SASS mixin.

Finally, because this is still a work in progress, some aspects of the spec is not implemented in all browsers. If this is an issue for you please consider using polyfills.

Creating multi column text: counting columns

The easiest way to work with columns is to tell CSS how many columns you want using the (prefixed) column-count property. This will tell the bowser how many columns to use. It will stick to that number of columns no matter what. They will be as wide or narrow as they need to be but the browser will always honor the number of clumns you tell it to use.

[codepen_embed height=”665″ theme_id=”2039″ slug_hash=”oXexXr” default_tab=”result” user=”caraya”]See the Pen Counting Columns by Carlos Araya (@caraya) on CodePen.[/codepen_embed]

Creating multi column text: counting width

The opposite effect is to use the (also prefixed) column-width property. Where column count takes a single integer without unit as its value, column-width takes a value with unit (like the 150px used in CSS Example 12-2) and will create as many columns of that width as there is space available. Contrast CSS Example 12-1 and 12-2. Where 12-1 sticks to the two columns, 12-2 creates as many 150px columns as it can with the space available. Try narrowing the window and see what happens in example 12-2… the number of columns will shrink a the space available decreases.

[codepen_embed height=”671″ theme_id=”2039″ slug_hash=”NqvNGj” default_tab=”result” user=”caraya”]See the Pen Measuring Columns Width by Carlos Araya (@caraya) on CodePen.[/codepen_embed]

Creating multi column text: the shorthand method

Some times I’m lazy and I want to just make columns work. Fortunately there is a shorthand syntax for column-width and column-count. It’s just columns. Examples of legal values taken from the CSS3 colmn module specification:

body {
  columns: 12em;      /* column-width: 12em; column-count: auto */
  columns: auto 12em; /* column-width: 12em; column-count: auto */
  columns: 2;         /* column-width: auto; column-count: 2 */
  columns: 2 auto;    /* column-width: auto; column-count: 2 */

As we can see it’s either a column-count or column-width, not both.

Column Gap

In both examples, the browser took it upon itself to create a gap between columns. In this case it was OK but it is not always the case. Fortunately the multi column spec gives you the ability of specifying a gap between the columns of your text.

[codepen_embed height=”675″ theme_id=”2039″ slug_hash=”RPZarP” default_tab=”result” user=”caraya”]See the Pen CSS Column Gap by Carlos Araya (@caraya) on CodePen.[/codepen_embed]

As you can see in the examples, the further apart we put the columns the easier each column it is to read but we get a smaller space to work with the overall text content.

[codepen_embed height=”640″ theme_id=”2039″ slug_hash=”gpxrMM” default_tab=”result” user=”caraya”]See the Pen CSS Column Gap – 4em by Carlos Araya (@caraya) on CodePen.[/codepen_embed]

Column Rules

In this context, rules are vertical lines between the columns to help differentiate the columns and prevent runon text. We can combine this with gutter/gap as in example 12-4 to create a more pleasing reading experience.

[codepen_embed height=”527″ theme_id=”2039″ slug_hash=”pJryEa” default_tab=”result” user=”caraya”]See the Pen Columns with rules between columns by Carlos Araya (@caraya) on CodePen.[/codepen_embed]

Spanning Columns

There are times when it’s nice to have an element (a div that holds byline information, for example) span the full width of our content area without regard to the number of columns. CSS Columns module provides the column-span rule to do just that.

This is where we see the first deviation from the specification. According to MDN, Firefox does not support column-span at all, it displays the content in its own column regardless of the settings authors choose.At least the result is not too bad…

[codepen_embed height=”527″ theme_id=”2039″ slug_hash=”mJMPOP” default_tab=”result” user=”caraya”]See the Pen Spanning Columns with CSS by Carlos Araya (@caraya) on CodePen.[/codepen_embed]

Filling Columns

So far columns are filled unevenly in all our examples. The right most column is shorter (sometimes considerably so.) The column-fill property will, when supported, make all the columns even in length. Currently only firefox will support the column-fill property.

[codepen_embed height=”675″ theme_id=”2039″ slug_hash=”XbadMo” default_tab=”result” user=”caraya”]See the Pen Column Fill by Carlos Araya (@caraya) on CodePen.[/codepen_embed]

Column Breaks

One of the most complex aspects of working with multi column content is how to prevent breaks inside, before or after a given piece of text. It gets even more complex when we factor columns into the mix. We’ll explore how to make sure that breaks work and that they actually do what we want them to:

In this case we’ll make the title h2 element stand alone in its own column and move the body text to the right and keep in the two column format. In the older days you’d accomplish this with table-based layouts but now it can be done using only CSS in bowsers that support it.

[codepen_embed height=”675″ theme_id=”2039″ slug_hash=”pJryPV” default_tab=”result” user=”caraya”]See the Pen CSS Column Break – Take 1 by Carlos Araya (@caraya) on CodePen.[/codepen_embed]

This is easy but it gets more complicated when we look at other values for break-before, break-after and break-inside that describe whether we should break before the element, after the element or inside the element. We’ll try another example where we’ll tell the browser to explicitly break after a paragraph… the results may not be what you’d expect.

I assumed, incorrectly as it turns out, that the break would still keep the content inside the parent’s container but as you can see it did not. In order to get the effect I wanted I had to provide smaller gap between columns and give different break styles to even and odd paragraphs. The second try looks better but it is brittle… although my tests have worked consistently I keep thinking there may be a combination of browser width where this will break.

[codepen_embed height=”521″ theme_id=”2039″ slug_hash=”aOyNwx” default_tab=”result” user=”caraya”]See the Pen CSS Column Break – Take 3 by Carlos Araya (@caraya) on CodePen.[/codepen_embed]

Mixins and Autoprefixer

If you’re a SASS monkey then you can use a mixin like the one below to work with columns. The mixing makes it easier for you to work with prefixes by abstracting the prefixes and, where it makes sense, providing sensible defaults.

@mixin column-attribs ($cols, $gap, $fill: balance, $span: none){
  /* How many columns? */
  -moz-column-count: $cols;
  -webkit-column-count: $cols;
  column-count: $cols;
  /* Space between columns */
  -moz-column-gap: $gap;
  -webkit-column-gap: $gap;
  column-gap: $gap;
  /* How do we fill the content of our columns, default is to balance */
  -moz-column-fill: $fill;
  -webkit-column-fill: $fill;
  column-fill: $fill;
  /* Column span, defaul is not to span columns */
  -moz-column-span: $span;
  -webkit-column-span: $span;
  column-span: $span;
.col2 {
  width: 100%;
  @include column-attribs (2, 20px);

And the result looks like this:

.col2 {
  width: 100%;
  /* How many columns? */
  -moz-column-count: 2;
  -webkit-column-count: 2;
  column-count: 2;
  /* Space between columns */
  -moz-column-gap: 20px;
  -webkit-column-gap: 20px;
  column-gap: 20px;
  /* How do we fill the content of our columns, default is to balance */
  -moz-column-fill: balance;
  -webkit-column-fill: balance;
  column-fill: balance;
  /* Column span, defaul is not to span columns */
  -moz-column-span: none;
  -webkit-column-span: none;
  column-span: none;

I understand that there are designers who are not comfortable with SASS/SCSS. For those people I think the best solution is to use automatic prefixer tools, either directly or as part of an automated workflow. I’ve chosen to use autoprefixer in a Grunt workflow.

I won’t go into details about the Grunt workflow but if you’re familiar with Grunt it shouldn’t be too hard to add Autoprefixer to the process. If you want to look at a (somewhat disorganized) reference you can look at the Gruntfile I created for this project.

Links and Resources

From MDN


Legal Issues

Unless you own the typeface or it is licensed through Google Fonts or another free service, you will have to pay for the font and be subject to whatever restrictions the EULA (End User License Agreement) specifies. This may be a problem when the foundry decides that you don’t need a TTF format for the font you just purchased or when you’re not allowed to generate an SVG version of your font to use with older iOS devices.

I do not mean to say or imply that you should break your license agreement. Quite the opposite; we should be thankful that foundries and font creators have decided that the bennefits outweigh the risks when it comes to online fonts. It is not a perfect solution and we need to keep working at making it better.

I recently asked a foundry on twitter why didn’t they offer certain font formats (the font purchase for web includes EOT and WOFF with TTF as a mockup font) there was no TTF, OTF, SVG or WOFF2 available for me to use. The exchange turned ugly and, from my perspective, ignored completely the fact that I had purchased a license to the font and was in my right to request additional font types to accommodate my user base… they indicated that they could do it in a special (as in more expensive) license and that they know best what formats of their fonts I will need for my clients based on general usage or that none of his big clients have made the request for TTF so it must mean that there is no need for the format anywhere.

Font Licensing is like DRM encumbered music. You have the medium but do not own the actual font. As far as I understand it the foundry can end your license for any reason and you’re not allowed to make changes to suit the fonts to our needs rather than believe the foundries have the answers for everything. Things changed for music files and I can only hope that the same changes will happen with fonts and font licensing.

Open Source fonts

So, if proprietary fonts can become such a nightmare will open source fonts work any better?

The answer, as usual, is it depends.

There are awesome fonts with open source licenses. Fonts like Raleway, Roboto, Gentium and Fira Sans are good open source solutions that have liberal open source licenses (either SIL font license or Mozilla Public License) but, as with everything else related to type, you need to test your chosen fonts with your content and make sure that it works for your particular project and the (human) languages your document has to support.

There are also purpose specific fonts like Adobe Source Code Pro or Deja Vu Mono that you can use in user interfaces or code heavy environments. I use Source Code Pro for all code examples in this project.

A good starting point, if you’re looking for free/open source fonts is the free font list from Font Squirrel. You can look at the fonts and download them to test on your local system before you decide if you want to use the font. You can also check sites like Fonts in Use to see other uses of the fonts you’re evaluating.

example screenshot from with samples of sites/apps using Roboto as their font
Example screenshot from with samples of sites/apps using Roboto as their font

Example from Fonts in Use with samples of sites/apps using Roboto as their font

For the most part the free fonts in Font Squirrel can be used with the Webfont Generator. This tool allows you to upload fonts (for which you have license and/or permission) to generate the formats needed to support all browsers (including SVG for all iOS and TTF for older versions of browsers.)


Unicode and multilingual support

Unicode is an ISO international standard (ISO/IEC 10646) for the consistent encoding, representation, and handling of text in most of the world’s writing systems. It answers the question: How do I combine multiple languages in a single document?

In the past we had different encodings for different language codified in the ISO/IEC 8859 series of standards. English, for example, uses ISO/IEC 8859-1 which is mostly ASCII. This is not sufficient to work with eastern European languages that use additional symbols accents and punctuation to fully express the language. See the Wikipedia entry for ISO 8859 for more details regarding what languages are supported on each section of the standard.

HTML and XHTML both come with a predefined set of entities to handle unicode characters using a name (for example using Υ for the uppercase Upsilon greek letter.) But that is still no guarantee that your chosen font will have the glyphs matching the character you need.

I’ve had a discussion in the XML Content/InDesign Publishing Linked in Group and, as part of my research, discovered that:

  • The level of unicode glyph support depends on the fonts available in the OS
  • Specific Unicode glyphs may not be available in all platforms

In my opinion he best solution is still to use web fonts you know have all the characters your text uses and you have tested with your content. This is doubly important when looking at the glyphs that appear on your document… we need to make doubly sure that whatever glyphs you use are available in the typeface you’ve selected.

To make things easier on yourself, you can also subset the fonts you’re using so that only the characters you need will be added to your font; This is particularly useful in multibyte characters like Japanese, (traditional) Chinese or Korean where there are at least several hundreds, if not thousands, of glyphs.

When I want to use font subsets my favorite tool is Font Squirrel’s Webfont generator. I’ve documented how I use the generator and other possible subsetting solutions so I won’t go into too much detail of the mechanics… but I will cover the basics just to be sure.

Font Squirrel has three options for subsetting fonts. We will work with custom options because they provide the most flexible approach

Font Squirrel Font Subset Options when using custom subsetting
Font Squirrel Font Subset Options

You can subset by character type, language, unicode table, single characters or, if you know what you’re doing by Unicode Ranges. The last option is only good if you know the exact range or ranges of characters that you need to support and the preview may show you that your chose font doesn’t support the characters you need.