When building a web site, one of the places I like to start is with the typography of the site. I use no more than six font-sizes. I would argue that even six is too many, but HTML allows for a total of six heading levels: h1–h6. Therefore, we’ll account for those headings but cap it off there. There are deeper design concerns outside of writing SMACSS or OOCSS, but I’ll address that at another time.

Headings

Based off the sizes we established for the headings in our HTML document (h1–h6), we can turn these into sibling modules. Remember that sibling modules have no common base class, but share a common purpose. Using the sizes and hierarchy of h1–h6, I might write:


.display-1 {
  font-size: 32px;
  line-height: 36px;
  font-weight: bold;
}

I have written three property/value pairs for this sibling module: font-size, line-height, font-weight. This is the bare minimum of what we need to apply the appearance of a heading to another element.

Why would I do that? Situational context. You may find an instance where the semantically correct element in the markup is not the same as its visual requirement. You would use this class to remedy that. Also, per the HTML5 Spec, you could use multiple instances of an h1 on the same page by using it within sectioning elements. This class would help give control over the correct appearance.

Body

We would finish out the remaining heading siblings in this fashion from 1–6. We might also consider an additional set of classes intended for body text. The font-size and line-height would be the same as their .display-(n) counterparts, but the font-weight would be normal. Something like:


.text-1 {
  font-size: 32px;
  line-height: 36px;
  font-weight: normal;
}

This helps keep our body text hierarchy in congruence with our heading hierarchy and maintain a standard of type size throught the site or application.

Naming

You maybe wondering why I chose those particular names. As I mentioned previously, the way we name modules is of high importance for their reusability. Naming can be difficult and requires heavy consideration. For these two examples, I deferred to the language of typography.

Display type is the name given to type that stands apart from the body text. Headlines, section headings, subheads would all be examples of where you would use display type. For these same reasons, I chose the name .display for this set of sibling modules. It is not coupled to HTML semantics, but maintains typographical meaning.

Likewise, text type refers to type that is intended for long form reading, e.g., the body copy. With the same rationale as above, I chose .text for the name of this set of sibling modules.

Going one step further, I normally reduce the class names down for the sake of brevity. So, .display-1 becomes .dsp-1 and .text-1 becomes .txt-1 (I spend a lot of time researching word abbreviations for class names). Just make sure that the rest of the team can easily understand the class name without much thought. The benefit is faster development time in the long run. It also helps break the association of .display the class name from display: the CSS property.

Utility

After establishing the overall hierachy, we can also author some helper classes, or utility classes, that we can leverage from time to time when semantic considerations are neutral or unbeneficial.

For example, we may create another series of sibling modules that address text alignment:


.text-l {
  text-align: left;
}

.text-r {
  text-align: right;
}

.text-c {
  text-align: center;
}

.text-j {
  text-align: justified;
}

This may feel a bit like unitasking (and it is), but I have found it to be extremely helpful. If you start to see a visual pattern arise that you can anchor semantic value to, then you can always refactor and associate the style to a module or component.

The idea of utility classes is not uniquely my own. Nicolas Gallagher has created SUIT utilities which demonstrate similar CSS considerations. The same can be found here in the OOCSS framework.

Conclusion

This whole bit on typography doesn’t require much of the Rough, Refactor, Repeat pattern because many of the decisions have already been made in the Base Rules. What we are doing is extending the Base Rules into modules. It’s good as a warm up. Now, we’re ready to get our hands dirty with components and modules!

Cheers!


Subscribe


← Back to Notes