Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/netlify/postcss-fout-with-a-class
Rewrite all selectors that will trigger a font load to be scoped under a class
https://github.com/netlify/postcss-fout-with-a-class
Last synced: 16 days ago
JSON representation
Rewrite all selectors that will trigger a font load to be scoped under a class
- Host: GitHub
- URL: https://github.com/netlify/postcss-fout-with-a-class
- Owner: netlify
- Archived: true
- Created: 2017-03-12T18:24:39.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2020-05-26T18:03:53.000Z (over 4 years ago)
- Last Synced: 2024-07-31T18:24:51.627Z (3 months ago)
- Language: JavaScript
- Size: 9.77 KB
- Stars: 28
- Watchers: 4
- Forks: 2
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# FOUT with a Class in PostCSS
At [Netlify](https://www.netlify.com) we wanted to speed up our initial page loads, and saw that font-loading
was the trickiest part of our critical path.Font-loading in modern browsers is somewhat of a dark art and can be hard to setup and configure properly.
One of the best current approaches is [FOUT with a class](https://www.zachleat.com/web/comprehensive-webfonts/#fout-class). This technique takes advantage of
the fact that the browser won't start loading fonts before they are applied to some DOM element on the page.We can combine this with service workers or session storage to make sure we lazy load fonts on the first view
to avoid blocking the initial critical rendering path, but load font instantly from cache so we avoid any
flash of un-styled text on subsequent page loads.The flip side of that approach is that it requires a lot of discipline in the CSS to avoid accidentally apply
a font-family to an element without scoping it under a relevant class.## PostCSS to the rescue!
This PostCSS plugin will handle all of that discipline for you, by detecting all fonts and moving them to scoped
selectors.Example CSS
```css
@font-face {
font-family: 'Mija';
src: url('/fonts/MijaBold/Mija_Bold-webfont.woff2') format('woff2');
}
.fancy-headline h1 {
font-size: 10rem;
font-family: 'Mija';
}
```Example PostCSS setup:
```js
import postcss from "postcss-gulp";
import foutWithAClass from "postcss-fout-with-a-class";gulp.task('css', () => (
gulp.src('./src/css/*.css')
.pipe(postcss([foutWithAClass({families: ['Mija'], className: 'wf-loaded'})]))
.pipe(gulp.dest('./dist/css'));
));
```CSS output:
```css
@font-face {
font-family: 'Mija';
src: url('/fonts/MijaBold/Mija_Bold-webfont.woff2') format('woff2');
}
.fancy-headline h1 {
font-size: 10rem;
}
.wf-loaded .fancy-headline h1 {
font-family: 'Mija';
}
```## Taking advantage of this
A simple way to take advantage of this is with a service worker. I recommend using the awesome [sw-toolbox](https://github.com/GoogleChrome/sw-toolbox) to simplify that. Here's an example
service worker that will load your fonts straight from the cache after initial load.```js
import toolbox from 'sw-toolbox';self.addEventListener('install', (event) => event.waitUntil(self.skipWaiting()));
self.addEventListener('activate', (event) => event.waitUntil(self.clients.claim()));toolbox.router.get('/fonts/*', toolbox.cacheFirst);
```And a quick way to use this to either start loading fonts after the onload event, or loading straight
away once your service worker is active:```html
Font Loading Demo
if ('serviceWorker' in navigator && navigator.serviceWorker.controller !== null && navigator.serviceWorker.controller.state === 'activated') {
document.querySelector("html").classList.add('wf-loaded');
} else {
document.addEventListener('load', function() { document.querySelector("html").classList.add('wf-loaded'); }, false);
}
A Fancy Headline
```