Introduction
Lately I've been reading a bit more around CSS typography.
One of the most discussed issues is font sizing: whilst sizing in pixels returns a more predictable output - and also makes a whole lot of sense for web rendering engines - it's not very accessible because it represents a fixed output size and some browsers (See IE 9 =<) won't allow scaling them for readability.
A bit of history
Let's start by saying that most of the web-safe fonts that we're familiar with (See Arial, Verdana, Tahoma, ..) have been distributed/partially produced by Microsoft in the '90s and were optimised for the screen, and especially to be readable in small sizes.
Although these fonts came before Apple and Microsoft developed parallel technologies to imitate Adobe's System engineers PostScript, (Coming from Xerox PARC) which allowed higher-res and smoother font rendering (Screen fonts where - at the time - rendered from fixed-sizes low-res bitmaps).
Microsoft and Apple then adopted TrueType, which was developed by Apple's engineers and is still the most popular format today - starting an open process of vectorialisation of digital typography.
Even though this doesn't seem to directly affect web it helps understanding why browsers are still carrying many limitations on the way they handle vector-based fonts.
Even after the invention of anti-aliasing and the conversion of bitmap webfonts into TrueType, the way most browsers interpret the rendering is still related to pixel values: IE, Opera and Safari don't swap the rendering size under pixel decimal values - they will produce a floored size as result.
This may sound obvious - of course you can't render parts of a pixel in a bitmap font logic - but it's also useful to understand the problems in using other measures than pixels in web.
Units of measurement
CSS of course offers many other units of measure (em, ex, pc, pt, cm, in - recently rem) even though - except for Ems - none of them is recommended to be used, mostly because they tend to not be supported by browsers or to just not make any sense in web development.
Ems have been considered to be the best practice since fluid layouts became popular around the web. This is because their rendering size is relative to the parent element.
This can create confusion when moving elements around, and in order to make an actual difference in the rendering it requires calculating every Em size in base of the px size that needs to be outputted.
Even though they are a - technically speaking - massive pain in the ass, they allow IE users enlarging and stretching text for readability - which is a big win-win for an accessible website.
Using Rems
In recent times it became quite popular to use Rems (Root Ems) which do not vary font-size when nested but will still scale on every browser.
Also, by setting the root size to 62.5% you will have simpler maths to translate Rems in pixels (1.2rem will match 12px, and so on) making it more intuitive to size text thinking about the result in pixels.
Headings and semantics
Another problem in web typography is that sometimes you may find yourself - for design reasons - having to style elements of different semantic level to look like headers of some sort - or make H2's look like H1's and so on.
When defining font-sizes for the headings it becomes then quite useful to also create a set of classes matching these styles, which will then be re-applied on other elements.
Anyone uses a different naming convention for that - in my case, I prefer to keep it simple and just go for '.h1, .h2, ..'.
Considered the problems listed above I have developed a very simple approach to size and style using LESS mixins and default definitions that I add to most of my projects.
These help me to easily configure the primitives of typography in a quick and efficient way.
Helping it out with LESS
I like having a small set of variables that define font-sizes, the main grid unit (From which I get spacings and sizes) and type colors in my main file and then import a very basic LESS file which contains definitions based on it.
This is what the configuration may look like:
main.less
// [..]
// ----------------------------------------------------------------------------
// variables > type
// ----------------------------------------------------------------------------
@type-root: 62.5%;
@type-size-large: 17;
@type-size-body: 15;
@type-size-small: 13;
@type-size-h1: 24;
@type-size-h2: 20;
@type-size-h3: 18;
@type-size-h4: 16;
@type-size-h5: 14;
@type-size-h6: 12;
@type-face-header: Helvetica, Arial, sans-serif;
@type-face-body: Helvetica, Arial, sans-serif;
@type-face-components: @type-face-header;
@type-size-components: 12;
@type-face-inputs: @type-face-components;
@type-size-inputs: 15;
@type-color-inputs: @color-type-grey;
// ----------------------------------------------------------------------------
// variables > colors > general
// ----------------------------------------------------------------------------
@color-highlight: #ed1457;
// ----------------------------------------------------------------------------
// variables > colors > type
// ----------------------------------------------------------------------------
@color-type-grey-light: #bfbfbf;
@color-type-grey: #6e6e6e;
@color-type-grey-dark: #333;
@color-type-body: @color-type-grey;
@color-type-header: @color-type-grey-dark;
@color-type-link: @color-type-highlight;
@color-type-highlight: @color-highlight;
@color-type-link-hover: lighten(@color-type-link, 20%);
@color-type-error: #ef4437;
@color-type-success: #83a355;
@color-type-error: #d25534;
// ----------------------------------------------------------------------------
// variables > units
// ----------------------------------------------------------------------------
@unit: 10px;
@half-unit: @unit / 2;
@dub-unit: @unit * 2;
@tri-unit: @unit * 3;
@quad-unit: @unit * 4;
// [..]
And this is what the typography file 'core' may look like:
typography.less
// [..]
.type-size(@size) {
font-size: @size * 1px;
font-size: @size * 1rem / 10;
}
.type-padding-top(@value) {
padding-top: @value * 1px;
padding-top: @value * 1rem / 10;
}
.type-padding-bottom(@value) {
padding-bottom: @value * 1px;
padding-bottom: @value * 1rem / 10;
}
.type-padding(@val-top, @val-bottom) {
.type-padding-top(@val-top);
.type-padding-bottom(@val-bottom);
}
.type-margin-top(@value) {
margin-top: @value * 1px;
margin-top: @value * 1rem / 10;
}
.type-margin-bottom(@value) {
margin-bottom: @value * 1px;
margin-bottom: @value * 1rem / 10;
}
.type-margin(@val-top, @val-bottom) {
.type-margin-top(@val-top);
.type-margin-bottom(@val-bottom);
}
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
font-family: @type-face-header;
color: @color-type-header;
font-weight: 100;
margin-top: 0;
font-weight: bold;
}
h1, .h1 {
.type-size(@type-size-h1);
text-align: center;
}
h2, .h2 {
.type-size(@type-size-h2);
}
h3, .h3 {
.type-size(@type-size-h3);
}
h4, .h4 {
.type-size(@type-size-h4);
}
h5, .h5 {
.type-size(@type-size-h5);
}
h6, .h6 {
.type-size(@type-size-h6);
}
// [..]
You can find a GitHub repo containing more extensive set of LESS styles and mixins to frame your typography here »