Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Bulletproof Font Icons
Search
zachleat
May 27, 2014
Programming
3.1k
19
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Bulletproof Font Icons
Originally presented at CSSConf 2014:
http://2014.cssconf.com/#zach
zachleat
May 27, 2014
More Decks by zachleat
See All by zachleat
NEJS CONF 2017 Interstitial Slides
zachleat
0
160
Credibility
zachleat
0
110
A Brief History of that Time You Used Web Fonts
zachleat
7
1.5k
The Performance and Usability of Font Loading (Velocity NYC 2015)
zachleat
3
690
The Performance and Usability of Font Loading (Velocity Santa Clara 2015)
zachleat
27
4.8k
Performance and Responsive Web Design
zachleat
7
2.2k
Remodeling @font-face
zachleat
17
3.6k
How and Why I Built fontfamily.io
zachleat
2
1.6k
Impostor Syndrome
zachleat
1
490
Other Decks in Programming
See All in Programming
数年滞っていたダークモード対応をおよそ2週間で完了させる
chigichan24
0
710
Starting & Sustaining Code-Based E2E Testing for Non-Coding QA Teams( #jasstniigata )
teyamagu
PRO
1
290
Are APIs Still Relevant in the AI Era?
soyuka
0
230
XP祭りでしか伝わらないフリップネタ #xpjug
murabayashi
0
150
How I Stole PSI from Android Studio - DroidKaigi2026
worker8
0
130
Omarchy Tokyo やると聞いて UMPC 買ってセットアップしてきた
mtsmfm
0
140
GraphRAGのKnowledge Graphを 直接!見る/View-GraphRAG's-KnowledgeGraph-directly!
tyumugi1113
1
320
標準パッケージに uuid が追加された 背景から見る Go らしい意思決定 / go_127_uuid_decision
convto
5
7.2k
そのリトライ、死んだコネクションを使い回していませんか ── GoのHTTPクライアントとHTTP/2を実プロダクト障害から学び直す
myus4a
0
140
AI Agent時代のリアーキテクチャ戦略と実践
hokaccha
9
4.5k
cdk deploy JawsSonic #MARATHONしながらAWSリソースをデプロイしてみよう
akihisaikeda
2
130
DroidKaigi 2026 「個人開発という実験場: Android エンジニアが手にする4つの自由」
slashnephy
0
230
Featured
See All Featured
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
390
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
290
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Why You Should Never Use an ORM
jnunemaker
PRO
61
10k
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
5
660
Building the Perfect Custom Keyboard
takai
2
870
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Large-scale JavaScript Application Architecture
addyosmani
515
110k
It's Worth the Effort
3n
188
29k
Mobile First: as difficult as doing things right
swwweet
225
10k
Everyday Curiosity
cassininazir
0
320
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!