這一期中咱們將圍繞着Web中的font
來展開。在現代Web中除了能使用font-family
屬性給Web應用指定字體以外,還有其餘一些用於字體的特性,好比@font-face
能夠加載非系統的字體,字體變體屬性font-variation-*
讓Web上排版和印刷上排版之間的差距在逐漸拉小,font-display
屬性來決定非系統方面字體的加載策略,提升性性能,font-palette
用來選擇字體配色,@font-palette-values
自定義字體配色等。若是你感興趣的話,請繼續往下閱讀。javascript
現代Web的開發,除了追求技術上的完善以外,有些開發者是設計出身,不少時候也追求藝術上的更好展示。特別是對於Web字體來講,受限於系統可用的字體很是的有限。但隨着@font-face
的出現,Web開發者可使用第三方(非系統內置)的字體,好比:css
@font-face {
font-family: 'NeuesBauenDemo';
src: url('../fonts/neues_bauen_demo-webfont.eot');
src: url('../fonts/neues_bauen_demo-webfont.eot?#iefix') format('embedded-opentype'),
url('../fonts/neues_bauen_demo-webfont.woff') format('woff'),
url('../fonts/neues_bauen_demo-webfont.ttf') format('truetype'),
url('../fonts/neues_bauen_demo-webfont.svg#NeuesBauenDemo') format('svg');
font-weight: normal;
font-style: normal;
}
.neuesDemo {
font-family: 'NeuesBauenDemo'
}
複製代碼
好比上面的示例,可讓Web上的字體更具藝術範:html
@font-face
除了能讓Web開發者使用第三方字體以外,還有另一個優點,並且在Web中運用也很是的常見,即字體圖標。好比Font Awesome就是一個很是受歡迎的用字體制做的圖標庫。前端
@font-face {
font-family: 'FontAwesome';
src: url('font/fontawesome-webfont.eot');
src: url('font/fontawesome-webfont.eot?#iefix') format('embedded-opentype'), url('../font/fontawesome-webfont.woff') format('woff'), url('../font/fontawesome-webfont.ttf') format('truetype'), url('../font/fontawesome-webfont.svgz#FontAwesomeRegular') format('svg'), url('../font/fontawesome-webfont.svg#FontAwesomeRegular') format('svg');
font-weight: normal;
font-style: normal;
}
<div class="icon-glass"></div>
複製代碼
使用也很是的方便。並且在現使用Font Awesome只須要調用相關的資源連接,需使用的時候指定相應的圖標類名便可:java
上面看到的字體都是現成的,若是你是一名設計師或者說你懂得字體的設計。那麼你就能夠在任何Web頁面或Web應用上使用你本身設計的字體。這樣一來,是否是很是有成就感。一樣的原理,還能夠設計一些SVG矢量圖標,藉助IcoMoon Web App將圖標生成Web可用的Web字體:css3
若是你對Web中字體圖標相關的東西感興趣的話,還能夠閱讀下面相關文章:git
@font-face
製做Web Icon@font-face
帶來不少優點,但大多人通常只會聊自定義的Web字體如何定義,可是沒有過多的人考慮其實際性能:github
特別是網絡環境很差或弱網狀況之下,可能訪問帶有Web字體的應用會對用戶帶來一些很差的體驗。好比下面這個錄展所示的效果:web
基本的@font-face
使用方法會至使用戶加載字體受到阻塞。不過慶幸的是,咱們能夠找到一些技術方案來改善字體加載性能,讓使用Webp字體的性能更好,加載字體更流暢。後面咱們會聊到這些相關的技術。chrome
你或許常常會看到有網站像下面這樣的引用非系統的字體:
<!-- HTML中經過link標籤引用 -->
<link href="https://fonts.googleapis.com/css?family=Gloria+Hallelujah" rel="stylesheet">
複製代碼
或者:
/* 在CSS中經過@import引用 */
@import url('//fonts.googleapis.com/css?family=Lato:400,400italic,700|Sansita+One');
複製代碼
打開字體文件,你會發現代碼以下:
/* latin-ext */
@font-face {
font-family: 'Lato';
font-style: italic;
font-weight: 400;
src: local('Lato Italic'), local('Lato-Italic'), url(https://fonts.gstatic.com/s/lato/v15/S6u8w4BMUTPHjxsAUi-qNiXg7eU0.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* 部分代碼略去 */
複製代碼
能夠看到,依舊離不開@font-face
這個屬性。固然裏面還有一些其餘的設置,好比unicode-range
。
簡單地說,上面的示例使用了Google Font,並且使用Google Font的人很是的多。在Google Fonts上有不少字體能提供你們選用:
其實按這樣的原理,咱們也能夠把本身的圖標提交到線上,使用CDN地址。
使用Google字體仍是有一些小技巧,這些技巧有助於咱們搞高字體加載的性能。後面會聊一些這些技巧。若是你的字體也放在CDN上,也能夠按相似的方案來作處理。若是感興趣話,敬請後面的內容。
這裏所說的Web中的中文字體,並非咱們系統常見的字體,好比「宋體」、「楷體」、」萍方「和」微軟雅黑「等。拿個示例來講吧,在UI還原中,你確定碰到帶有藝術字體的設計稿:
碰到這樣的場景大部分解決方案,要麼是使用系統默認字體,要麼是使用圖片來替換。或許你會問:
既然
@font-face
這麼牛逼,爲何中文藝術字體不用該特性呢?
緣由很是簡單,對於英文而言,它只有26
字母,一張ASCII碼上128
個字符集,體量較小,設計成本較小。但對於中文而言,單單GB2313
編碼的中文字字符就達到7445
個,體量較大,設計成本較大。這就是中文相比於英文不太好設計的緣由之一,若是要設計出這麼一套中文字體(帶藝術性,個性化字體),除了設計成本和難度較大以外,就算是設計出來,字體體積也很是的大,面對這麼大的字體文件,要是運用於Web上,也不是件易事。最起碼要面對字體的加載,性能的優化等問題。
不過並非沒有任何方案可解,在社區中也有相應的字體裁剪工具,好比:
就算是有了這些工具,咱們也沒法大面積的在Web上使用特殊的中文字體。而在中文Web應用程序中,使用這種藝術字體的場景也不是全站都是,大部分會出如今標題、Banner等場景。而這樣的場景下所需的字體數量有限的,這樣咱們就能夠藉助上面的兩個工具對字體進行裁剪,生成一個只包含特定字符的小字體文件。這樣就達到了減小字體文件的目標。
有關於這方面的詳細介紹能夠閱讀下面幾篇文章:
@font-face
前面提到過,使用@font-face
使用第三方字體的時候受限於字體的大小,網絡的影響等,對用戶的體驗是會有相應的影響。除了下降字體包的大小以外還有一些別的優化方式。好比@Danny Cooper在他的最新博客中就聊到了如何優化Google Fonts性能。在這篇文章中提到的一些優化方案其實都適合使用@font-face
的任何地方。
下面簡單的來了解一下@Danny Cooper在文章中給咱們介紹哪些技術手段能對字體方面作相關的優化。
無論是使用的Google Fonts仍是其餘地方提供的字體。能夠說每種字體在Web瀏覽器中顯示以前都須要先下載。經過正確的設置,額外的加載時間並不明顯。可是,若是出現錯誤,用戶可能須要等待必定的時候才能顯示。接下來,做者拿Google Fonts爲例,闡述瞭如何對字體作相關的性能優化。
Google Fonts API不只僅向咱們提供字體文件,它還有一個更大的優點,就是會執行智能檢查,以查看如何以最優化的格式交付文件。 好比Roboto
字體,Github告訴咱們,常規版的字體體積大約爲168kb
:
若是咱們從API請求相同的字體變體(Font variant)就會獲得這個文件,只有11kb
。是否是很神奇。那是由於,當瀏覽器向API發出相應的請求時,Google首先會檢查瀏覽器支持哪些文件類型。好比最新版本的Chrome瀏覽器和大多數的瀏覽器同樣,也支持WOFF2
,因此字體是以高度壓縮的格式提供給咱們的。
不一樣的瀏覽器會獲取不一樣的字體格式。
最爲強大的是,Google Fonts 爲 每種字體維護了30多個優化的字體變體,並自動檢查和交付每種平臺和瀏覽器的最佳變體。@Ilya Grigorik在這方面作過深刻的討論,詳細的能夠閱讀《網頁字體優化》一文。
網頁字體是一個字形集合,而每一個字形是描述字母或符號的矢量形狀。 所以,特定字體文件的大小由兩個簡單變量決定:每一個字形矢量路徑的複雜程度和特定字體中字形的數量。
Google Fonts的另外一個內置優化是瀏覽器緩存。
因爲Google Fonts的廣泛性,瀏覽器並不老是須要下載完整的安體文件。例如,使用了Mija
這樣的一個字體,若是你的瀏覽器首次看到該字體,在須要顯示以前會下載該字體,但下次再從新訪問該網站時使用之個字體,瀏覽器將會使用緩存版本。
Google Fonts瀏覽器緩存被設置爲一年後過時,除非緩存被提早清除。
雖然谷歌在優化字體文件的交付方面投入了大量的精力,可是仍然能夠在實際使用中進行一些更多的優化,以減小對頁面加載時間的影響。
最簡單的優化注是使用更少的字體庫。每種字體的頁面重量加起來可能達到400kb
,再乘以幾個不一樣的字體族,您的字體的重量就會忽然超過整個頁面的重量。@Danny Cooper在文章中建議:
在頁面中不要使用超過兩種字體,一種用於標題,另外一種用於內容。
使用正確的字體大小、重量和顏色,即便只有一種字體,在性能上也有較好的優化。
Google Fonts質量是出了名的,而Google爲了讓字體具備較高的質量標準,請多字體都包含了可用的字體權重(font-weight
):
權重關鍵詞 | 權重對應的值 | 權重關鍵詞 | 權重對應的值 | 權重關鍵詞 | 權重對應的值 | 權重關鍵詞 | 權重對應的值 |
---|---|---|---|---|---|---|---|
Thin | 100 | Thin Italic | 100i | Light | 300 | Light Italic | 300i |
Regular | 400 | Regular Italic | 400i | Medium | 600 | Medium Italic | 600i |
Bold | 700 | Bold Italic | 700i | Black | 800 | Black Italic | 800i |
這對於可能須要全部12
種變體的高級用例來講是很是好的,可是對於一個普通的網站,意味着下載全部12
種變體,就過於浪費,由於你可能只會用到3
或4
種變體。例如,Roboto
字體系列的重量大約爲144kb
。可是,若是你只使用常規的,常規的斜體和粗體等,那麼這個字體的重量就能夠降低到大約36kb
,至關於節約了75%
。
通常狀況下,加載Google Fonts的默認代碼以下:
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
複製代碼
這樣作,只是加載了常規400
(Regular 400
)版本。這意味着字體集中的其餘版本,好比Light
、Bold
和Italic
將不會正確的顯示。若是要改變這個現象,即 要加載全部字體變體,能夠在href
中的URL
顯式指定字體變體的權重,以下所示:
<link href="https://fonts.googleapis.com/css?family=Roboto:100,100i,300,300i,400,400i,500,500i,700,700i,900,900i" rel="stylesheet">
複製代碼
前面也提到過了,不多網站會使用全部字體的變體,從100
到900
,而實際使用中,最佳的方式是指定你可能須要的字體變體權重,好比:
<link href="https://fonts.googleapis.com/css?family=Roboto:400,400i,600" rel="stylesheet">
複製代碼
這種方式,在使用多個字體的時候更顯得重要。好比,若是使用Lato
做爲Web中的標題,它可能只會請求粗體(可能還會有粗體斜體):
<link href="https://fonts.googleapis.com/css?family=Lato:700,700i" rel="stylesheet">
複製代碼
無論是使用Google Fonts(若是沒有下載到本地)或者使用其餘CDN上的線上字體庫,都會須要相應的HTTP
請求。對於Web應用而言,發出的HTTP
請求越多,加載所需的時間就越長,對於性能的影響就越大。若是你的頁面中使用到多個字體時,就要面對HTTP
請求增多的事實。實際上,咱們能夠按下面這種方式對請求作相應的優化,能夠減小HTTP
的請求數:
<!-- 優化前的方式 -->
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,400i,600" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<!-- 優化後的方式 -->
<link href="https://fonts.googleapis.com/css?family=Roboto|Open+Sans:400,400i,600" rel="stylesheet">
複製代碼
資源提示(Resource Hints)是現代瀏覽器支持的一種特性,能夠用來提升網站的性能。該特性包含了prefetch
、preload
、preconnect
、dns-prefetch
和prerender
等。它們能夠用於<link>
標籤的rel
中,告訴瀏覽器預加載一些東西:
<link rel="prefetch" href="/style.css" as="style" />
<link rel="preload" href="/style.css" as="style" />
<link rel="preconnect" href="https://example.com" />
<link rel="dns-prefetch" href="https://example.com" />
<link rel="prerender" href="https://example.com/about.html" />
複製代碼
其中dns-prefetch
和preconnect
對於字體加載方面的優化有很大的做用。
dns-prefetch
容許瀏覽器在頁面開始加載時當即啓動和Google Fonts API(fonts.googleapis.com
)的鏈接。這意味着當瀏覽器準備發出請求時,一些工做已經完成了。要實現谷歌字體的dns-prefetch
,只須要在<head>
標籤中添加像下面這樣的一行代碼便可:
<link rel="dns-prefetch" href="//fonts.googleapis.com">
複製代碼
另外,谷歌字體的嵌入代碼看上去好像只發出一個單一的HTTP
請求:
<link href="https://fonts.googleapis.com/css?family=Roboto:400,400i,700" rel="stylesheet">
複製代碼
事實上並不是如此若是咱們訪問https://fonts.googleapis.com
這個URL
,它並不僅發出一個HTTP
請求,其實他實際上發出了多個請求。
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
src: local('Roboto Italic'), local('Roboto-Italic'), url(https://fonts.gstatic.com/s/roboto/v19/KFOkCnqEu92Fr1Mu51xFIzIXKMnyrYk.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
src: local('Roboto Italic'), local('Roboto-Italic'), url(https://fonts.gstatic.com/s/roboto/v19/KFOkCnqEu92Fr1Mu51xMIzIXKMnyrYk.woff2) format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
src: local('Roboto Italic'), local('Roboto-Italic'), url(https://fonts.gstatic.com/s/roboto/v19/KFOkCnqEu92Fr1Mu51xEIzIXKMnyrYk.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
src: local('Roboto Italic'), local('Roboto-Italic'), url(https://fonts.gstatic.com/s/roboto/v19/KFOkCnqEu92Fr1Mu51xLIzIXKMnyrYk.woff2) format('woff2');
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
src: local('Roboto Italic'), local('Roboto-Italic'), url(https://fonts.gstatic.com/s/roboto/v19/KFOkCnqEu92Fr1Mu51xHIzIXKMnyrYk.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
src: local('Roboto Italic'), local('Roboto-Italic'), url(https://fonts.gstatic.com/s/roboto/v19/KFOkCnqEu92Fr1Mu51xGIzIXKMnyrYk.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
src: local('Roboto Italic'), local('Roboto-Italic'), url(https://fonts.gstatic.com/s/roboto/v19/KFOkCnqEu92Fr1Mu51xIIzIXKMny.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu72xKKTU1Kvnz.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu5mxKKTU1Kvnz.woff2) format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu7mxKKTU1Kvnz.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu4WxKKTU1Kvnz.woff2) format('woff2');
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu7WxKKTU1Kvnz.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu7GxKKTU1Kvnz.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu4mxKKTU1Kg.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmWUlfCRc4AMP6lbBP.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmWUlfABc4AMP6lbBP.woff2) format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmWUlfCBc4AMP6lbBP.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmWUlfBxc4AMP6lbBP.woff2) format('woff2');
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmWUlfCxc4AMP6lbBP.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmWUlfChc4AMP6lbBP.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmWUlfBBc4AMP6lQ.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
複製代碼
若是在<link>
標籤中指定rel="preconnect"
時,這些附加的請求的問題是,直到第一個對https://fonts.googleapis.com/css
的請求完成以後,瀏覽器纔會開始處理這些請求。
也能夠說preconnect
是prefetch
的加強版。它是在瀏覽器將要加載的特定URL
上設置它。它不只執行DNS
查找,還完成了TSL
協商和TCP
握手。
<link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin>
複製代碼
僅僅添加這一行代碼就能夠將頁面加載時間減小100ms
。
若是你對Resource Hints相關的技術感興趣的話,還能夠閱讀下面相關的教程進行擴展:
谷歌字全是在」Libre「或」自由軟件「許可下受權的,它容許你在沒有請求許可的狀況下自由使用、更改和分發字體。言外之意,若是你不想使用谷歌的主機,能夠本身託管。甚至能夠將字體下載到本身本地,作一些其餘的優化。
另外,谷歌字體還提供一個服務,容許你選擇要使用的字體,而後提供所需的文件和CSS。
font-display
屬性提供了幾個不一樣的屬性值,對於字體的加載能夠作相應的優化。font-display
經常和@font-face
配合在一塊兒使用:
@font-face {
font-family: 'Roboto';
src: local('Roboto Thin Italic'),
url(https://fonts.gstatic.com/s/roboto/v19/KFOiCnqEu92Fr1Mu51QrEz0dL-vwnYh2eg.woff2)
format('woff2');
font-display: swap;
}
複製代碼
若是引用谷歌在線的字體,還能夠這樣使用:
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+HK&display=swap" rel="stylesheet" >
複製代碼
在href
的URL
地址上配合font-display
一塊兒使用&display=swap
。
font-display
它還能實現相似於Font Loading API和Bram Stein's Font Face Observer這種第三方腳本實現的功能。
用一張簡單的圖來描述font-display
屬性對瀏覽器加載字體的相關影響:
特別聲明,上圖來自於@monica的《Font-display》一文。
有關於font-display
屬性更多的相關介紹能夠閱讀:
font-display
的用法font-display
font-display
: The Future of Font Rendering on the WebGoogle Fonts API還有一個特性,應該是提供了text
參數。這個不多使用的參數容許你只加載所須要的字符。例如,若是你的文本Logo(使用文本製做的Logo)須要惟一的之際體,則可使用text
參數只加載製做Logo須要的字符:
https://fonts.googleapis.com/css?family=Roboto&text=CompanyName
複製代碼
固然,這種技術很是具體,只有少數實際應用。然而,若是你可使用它,它能夠減小字體的重量高達90%
。另外,使用text
的參數時,默認狀況下只加載normal
的字體權重(font-weight
)。若是須要使用另外的一個權重,須要在URL
中顯式的指定它:
https://fonts.googleapis.com/css?family=Roboto:700&text=CompanyName
複製代碼
這幾點是@Danny Cooper針對於Google Fonts API作的一些性能優化。其實文章中提到的這些技術方案可否實用於其餘的第三方字體庫有待於考量,可是對於font-display
屬性而言,他能夠適用於任何一個加載字體的地方。
不少同窗可能會有困惑,本身在Web中開發時,使用到Google Fonts API的場景並很少,甚至是沒有。那麼要怎麼來優化字體的加載呢?事實上仍是有不少字體加載的優化方式值得咱們去探究和深挖。
很早以前,@Bram Stein提到使用fontFaceObserver
來對字體加載作優化。如今,咱們能夠不借助任何的Polyfill,在瀏覽器中使用原生的JavaScript API也能夠作相關的優化,好比FontFaceSet.load()
。
若是你擔憂瀏覽器是否支持該API,能夠先對其作相應的判斷:
;(function () {
if (!('fonts' in document)) return;
})();
複製代碼
若是不支持,那程序會直接return
掉,釋放程序。該方法使用promise
在加載字體後運行函數。該函數將會傳遞font-size
和name
做爲參數,並使用.then()
設置函數,該函數將在加載字體後運行。好比下面這個示例:
;(function () {
if (!('fonts' in document)) return;
document.fonts.load('1em PT Serif').then(function () {
document.documentElement.className += ' fonts-loaded';
});
})();
複製代碼
在函數中,咱們將在html
元素中添加.font-load
類,它將激活自定義字體。
另外該方法還能夠爲字體在瀏覽器中設置一個緩存的期間:
;(function () {
if (!('fonts' in document)) return;
document.fonts.load('1em PT Serif').then(function () {
var expires = new Date(+new Date() + (7 * 24 * 60 * 60 * 1000)).toUTCString();
document.cookie = 'fontsLoaded=true; expires=' + expires;
document.documentElement.className += ' fonts-loaded';
});
})();
複製代碼
在頁面加載時,若是cookie
存在,將當即添加.font-load
類到html
元素中並結束程序。
注意,load()
方法僅適用於現代瀏覽器,但在Edge和IE支持。若是你想使用該方法來加載自定義字體的話,能夠考慮將FontFaceSet.load()
和fontFaceObserver
結合起來:
;(function () {
// Native behavior
if ('fonts' in document) {
document.fonts.load('1em PT Serif').then(function () {
var expires = new Date(+new Date() + (7 * 24 * 60 * 60 * 1000)).toUTCString();
document.cookie = 'fontsLoaded=true; expires=' + expires;
document.documentElement.className += ' fonts-loaded';
});
}
// Fallback for IE/Edge
else {
// Use fontFaceObserver
}
})();
複製代碼
若是你對這方面的知識感興趣的話,還能夠閱讀下面相關文章:
FontFaceSet.load()
methodFontFaceSet.load()
method instead of the CSS font-display: swap
property?@zachleat早在2016年對於@font-face
的使用時加載字體就探討過有關於字體加載方面的策略,用文章中的一張圖來描述:
最近,@zachleat在他的新博客中以CSS-Tricks網站爲例,介紹了CSS-Tricks中是如何使用CSS相關的技巧爲開發提供了比較健壯的字體加載策略。
文章中提到的一些策略(或者說技術手段)和@Danny Cooper文章中提到的有點相似。好比<link>
標籤中rel
指相應的屬性(如preload
)、CSS的font-display
,CSS字體加載API(如FontFace
)等。文章中詳細討論瞭如何爲兩個階段加載肯定不一樣特性的優先級。可是實現起來難度並不大,代碼很是簡單。
首先,在第一階能作的事情。
預加載HTML,可使用link
標籤的rel
屬性來指定加載姿式:
<link rel="preload" href="Rubik-Bold-kern-latin.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="Rubik-Regular-kern-latin.woff2" as="font" type="font/woff2" crossorigin>
複製代碼
另外使用到@font-face
的CSS內聯到頁面中(放置在</head>
)中:
@font-face {
font-family: Rubik;
src: url(Rubik-Bold-kern-latin.woff2) format("woff2"),
url(Rubik-Bold-kern-latin.woff) format("woff");
font-weight: 700;
font-display: swap;
}
@font-face {
font-family: Rubik;
src: url(Rubik-Regular--kern-latin.woff2) format("woff2"),
url(Rubik-Regular-kern-latin.woff) format("woff");
font-weight: 400;
font-display: swap;
}
複製代碼
第二階段就是藉助JavaScript來作相關的優化,這裏指的就是CSS字體加載相關的API。你能夠把這段腳本放到任何你想放的地方。也能夠內聯到<head>
中:
if( "fonts" in document ) {
var regular = new FontFace("Rubik", "url(Rubik-Regular-hint-all.woff2) format('woff2'), url(Rubik-Regular-hint-all.woff) format('woff')");
var bold = new FontFace("Rubik", "url(Rubik-Bold-hint-all.woff2) format('woff2'), url(Rubik-Bold-hint-all.woff) format('woff')", { weight: "700" });
Promise.all([ bold.load(), regular.load() ]).then(function(fonts) {
fonts.forEach(function(font) {
document.fonts.add(font);
});
});
}
複製代碼
若是你有更重要的資源須要加載的話,建議到這段腳本以前,以避免被阻塞。前面也提到過了,CSS字體加載相關的API不是全部瀏覽器都支持,若是你使用了該方面的API來對字體加載作相應的優化的話,那麼還能夠考慮像下面這樣的方式爲不支持CSS字體加載的API提供相應的降級方案:
if(!("fonts" in document) && "querySelector" in document) {
// Awkwardly dump the second stage @font-face blocks in the head
var style = document.createElement("style");
// Note: Edge supports WOFF2
style.innerHTML = "@font-face { font-family: Rubik; src: url(/rubik/Rubik-Regular-hint-all.woff2) format('woff2'), url(/rubik/Rubik-Regular-hint-all.woff) format('woff'); } @font-face { font-family: Rubik; font-weight: 700; src: url(/rubik/Rubik-Bold-hint-all.woff2) format('woff2'), url(/rubik/Rubik-Bold-hint-all.woff) format('woff'); }";
document.querySelector("head").appendChild(style);
}
複製代碼
字體加載的不一樣策略直接會影響到網站的性能,用戶的體驗。若是你平時的項目中經常會用到@font-face
來加載一些Web非安全字體,或者使用一些字體圖標。那麼就頗有必要多瞭解字體加載、字體性能優化方面的相關知識和技巧。若是你感興趣的話,建議花一些時間閱讀下面這些文章:
若是說,使用CSS相關的特性能實現上圖這樣的彩色字體效果,會不會感到很是的驚訝和好奇。是的,不會錯的,在CSS Fonts Module Level 4工做草案中提供了一些新特性,即爲Color Font提供了相應的描述。
彩色字體經過 CPAL 表是能夠擁有多種不一樣的配色方案的。font-palette
有三個內置的參數以及支持自定義配色來達到修改配色方案的效果。
normal
:瀏覽器儘量地將該字體看成非彩色字體進行渲染,並選擇一個最適合閱讀的配色方案。瀏覽器在作決策時還可能將當前設定的字體顏色color
加入決策條件中。還有可能自動生成一組未內置在字體中的配色方案進行渲染。light
:一些彩色字體在其元數據中標明某個配色方案適用於亮色(接近於白色)背景中。使用此數值,瀏覽器將會直接使用標記了該特性的首個配色方案進行渲染。若是字體文件格式無元數據或時元數據中未標記相應的配色方案,那麼此時該數值的行爲與 normal
相同dark
:正好與light
相反@font-palette-values
的幫助。@font-palette-values
用於定義指定字體的配色規則。它容許開發者不只能夠自由選擇字體內置的各類配色方案,還能自定義配色方案。而font-palette
選擇自定義配色方案也是經過本規則設置。
它的基本定義規則是@font-palette-values name
,name
即爲本配色規則的自定義規則名稱。
若是你對彩色字體感興趣的話,能夠閱讀早前整理的一文章。
在CSS中能夠經過font-variant-*
屬性來控制大多數OpenType特性。font-variant-*
主要包括:
font-variant-ligatures
font-variant-caps
font-variant-numeric
font-variant-alternates
font-variant-east-asian
這裏不對字體變體作過多的闡述,若是你對這面感興趣,能夠閱讀《字體變體font-variation-*
》一文。這裏給你們提供一個案例,讓你們有一個更形象的體感:
前端時間@袁川 老師再次向你們展現了CSS的藝術。即使用CSS製做中國式的窗櫺:
在製做窗櫺時使用到了CSS的-webkit-box-reflect
屬性。印象中最先接觸該屬性的時候大約是在2014年的時候,就嘗試着使用了這個屬性來實現一些倒影或鏡像的效果。
而在CSS中實現鏡像效果的技術方案不只侷限於-webkit-box-reflect
屬性。接下來,簡單的聊聊CSS中的鏡像。
最簡單的方式就是使用CSS的transform
中的scaleX(-1)
實現水平鏡像,scaleY(-1)
實現垂直方向的鏡像效果。好比你有一張這樣的圖:
使用上面提到的方法,能夠很容易的實現水平和垂直方向的鏡像效果:
該特性是真正用來製做鏡像的。其主要包括如下幾個屬性值:
none
:此值爲-webkit-box-reflect
默認值,表示無倒影效果;<direction>
:此值表示-webkit-box-reflect
生成倒影的方向,主要包括如下幾個值:above
生成的倒影在對象(原圖)的上方;below
生成的倒影在對象(原圖)的下方;left
生成的倒影在對象(原圖)的左側;right
生成的倒影在對象(原圖)的右側;<offset>
:用來設置生成倒影與對象(原圖)之間的間距,其取值能夠是固定的像素值,也能夠是百分比值,如:使用長度值來設置生成的倒影與原圖之間的間距,只要是CSS中的長度單位均可以,此值可使用負值;使用百分比來設置生成的倒影與原圖之間的間距,此值也可使用負值<mask-box-image>
:用來設置倒影的遮罩效果,能夠是背景圖片,也能夠是漸變生成的背景圖像。好比@袁川 老師在教程中向你們演示的案例,就是使用該特性製做的一箇中國式窗櫺效果:
在CSS Image Values and Replaced Content Module Level 4中有一個element()
函數。 這個函數能夠將網站中的某部分看成圖片渲染。當一個DOM元素在瀏覽器中獲得正確的渲染時,其實獲得的就是一張圖片。並且元素修改以後,獲得的圖片也會立馬改變。
使用該函數配合transform
能夠像-webkit-box-reflect
同樣實現鏡像效果:
在CSS中,無論是-webkit-box-reflect
,仍是transfrom: scaleX(-1)
(或transform: scaleY(-1)
),甚至element()
函數之類的,結合CSS Making相關的特性或者CSS漸變相關的特性會讓鏡像效果更佳。好比 @ANA TUDOR在她的教程《The State of CSS Reflections》(譯文)中向你們演示的案例:
若是你對CSS中實現鏡像相的技術感興趣的話,還能夠閱讀下面相關教程:
在Web技巧系列的第10期中,咱們聊天了排版相關的技巧。而排版中或者說Web製做中都離不開字體的使用。在之一期中咱們主要和你們一塊兒探討了Web中怎麼使用@font-face
來加載非安全的Web字體(也就是自定義字體,或系統中不具有的字體)。@font-face
除了可讓咱們使用帶有藝術範或個性化的字體以外,還可使用它來實現字體圖標。無論家文本仍是圖標都會涉及到字體的製做與轉換,所以簡單的一塊兒聊了一下怎麼製做字體和轉換字體。
既然使用@font-face
特性,都將面臨字體的加載,無論是線上(從CDN
加載字體)仍是加載本地字體,都要考慮怎麼作字體加載。因此這一期中,大部分篇幅和你們一塊兒聊聊怎麼來優化字體加載,提升頁面性能,從而改善用戶體驗。
最後再向你們展現了CSS另外一方面的能力,即,怎麼使用CSS的transform
、-webkit-box-reflect
和element()
等來實現鏡像效果。最後,但願這一期中討論的東西,你們會喜歡。若是您在這方面有相關的經驗,或有較好的建議,歡迎在下面的評論中與咱們一塊兒討論。