Typography

Unicode characters in CSS generated content

I ran across an issue today where I had set some generated content to an unusual character (an open quotation mark), but the compiled and minified CSS served by Drupal was showing me the wrong characters. It was likely caused by character encoding getting screwed up somewhere along the line. The solution was to specify the Unicode character I wanted in the format seen in the code block below, as demonstrated in the source link below and this Stack Overflow answer.

Code language: CSS

p:before {
  content: "\201C";
}

Text stroke with CSS

There is a non-standard way to stroke HTML text (SVG has a standard way). It’s not particularly new. There are -webkit- and -moz- prefixes for it. Jen Simmons recently posted about it, with an example:

Code language: CSS

span {
     -moz-text-fill-color: #fde;
  -webkit-text-fill-color: #fde;
     -moz-text-stroke-color: #666;
  -webkit-text-stroke-color: #666;
     -moz-text-stroke-width: 2px;  
  -webkit-text-stroke-width: 2px;
}

And she’s right:

This CSS isn’t fully-baked or fully-supported. But it’s good enough to be used today, especially since it’s simply offering a visual enhancement. It’s not mission critical to making a website usable.

I’d only perhaps add that if you were going to do something like add a stroke around white text, you could wrap it in a @supports to be extra sure it’ll be OK (just in case a browser exists that supports text-fill-color but not text-stroke-color) :

Code language: CSS

@supports 
  ((-webkit-text-stroke-color: #666)
  and
  (-webkit-text-fill-color: white))
  or
  ((-moz-text-stroke-color: #666)
  and
  (-moz-text-fill-color: white)) {
  span {
       -moz-text-fill-color: white;
    -webkit-text-fill-color: white;
       -moz-text-stroke-color: #666;
    -webkit-text-stroke-color: #666;
       -moz-text-stroke-width: 2px;  
    -webkit-text-stroke-width: 2px;
  }
}

See the link for more tricks, and the comments make a good point that you don’t have to use text-fill-color if you’re using @supports: just use color.

Dealing with long words in CSS

Code language: CSS

.hyphenate {
  overflow-wrap: break-word;
  word-wrap: break-word;
  -webkit-hyphens: auto;
  -ms-hyphens: auto;
  -moz-hyphens: auto;
  hyphens: auto;
}

This solution will show hyphens for every browser supporting it and will break lines in every other browser – perfect. [Although] I have tested this solution in 26 different browsers I am still not sure this will work 100% – if you find any edge case please let me know.

Tuna - Typeface

Tuna is simply a contemporary body text font. It is contemporary, meaning the merge of charming broad-nibbed calligraphic style with optimized legibility on screen – showing that the roots of writing and typesetting are still in charge when reading “Anna Karenina” on a kindle till 4 o’clock in the morning.

Tuna has a natural fit for cross-media use because the design is based on forms characterized by different conditions of consistency, stability and good legibility. Well defined shapes and distinctive details only become apparent when used in larger sizes, making Tuna a true all-rounder.

With more than 700 glyphs in 10 styles created with a maximum of consideration, it has all the qualities of a modern OpenType font serving the needs of [today’s] communication.

Typefaces: NPM packages for Open Source typefaces - making it easier to self-host webfonts

Why

  • Self-hosting is significantly faster. Loading a typeface from Google Fonts or other hosted font service adds an extra (blocking) network request. In my testing, I’ve found replacing Google Fonts with a self-hosted font can improve a site’s speedindex by ~300 miliseconds on desktop and 1+ seconds on 3g. This is a big deal.
  • Your fonts load offline. It’s annoying to start working on a web project on the train or airplane and see your interface screwed up because you can’t access Google fonts. I remember once being in this situation and doing everything possible to avoid reloading a project as I knew I’d lose the fonts and be forced to stop working.
  • Go beyond Google Fonts. Some of my favorite typefaces aren’t on Google Fonts like Clear Sans, Cooper Hewitt, and Aleo.
  • All web(site|app) dependencies should be managed through NPM whenever possible. Tis the modern way.

What

Each typeface package ships with all the necessary font files and css to self-host an open source typeface.

All Google Fonts have been added as well as a small but growing list of other open source fonts. Open an issue if you want a font added!

How

Couldn’t be easier. This is how you’d add Open Sans.

npm install --save typeface-open-sans

Then in your app or site’s entry file.

require("typeface-open-sans")

And that’s it! You’re now self-hosting Open Sans!

It should take < 5 minutes to swap out Google Fonts.

Typeface assumes you’re using webpack with loaders setup for loading css and font files (you can use Typeface with other setups but webpack makes things really really simple). Assuming your webpack configuration is setup correctly you then just need to require the typeface in the entry file for your project.

Many tools built with webpack such as Gatsby and Create React App are already setup to work with Typefaces. Gatsby by default also embeds your CSS in your <head> for even faster loading.

If you’re not using webpack or equivalent tool that allows you to require css, then you’ll need to manually integrate the index.css and font files from the package into your build system.

Align SVG Icons to Text and Say Goodbye to Font Icons

In building my own SVG-based icon system, I’ve run into (and mostly solved) these same issues.

Why should I care about how SVGs are styled?

If you’ve ever used font icon systems like Font Awesome you know how easy it is to add to a project and get going. The icons align to your text easily and can be modified by changing the font-size of the element. There is no clearly defined way for styling an SVG icon system. I’ve seen some systems custom style and place each icon in their library. This route sounds painfully unsustainable if you utilize more than 15 icons in your UI.

Can it scale like an icon font?

To emulate the font-size scaling I use a class to set the SVG size to 1em by 1em. This means that if your title text is a 48px font size the SVG will be 48px by 48px. This works nicely for components like buttons and inputs when you want to add an icon. This also empowers you to pass a font size to the element via modifier class or inlined CSS. Using font-size to determine the size of your icon makes your life a little easier.

Code language: CSS

.svg-icon svg {
  height: 1em;
  width: 1em;
}

My SVG won’t align to with my text. How do I fix this?

The downside is that a DOM element on it’s own doesn’t align nicely with text. To counter this I wrote the .svg-icon handler class to hold the size and be relative positioned so that I can absolute position the SVG inside of it. Moving the icon down by “-0.125em” allows me to pull down the icon by 12.5% at any scale.

The first example shows that DOM elements align to the baseline of text by default. However, since our icon is already properly scaled to consider the baseline, we need to pull it down for the baseline to truly align. At this size the distance is 6px away, 6px/48px = ⅛ or 12.5%. In the second example, pulling the icon down by -0.125em places the icon onto the proper baseline of the text.

Code language: CSS

.svg-icon {
  display: inline-flex;
  align-self: center;
  position: relative;
  height: 1em;
  width: 1em;
}
 
.svg-icon svg {
  height:1em;
  width:1em;
}
 
.svg-icon.svg-baseline svg {
  bottom: -0.125em;
  position: absolute;
}

Vertical viewport units are unreliable on mobile

When I was first styling Resilient Web Design, I made heavy use of vh units. The vertical spacing between elements—headings, paragraphs, images—was all proportional to the overall viewport height. It looked great!

Then I tested it on real devices.

Here’s the problem: when a page loads up in a mobile browser—like, say, Chrome on an Android device—the URL bar is at the top of the screen. The height of that piece of the browser interface isn’t taken into account for the viewport height. That makes sense: the viewport height is the amount of screen real estate available for the content. The content doesn’t extend into the URL bar, therefore the height of the URL bar shouldn’t be part of the viewport height.

But then if you start scrolling down, the URL bar scrolls away off the top of the screen. So now it’s behaving as though it is part of the content rather than part of the browser interface. At this point, the value of the viewport height changes: now it’s the previous value plus the height of the URL bar that was previously there but which has now disappeared.

[…]

In my initial implementation of Resilient Web Design, the one where I was styling almost everything with vh, the site was unusable. Every time you started scrolling, things would jump around. I had to go back to the drawing board and remove almost all instances of vh from the styles.

Google Noto Fonts

When text is rendered by a computer, sometimes characters are displayed as “tofu”. They are little boxes to indicate your device doesn’t have a font to display the text.

Google has been developing a font family called Noto, which aims to support all languages with a harmonious look and feel. Noto is Google’s answer to tofu. The name noto is to convey the idea that Google’s goal is to see “no more tofu”. Noto has multiple styles and weights, and is freely available to all.

`font-display`, a CSS alternative to JavaScript font loading

The font-display property is landing in browsers, and this is a great introduction to using it:

If you don’t know which option to use, then go with swap. Not only does it provide an optimal balance between custom fonts and accessibility of content, it provides the same font loading behavior that we’ve relied on JavaScript for. If you have fonts on the page that you’d like to have load, but could ultimately do without, consider going with fallback or optional when using font-display.

Until it’s more widely supported, you can continue to use a JavaScript solution, but even then you can feature detect first:

Code language: JavaScript

if ("fontDisplay" in document.body.style === false) {
  /* JavaScript font loading logic goes here. */
}