$30 off During Our Annual Pro Sale. View Details »
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Bulletproof Font Icons
Search
zachleat
May 27, 2014
Programming
19
2.9k
Bulletproof Font Icons
Originally presented at CSSConf 2014:
http://2014.cssconf.com/#zach
zachleat
May 27, 2014
Tweet
Share
More Decks by zachleat
See All by zachleat
NEJS CONF 2017 Interstitial Slides
zachleat
0
140
Credibility
zachleat
0
86
A Brief History of that Time You Used Web Fonts
zachleat
7
1.4k
The Performance and Usability of Font Loading (Velocity NYC 2015)
zachleat
3
610
The Performance and Usability of Font Loading (Velocity Santa Clara 2015)
zachleat
27
4.6k
Performance and Responsive Web Design
zachleat
7
2k
Remodeling @font-face
zachleat
17
3.4k
How and Why I Built fontfamily.io
zachleat
2
1.5k
Impostor Syndrome
zachleat
1
430
Other Decks in Programming
See All in Programming
関数実行の裏側では何が起きているのか?
minop1205
1
650
Herb to ReActionView: A New Foundation for the View Layer @ San Francisco Ruby Conference 2025
marcoroth
0
250
社内オペレーション改善のためのTypeScript / TSKaigi Hokuriku 2025
dachi023
1
540
[堅牢.py #1] テストを書かない研究者に送る、最初にテストを書く実験コード入門 / Let's start your ML project by writing tests
shunk031
12
7k
dotfiles 式年遷宮 令和最新版
masawada
1
690
TypeScriptで設計する 堅牢さとUXを両立した非同期ワークフローの実現
moeka__c
6
2.9k
チームをチームにするEM
hitode909
0
250
Developing static sites with Ruby
okuramasafumi
0
190
WebRTC、 綺麗に見るか滑らかに見るか
sublimer
1
160
AIコーディングエージェント(Manus)
kondai24
0
150
Google Antigravity and Vibe Coding: Agentic Development Guide
mickey_kubo
2
150
How Software Deployment tools have changed in the past 20 years
geshan
0
28k
Featured
See All Featured
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
285
14k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
10
710
Statistics for Hackers
jakevdp
799
230k
The Invisible Side of Design
smashingmag
302
51k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.2k
Leading Effective Engineering Teams in the AI Era
addyosmani
8
1.3k
The World Runs on Bad Software
bkeepers
PRO
72
12k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
5.7k
Unsuck your backbone
ammeep
671
58k
Why You Should Never Use an ORM
jnunemaker
PRO
60
9.6k
The Art of Programming - Codeland 2020
erikaheidi
56
14k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
1
87
Transcript
N Bulletproof C E U R N
LET’S LEARN EVERYTHING ABOUT @FONT-FACE
@zachleat zachleat.com
None
If you wish to make a font icon from scratch,
you must first invent the universe. —Carl Sagan, probably https://www.flickr.com/photos/scott-s_photos/11763686274 “ ”
@Font-face THIS ONE WEIRD TRICK A G EN D A
CAT FANCY UNICODE LOADING.. . .. .
1997 @font-‐face
1995 <font>
None
@font-‐face
CSS3 CSS2.1 CSS2
@font-‐face { ! font-‐family: The Font that Could;
src:url('icanfont.ttf') format('truetype'), url('icanfont.woff') format('woff'); font-‐weight: normal; font-‐style: normal; ! }
@font-‐face { ! font-‐family: The Font that Could;
src:url('icanfont.ttf') format('truetype'), url('icanfont.woff') format('woff'); font-‐weight: normal; font-‐style: normal; ! }
@font-‐face { ! font-‐family: The Font that Could;
src:url('icanfont.ttf') format('truetype'), url('icanfont.woff') format('woff'); font-‐weight: normal; font-‐style: normal; ! }
David Hasselwoff USE WOFF
Woff caniuse.com 5.0! 6.0 7.0! 7.5!
WOFF BY ONE ERROR
Woff + TTF caniuse.com 5.0! 6.0 7.0! 7.5!
NEED IE8? Add EOT
@font-‐face { ! font-‐family: The Font that Could;
src:url('icanfont.eot?#iefix') format('embedded-‐opentype'), url('icanfont.ttf') format('truetype'), url('icanfont.woff') format('woff'); font-‐weight: normal; font-‐style: normal; ! }
Woff + TTF + EOT caniuse.com 5.0! 6.0 7.0! 7.5!
NEED Chrome + Windows? Add SVG http://www.fontspring.com/blog/smoother-web-font-rendering-chrome
34 8.1 WOFF SVG ISSU E XP
Woff + EOT + TTF + SVG https://code.google.com/p/chromium/issues/detail?id=137692 caniuse.com 5.0
7.0! 7.5! 6.0 6.0
@font-‐face { font-‐family: The Font that Could;
src:url('icanfont.eot?#iefix') format('embedded-‐opentype'), url('icanfont.ttf') format('truetype'), url('icanfont.woff') format('woff'), url('icanfont.svg#icanfont') format('svg'); font-‐weight: normal; font-‐style: normal; } W R O N G
@media (-‐webkit-‐min-‐device-‐pixel-‐ratio:0) { ! @font-‐face {
font-‐family: The Font That Could; src: url('icanfont.svg#icomoon') format('svg'); font-‐weight: normal; font-‐style: normal; } ! }
https://github.com/scottjehl/Device-Bugs/issues/43 ISSU E
None
@media (-‐webkit-‐min-‐device-‐pixel-‐ratio:0) and (min-‐resolution: .001dpcm) { !
@font-‐face { font-‐family: The Font That Could; src: url('icanfont.svg#icomoon') format('svg'); font-‐weight: normal; font-‐style: normal; } ! }
Supports -‐webkit-‐min-‐device-‐pixel-‐ratio Supports min-‐resolution Yes No Yes No
Woff + EOT + TTF + SVG https://code.google.com/p/chromium/issues/detail?id=137692 caniuse.com 5.0
7.0! 7.5! 6.0 6.0
WHEW.
A QUICK REVIEW
@font-‐face { font-‐family: The Font that Could;
src:url('icanfont.eot?#iefix') format('embedded-‐opentype'), url('icanfont.ttf') format('truetype'), url('icanfont.woff') format('woff'); font-‐weight: normal; font-‐style: normal; } ! @media (-‐webkit-‐min-‐device-‐pixel-‐ratio:0) and (min-‐resolution: .001dpcm) { ! @font-‐face { font-‐family: The Font That Could; src: url('icanfont.svg#icomoon') format('svg'); font-‐weight: normal; font-‐style: normal; } }
@font-‐face { font-‐family: The Font that Could;
src:url('icanfont.eot?#iefix') format('embedded-‐opentype'), url('icanfont.ttf') format('truetype'), url('icanfont.woff') format('woff'); font-‐weight: normal; font-‐style: normal; } ! @media (-‐webkit-‐min-‐device-‐pixel-‐ratio:0) and (min-‐resolution: .001dpcm) { ! @font-‐face { font-‐family: The Font That Could; src: url('icanfont.svg#icomoon') format('svg'); font-‐weight: normal; font-‐style: normal; } } REMOVE AFTER CHROME DIRECTWRITE
GO TO YOUR HAPPY PLACE
LET’s PUT THE @FONT-FACE BLOCK ON OUR WEB PAGE
None
NO FONT-FAMILY NO DOWNLOAD
34 28 9, 10, 11 20 6.1, 7 2.3, 4.1
7 8
body { font-‐family: My Icon Font, serif;
}
var b = document.body; ! b.style.fontFamily = "My Icon
Font";
@Font-face THIS ONE WEIRD TRICK A G EN D A
CAT FANCY UNICODE LOADING…
BASIC LATIN CODE POINT Arial Chunk Five x41 A A
x42 B B x43 C C x44 D D x45 E E
Higher UNICODE Ranges x2261 ≡ x2605 ˒ x2665 ♥ x2713
✓
Arial Chunk Five 0x1F300 0x1F302 0x1F350 Arial Chunk Five 0x1F300
0x1F302 0x1F350 EMOJI http://doeschromesupportemojiyet.com/ https://code.google.com/p/chromium/issues/detail?id=62435
None
CONSISTENCY
unicode.johnholtripley.co.uk
None
READ AS x2261 ≡ IDENTICAL TO x2605 ˒ BLACK STAR
or STAR x2665 ♥ HEART SUIT ACCESSIBILITY
None
PRIVATE USE AREA
YOUR ICON FONT HERE 0xe001 0xe002 0xe003 0xe004 PRIVATE USE
AREA
@Font-face THIS ONE WEIRD TRICK A G EN D A
CAT FANCY UNICODE LOADING…
https://www.flickr.com/photos/79157069@N03/11616536203/ OUR @FONT-FACE REQUEST LEAVES THE NEST
LOCAL FONT { @FONT-FACE {
None
FOIT Flash of Invisible Text
@FONT-FACE LOAD
https://twitter.com/aanand/status/465182499577286656
LOCAL FONT { @FONT-FACE {
FOUT Flash of UNSTYLED Text
3 S @FONT-FACE LOAD ABCDEFGH ABCDEFGH
3 S @FONT-FACE LOAD
https://twitter.com/raganwald/status/452092613529567233 Screenshot of GitHub
LOCAL FONT { @FONT-FACE {
Timeouts/CURFEWS 34 > 60 s 36 28 9, 10, 11
N/A 20 > 60 s 3 s 3 s 7 60 s 4.1 > 60 s * 6 > 60 s 60 s* 7
if font loads after 60 seconds SAFARI IGNORES IT 7
*Timeout ISSU E 7
WHAT HAPPENS WHEN A USER HITS THE STOP BUTTON?
LOCAL FONT { @FONT-FACE { ISSU E
None
@Font-face THIS ONE WEIRD TRICK A G EN D A
CAT FANCY UNICODE LOADING…
LET’S FIX EVERYTHING
DECORATIVE ICON U SE C A SE
<span class="twitter icon" aria-‐hidden="true"></span> Share on Twitter
<span class="twitter icon" aria-‐hidden="true"></span> Share on Twitter
FILAMENTGROUP/A-Font-Garde https://github.com/filamentgroup/a-font-garde
FontFaceOnload( "My Icon Font", {
glyphs: "\uE600\uE601\uE602\uE605", success: function() { var docEl = document.documentElement; docEl.className += " my-‐icon-‐font"; } }); // requires http://filamentgroup.github.io/a-font-garde/src/fontfaceonload.js
/* @font-‐face omitted */ ! .my-‐icon-‐font .icon-‐twitter:before {
font-‐family: My Icon Font; content: "\e600"; }
typekit/webfontloader https://github.com/typekit/webfontloader
CSS Font Loading Module Level 3 http://dev.w3.org/csswg/css-font-loading/
document.fonts.load("1em My Icon Font") .then(function() { !
var docEl = document.documentElement; docEl.className += " my-‐icon-‐font"; ! });
BRAMSTEIN/FONTLOADER https://github.com/bramstein/fontloader FOLLOW HE’S WORKING ON A POLYFILL. https://twitter.com/bram_stein/status/465560158723395584
my-‐icon-‐font SOLVES OUR PROBLEMS
WE NOW CONTROL FOIT & FOUT
NO MORE UNICODE SURPRISES TIMEOUT SURPRISES STOP BUTTON SURPRISES
DECORATIVE ICON 3 S @FONT-FACE LOAD FOIT FOUT
@Font-face THIS ONE WEIRD TRICK A G EN D A
LET’S GET FANCY UNICODE LOADING…
LET’S GET CAT FANCY
TEXT to ICON @FONT-FACE LOAD U SE C A SE
<style> .facebook .icon { display: none;
} .my-‐icon-‐font .facebook .icon { display: inline-‐block; } .my-‐icon-‐font .facebook .text { /* Visually hide but keep for screen readers */ clip: rect(0 0 0 0); overflow: hidden; position: absolute; height: 1px; width: 1px; } </style> <span class="facebook"> <span class="icon" aria-‐hidden="true"></span> <span class="text">Facebook</span> </span> https://github.com/h5bp/html5-boilerplate/blob/master/css/main.css#L127
<style> .facebook .icon { display: none;
} .my-‐icon-‐font .facebook .icon { display: inline-‐block; } .my-‐icon-‐font .facebook .text { /* Visually hide but keep for screen readers */ clip: rect(0 0 0 0); overflow: hidden; position: absolute; height: 1px; width: 1px; } </style> <span class="facebook"> <span class="icon" aria-‐hidden="true"></span> <span class="text">Facebook</span> </span> https://github.com/h5bp/html5-boilerplate/blob/master/css/main.css#L127
GLYPH to ICON ≡ U SE C A SE
https://twitter.com/bjankord/status/451367657493647361 Hamburger Helper
Hamburger Emoji
= Veggieburger
– Gluten Free Hamburger https://twitter.com/brouxhaha/status/464787128334180354
Facebook’s Manburger https://twitter.com/jedschmidt/status/455871778267463680
Hungryman Burger
@FONT-FACE LOAD GLYPH to ICON ≡
<style> .hamburger .icon:before { content: "\2261";
/* Adjust font-‐size and line-‐height to match */ } .hamburger .text { /* Visually hide but keep for screen readers */ clip: rect(0 0 0 0); overflow: hidden; position: absolute; height: 1px; width: 1px; } .my-‐icon-‐font .hamburger .icon:before { font-‐family: My Icon Font; content: "\e601"; ! /* Reset font-‐size and line-‐height */ font-‐size: inherit; line-‐height: inherit; } </style> <span class="hamburger"> <span class="icon" aria-‐hidden="true"></span> <span class="text">Menu</span> </span>
<style> .hamburger .icon:before { content: "\2261";
/* Adjust font-‐size and line-‐height to match */ } .hamburger .text { /* Visually hide but keep for screen readers */ clip: rect(0 0 0 0); overflow: hidden; position: absolute; height: 1px; width: 1px; } .my-‐icon-‐font .hamburger .icon:before { font-‐family: My Icon Font; content: "\e601"; ! /* Reset font-‐size and line-‐height */ font-‐size: inherit; line-‐height: inherit; } </style> <span class="hamburger"> <span class="icon" aria-‐hidden="true"></span> <span class="text">Menu</span> </span> <span class="icon" aria-‐hidden="true"></span>
@Font-face THIS ONE WEIRD TRICK A G EN D A
LET’S GET FANCY UNICODE LOADING…
Different GOALS FOR CONTENT ICONFONTS CONTENT ICON
@zachleat Thank you!