Acclerated Mobile Pages

O2 DAC + AMP,

Acclerated Mobile Pages簡稱 AMP,是 Google 所推出,為了提升行動網路體驗的一個專案,我一開始對於這種(看似)偏離網路標準的方案其實不太有興趣,不過在瞭解其技術原理後,覺得相當有趣,而且其實沒有想像中的偏離標準,整個架構也比 Facebook 的 Instant Article 還要來的開放,雖然我覺得這個解決方案(只說是 Framework 或是 Library 都不夠完整),其實只算是個暫時的解法,但是 AMP 本身的實做方式,其實是架構在一堆網路標準的發展之上的,相當出人意料,可以說是Extensible Web 宣言以來,第一個重要的里程碑。

閱讀「Acclerated Mobile Pages」全文

Modern HTML Email Development

今天在 Modern Web 分享的主題

其實最主要是想介紹MJML這個工具,不過最後介紹的篇幅有些不夠,有些可惜,話說今天設備也有些狀況,一是投影機解析度和預期的不一樣,二是無線麥克風聲音會延遲,對於講者來說還蠻干擾的,最後時間還剩的比預期多,覺得愧疚啊。

最後附上這次介紹的一些資源的連結,方便取用:


Pure.css

最近做的修改還有一個就是把Bootstrap換掉,因為我覺得它實在是太大了,包進很多我沒用到的東西,即使是壓縮過的版本也要上百 KB,其實我只需要一部份的元件,像是圖片、引言、程式碼和 grid layout 等,但是這些部分的 CSS 所佔的比例其實超級少,所以我決定找一個新的 framework 把它換掉,結果我挑的是 Yahoo 已經沒有繼續更新的專案Pure.css

Pure.css 檔案大小比起 Bootstrap 實在小很多,最小化過的版本只有約 17KB,不過 responsive grid layout 的部分是獨立的,該模組的大小約是 9.57KB,和原來使用 Bootstrap 相比,總共大概是只有原來的四分之一(當然 gzip 後沒差這麼多),不過檔案小這麼多一定有所犧牲,Pure.css 提供的元件比起 Bootstrap 來少很多,而且提供的我幾乎都沒用到,最後我只用到 menu 和 grid layout 兩個部分而已,所以又從 Bootstrap 那邊把我要的元件手工複製出來使用,最後整理出來的 CSS 是 36.15KB,gzip 後是 7.3KB,brotli 壓縮過後是 6.34KB,傳輸前的資料量和原來相比大約是三分之一至四分之一,使用 gzip 壓縮傳輸的資料量則是三分之一左右(相較於原本的 18.97KB),整體來說成效不錯,其實 Framework 的部分還是佔了很大的比例,所以下一步就是把整個 CSS Framework 拿掉了,我推估實際上我需要的這些 CSS 大概 3KB 的資料量就夠了。

不過 Pure.css 是個已經沒在維護的專案了,Github 上已經超過一年沒有動靜,再加它其實沒 Bootstrap 那樣簡單用,有很多細節都還是要自己處理,就連它們首頁應該都是加工不少才出來的,所以要用這套 CSS Framework 的人還是要三思啊。


Device Pixel Ratio Header

之前文章有介紹過 DPR(Device Pixel Ratio),不過當時只能透過 JavaScript 在 client 端存取,如果 server 端要知道 client 端的 DPR 至少得要來回交換一次資訊,在那個時候就有想過應該之後會有新的標準來負責處理這個問題,而最近終於看到標準的草案了,叫做HTTP Client Hints,照字面的意思,這個 HTTP 擴充標準不是只有 DPR,而是提供 client 端的一些資訊,目前包括了:

  • DPR
  • width
  • viewport-width
  • downlink

其中DPR就是 device pixel ratio;viewport-width就和以前介紹過的 viewport width 一樣;width比較特別,是實際希望的 resource 寬度,而不是真的屬於 device 的資訊,例如圖片在網頁內是 160px,裝置的 DPR 是 2,width就是 160×2 = 320px;最後一個downlink則是以前一直很難取得的網路速度,以前最大的限制在於不管是 client 端還是 server 端都很難取得實際的網路速度,雖然可以用 JavaScript 下載檔案算時間來取得素質,但是這樣的作法其實有個兩難的問題,一方面問題是如果檔案大小,那取得的數字會很不準確,另一方面問題是如果檔案太大,那必然就是浪費時間和網路頻寬,更不用說很多地方沒有吃到飽方案可以用,這樣的作法應該不會太受歡迎,甚至如果不測速度,搞不好都已經把網頁讀好了。現在把這個資訊的提供者更往上一層,改成由瀏覽器提供,瀏覽器就可以跟作業系統作溝通,就比較有機會不用先測速就拿到可以參考的網路速度。這些 Header 傳輸的時候都不用附上單位,只有數字,其中 downlink 的單位是 Mbps,而規範所希望瀏覽器提供的 downlink 數字是參考Network Information API這份 API 裡面整理的,主要連線方法的理論速度上限,例如 GSM 就是 0.01、LTE 是 100﹑wifi 802.11g 是 54,本來是想說這個數字是看瀏覽器自己決定,不只根據連線的方式,還會看實際的傳輸數字或是使用者偏好,例如他可能使用 LTE 但是因為不是吃到飽,所以希望把速度報低一點之類的。

Downlink 其實會比預期的還要有用,除了可以根據網路速度決定回傳的圖片大小外,還可以根據 downlink 大小來決定要回傳的 CSS,實際上使用可能像是,網路慢的時候就給出比較輕量的 CSS 回去給 client 端,用不一樣的版面呈現給使用者,有點像是 Google 的Accelerated Mobile Pages Project所做的。

Client hint header 是個需要 opt-in 的擴充功能,就是預設是沒開的,那要怎麼開啟呢,就是在網頁 document 的 header 加上Accept-CH

Accept-CH: "DPR, Downlink"

或是加上 meta tag

<meta http-equiv="Accept-CH" content="DPR, Width, Viewport-Width">

其中 equiv 是 equivalent 意思,就是和 HTTP header 等效的意思,透過這個 header 跟瀏覽器說 server 端可以接收 client hint 資訊,然後支援的瀏覽器就會在後續,這個網頁所需要用到的其它資源,像是 js, css, 圖片等等的 request 都加上這些資訊,這個溝通過程其實就是使用已經很久的機制:HTTP content negotiation,用的 header 也是Accept開頭的,目前已經支援的還只有 Chrome,而且要 46 版以後,其他幾個瀏覽器大多都還在討論要不要支援,Firefox 是有一些進度

這樣的設計其實有點先進,不完全是褒意,因為這意味著要 server 端,負責提供圖片的服務器,收到 request 後去看 DPR 或是 width 之類的資訊再來挑選要回傳哪一張圖片回去,而通常提供圖片靜態檔案的服務都不太有邏輯處理,大部分就是簡單的 HTTP server,只看靜態檔案,有就傳檔案回去,沒有就回傳 404,相信之後是會有些 module 或是設定的方法讓 HTTP server 可以把這部分直接處理掉,不過一些規模比較大的網站,如果有用上 CDN 的,可能就沒法直接用上這功能,還要等看有沒有 CDN 廠商支援。

Client hint 目前看來會是 responsive image 未來的一個主要解法,和 media query 相比其實有兩個很大的差異,第一個是 media query 是馬上(且隨時)發生效果,和 HTTP request 是無關的,所以一開始下載下來的網頁就會發生效果,但是 client hint 要透過第一個 HTML document 本身的 request 進行溝通,意味著 HTML document 本身的 request 是不會收到 client hint。第二個就是 media query 是隨時發生作用的,即使在網頁完整讀取下來後,還是有可能因為使用者造成的 client 環境變化,而讓瀏覽器去多下載一份檔案,最常見的情形就是調整視窗大小,在手機上可能就是轉直轉橫造成 viewport 寬度變化,甚至在 Mac 如果外接普通螢幕,拖拉瀏覽器視窗到不同螢幕也會造成影響,如果這些變化剛好符合設定的 media query,DPR 從 1 變成 2,就會讓瀏覽器又去下載了一張 DPR 不同的圖片,這類狀況在網路頻寬有限的環境下實在不是好事,而用 client hint header 的話就完全不會有這種狀況了,就只會有一開始帶著 Client Hint 去抓下來的那個檔案。

不過 Client Hint 也不是完全沒有副作用,目前最大的問題就是這幾個新 header 都不列在simple headers裡面,所以在做 CORS request 的時候,本來不用 preflight request 的都會變成需要 preflight request 了,這個問題其實現在還在討論,因為其實有很多類似的新 header 都會造成一樣的問題,像是 CSP、Server-Sent Events 裡面的 Event-ID,主要是這麼多 Header 進去,就不 simple 了,而且照最近標準發展的狀況來看,這份 simple headers 的清單很難固定不變,有興趣的可以跟一下討論


srcset

Responsive Image 大概定案成srcset<picture>都有了,src-N 已經消失,雖然我還蠻喜歡,不過總之最近發現srcset和我當初介紹時已經差蠻多,中文資源有找到 Zhusee 有另外一篇介紹,不過其實我去看現在的 spec 的時候發現,又有些修改了!最早 srcset 後面是用類似 media query 的設計,後來改成對圖片的 metadata,spec 裡面稱為 descriptor,分別有 width descriptor 用w和 density descriptor 用x,而且限制 srcset 裡面只能用同一種 descriptor,例如全部用x或是全部用w,所以:

  1. 不能在一張圖片裡面同時有wx
  2. 全部都用w或是全部都用x
  3. 不可有相同的數值,例如兩個1x或是兩個760w
  4. Descriptor 可以算是該圖片的資訊
閱讀「srcset」全文

Resource Hints

Resource Hints是最近剛公開的一個 W3C Working Draft,目前看作者都是 Google 的人,Resource Hints 是依附在<link>標籤或是 header 下的,用來告訴瀏覽器有哪些資源可以先讀好的一個慣例語法,範例如下:

<link rel="preconnect" href="//example.com">
<link rel="preconnect" href="//cdn.example.com">
<link rel="preload" href="/assets/font.woff" as="font" loadpolicy="next">
<link rel="preload" href="/assets/logo.webp" as="image" loadpolicy="next inert">

可以發現有兩種 hint,分別是preconnectpreload,當然就照字面上的意思就可以理解了,preconnect就是先建立好連線,像是 HTTPS 連線就需要先做 handshake 交換好加解密用的 key,影響比較直接,preload當然就是先把特定的檔案拉下來,而且還可以指定要不要先做處理,像是 decode jpg 圖檔之類的動作可以推遲到真的需要圖片時才做。

目前看起來是不適合大量的檔案,應該還是要用來指派較關鍵的一些檔案,像是主要背景、大圖、字形之類的,而且因為可以根據設定 block onload event,拿來讀字形似乎可以避免 FOUT 的狀況,感覺是個看似簡單,但是功能其實還蠻多的新東西。


RGBA_ 控字慾

昨天去參加了 RGBA 很久沒辦的活動,這次主題是字體,剛好是我很有興趣的議題,所以從一開始就很想參與,結果報名時竟然忘記,而且還連續兩次都忘記了,想不到活動當天 hlb 沒辦法過去,我就順利的接手他的票了,然後覺得應該分享一下,所以就有了這篇文章。

RGBA_ 控字慾

一開始是由 Jason 的手寫西文毛筆字開始,我有拍些照片也錄了一段影片:

一直覺得寫這種字體用的筆很有趣,根本就是一片鐵片,要控制的好讓出墨平均應該需要不少練習吧,

接著就是 Even 介紹他挑選字形的方法,因為他基本上都是挑選黑體來用比較多,不過黑體也分很多種,所以先介紹了不同黑體的差異,基本上就是黑體字並不是所有都侷限現在框框內的,筆劃也不是都方方正正的,例如蒙納黑和 Arial Unicode MS 的底就不平,所以字體本身可能是有點歪斜的。

喇叭口

另外一種變化可以稱為喇叭口,也就是上圖那樣,在筆劃末端會放大,這種黑體比較適合小字使用,喇叭口可以讓視覺上感覺筆會比較粗,但是又不會影響整體的灰度,例如 Hiragino 這個 OSX 內建的日文字體。如果不要喇叭口的話可以選華康黑,華康黑又有一個特別的地方是他的一些筆劃是有裝飾的,我本來以為黑體就是不會有這些裝飾元素的,真是沒想到啊。最後講到信黑體,信黑體就是非常標準,文字侷限在方框內,灰度平均,沒有裝飾的黑體。然後 Even 還有用fontshop這個網站和Sketch示範一下不同字重的搭配。

RGBA_ 控字慾

接下來聽的是 but 介紹 OpenType 特殊功能和他做的一些實驗,OpenType 的規範有定義一些在西文排版上已經存在很久的功能,例如連字 Ligatures。

Ligatures

OpenType 有的功能時很很多,微軟有份文件有列出,據 but 說,OpenType 是微軟Adobe合作產出的,我後來搜尋一些相關資料時發現微軟有不少文件,可惜 IE 對於 OpenType feature 的支援卻落後不少,Firefox 和 Chrome 都已經支援一陣子了,雖然目前都還算是實驗中的功能, but 有用這些功能和他自己製作的字形弄了兩個實驗網站,兩個其實都是用連字辦到的,第一個是完全用文字把日本的火車時刻表做出來,這樣做除了畫面呈現上可以和紙本一樣,SEO 也會表現的比插入 icon 來的好,當然親和力也自動跟著提昇,第二個則是注音字形,可以邊打拼音邊顯示你輸入的注音符號,然後另外還做一個反向的,可以打注音拼音,兩個 demo 都蠻有趣的,而且可以在頁面上玩玩看連字。

另外因為有提到 emoji,因為 emoji 是彩色的,目前各家實做不一樣,蘋果是塞圖進字形、Firefox 我忘了,然後微軟是用多個圖層來處理多色的問題,所以我問了一下去年看過的 SVG in OpenType 的相關資訊,可惜 but 沒接觸過,後來我去搜尋看看到底這神秘的東西是誰推出來的,因為把 SVG 放進去字形裡面不是單純只是向量的彩色圖片,所有 SVG 可以做的事情都可以辦到,例如動畫之類的。總之發現是 Mozilla 開始這計畫的,在 W3C 有community,Adobe 的網站也有介紹過,應該不會是個孤兒格式才是,目前好像轉轉進到 MPEG 組織下維護了,Open Type 有個很神秘的地方是它現在是由 MPEG 組織來維護,屬於MPEG-4檔案格式的一部分,真是令不解的狀況啊~

最後比較可惜的是 Vertical Rhyme 沒聽到,不知道之後會不會放出投影片(but 的投影片也想要啊),主要想聽的主題就差那個而已,有一些特別去聽的就是之前已經在別的場合聽過了,整體來說這次收穫算是很多的,最後還是要感謝一下辦活動的 Even 和突然沒辦法去的布丁了,然後就看一下當天的盛況吧。

RGBA_ 控字慾

RGBA_ 控字慾

RGBA_ 控字慾


object-fit

在一些情境下,網站的圖片來源可能無法和版面很契合,例如新聞網站,新聞的照片可能有直的橫的,甚至有不同的寬高比,但是網站的版面配置不可能配合所有的可能性,如果想要有個封面故事,又要個滿版的照片,又或者是提供給 Facebook 的照片,它的縮圖都是正方形的,但是大部分的時候,文章的照片都不會是這種比例,最理想是有個 server 端的程式可以幫忙把圖片轉成想要的大小,例如 Facebook 其實是有個程式來作這件事,包括調整大小、重新壓縮、快取,大概連雲端分散式儲存的部份等等問題都一口氣處理掉了。

如果要純前端處理,其實目前最好用的作法是用CSS3 Backgroundbackground-size: cover;,這個樣式會讓標籤的背景圖調整成剛好可以填滿元素大小的程度,當然也考慮好寬高比了,這個方法最主要的缺點在於把圖片從 HTML 文件中抽掉了,在語意上不太好,像是搜尋引擎之類的,對於<img>和 CSS 背景的處理應該還是會有差異的,例如 Google 圖片搜尋我就沒印象有找到 CSS 的背景圖過。

要維持<img>標籤的存在,又要不管大小和寬高比都可以滿版,在現在是只能用 JavaScript 來輔助,實際上的邏輯也不會太複雜,其實就是比較一下版面的寬高比和圖片的寬高比,然後決定用外框的寬還是高當基準,接著維持圖片的寬高比縮放到計算的大小,定位到讓圖片置中,寫成 jQuery plugin 大概像是下面這樣:

$.fn.cover = (selector) ->
  $(@).each ->
    $outer = $(@)
    ow = $outer.width()
    oh = $outer.height()
    or = ow / oh
    $outer.find(selector).each ->
      $item = $(@)
      iw = $item.width()
      ih = $item.height()
      ir = iw / ih
      if ir < or
        w = ow
        h = ow / ir
        l = 0
        t = (oh - h) / 2
      else
        h = oh
        w = oh * ir
        t = 0
        l = (ow - w) / 2

      $item.css(width: w, height: h, top: t, left: l)

使用範例:

$('.cell').cover('img')

不過實際上還要考慮的問題不少,像是執行的時間點,上面這個範例可以運作的時間不只要圖片讀好,有正確的寬高之外,.cell或是說$outer也要在頁面上顯示,有 render 過,才能夠取得它的寬高,整個函式才能夠正確的運作,結果就是訪客其實會看到一瞬間圖片調整好大小位置前的樣子。

用 JavaScript 加上<img>這個方案的缺點除了上面說的之外,還有一個是會需要多一層的標籤,不過目前還是很多人會使用這個方案,也有不少 Library 在處理這個問題,像是fit.js

這個問題,其實在未來就不存在了,CSS3 Image 裡面有個新的樣式定義就是為了處理這個問題,叫做object-fit,可以想像成讓<img>標籤可以用 background-image 的方式來操控裡面的圖面了,而對應background-size的,就是object-fit了,未來可以這樣寫 HTML:

<img src="http://blah.com/blah.png" class="cover" width="300" height="300" />

配上 CSS:

img.cover {
  object-fit: cover;
}

就可以同時達到不用多一層標籤,又有實際的<img>,加上不用 JavaScript,不用考慮 resize 圖片的時機,非常的完美,不過這個新標準目前實作的瀏覽器不多,只有 Chrome 和換成 WebKit 前的 Opera,Opera 的 blog 也有發表過一篇文章介紹這個新屬性:CSS3 Object Fit Object Position,裡面也有不少範例可以用 Chrome 開來試試看。

要說有什麼缺點的話,其實還是有的,就是這個 object-fit 不是排版用的,只能用在圖片上,不像 JavaScript library 基本上是什麼元素都可以調整,沒有受限。


More Twitter Cards

進入本題前,先岔題到 open graph 一下,就是前兩天才注意到要用Open Graph protocol的話,其實在 html 裡面要加上prefix="og: http://ogp.me/ns#"的屬性和值:

<!DOCTYPE html>
<html
    xmlns="http://www.w3.org/1999/xhtml"
    lang="zh-tw"
    prefix="og: http://ogp.me/ns#"
>

這個 prefix 屬性其實是RDFa來的,所以其實 Open Graph Protocol 也是走 RDFa 系統,Twitter Card 就比較沒走的這麼語意網了。

這篇其實是要說 Twitter Card 的更新,首先是卡片的種類變多了,在一開始只有 Photo、Summary 和 Player 三種,現在則又多了 App、Product、Gallery 和 Summary Large Image 四種。

Twitter Card

其中 App 還蠻早就有了,以前如果貼 iTunes Store 連結的話就可以看到,只是一開始沒開放申請的樣子,新的幾種卡片我最想要的其實是 Summary Large Image,這個其實就是最早的 Photo 卡片的樣子,和 Photo 其實只差 description,我一開始會偷用 Photo 卡片來讓文章的圖片比較大,只是他們後來改成不會顯示我提供的文章摘要,直到前幾天才發現有新的 Summary Large Image,完全就是當初的 Photo 卡啊,所以看到就立馬申請下去。

申請的過程和以前也不一樣了,現在是在卡片測試工具那邊先測試,如果驗證格式沒問題就會出現黃色的通知和申請鈕可以按下去,如果是已經申請通過的話就會是綠色的。還有就是測試工具也多了組出 sample code 的功能,還算蠻不錯的,有些比較複雜的卡片格式就可以利用這個工具來搞清楚。

Twitter Card


Scrolling Performance

元旦就是要來發篇技術文章的啦。

一直覺得我的 blog 在 scroll 的時候好像不是很順暢,把之前亂加的 parallax 特效拿掉也沒什麼改善,於是週末花了些時間研究了一下,其實要改進捲動時效能可以作的事情大概就是那些,Fixing a parallax scrolling website to run in 60 FPS這篇文章有整理成條目:

  1. Resize、scroll 事件不要在迴圈內綁
  2. Resize、scroll 事件的 handler 用 requestAnimationFrame 來執行
  3. 避免 resize 大張圖片
  4. 避免 background-size

HTML5 Rocks 的Scrolling Performance這篇文章則是介紹如何分析網站捲動的效能,也有提到一些上面那篇文章沒講到的項目,像是避免 repaint,避免一些計算比較昂貴的 style 等。另外最近還有一個很有名的hack,是在捲動時,使用pointer-events: none;來避免元件產生 hover 的特效結果增加畫面 painting 的運算。

在講我遇到的問題前想先來說一下下面這張圖怎麼看:

Scroll cause image resize

這張圖是 Chrome 的內建開發工具,目前要作 performance tuning 最好的工具還是 Chrome 開發工具的這個 Timeline 和 Profile,網路上找的到的相關資源也是以 Chrome 為主。這張圖的上半是 framerate 的狀態表示,上面的綠色 bar 代表的是生成畫面前運算執行的時間,所以是越短越好,可以看到那個區塊有兩條橫線,右邊寫了 30fps 和 60fps,意思是執行時間只要能壓在那條線下面,就可以讓頁面有該 frame rate 的表現。下半部就可以拉近去細看不同時間點做了哪些事情,像是圖片 decode、resize、事件的 callback 執行等等都可以分辨。

使用這個開發工具來看到底是那邊計算很花時間,結果發現一直有 image resize 的運算在發生,即使我的圖片都已經全部讀好,頁面從頭卷到尾過,只要從新捲動就會發現 Chrome 又重新把 resize 過的 image 再 resize 一次,後來同事Linmic寫了 test case 來測試各種定義圖片寬高的方法:

  • <img>width/height 屬性
  • CSS 相對長度定義(百分比、em)
  • CSS 絕對長對定義(px)
  • CSS 背景圖 + background-size

等等,結果發現只有第一個方法圖片不會因為頁面捲動而需要重新 resize,簡單說就是,如果圖片的寬高是用到 CSS 的定義來決定的話,那在 Chrome 下就會有個 bug 是,頁面捲動時,即使圖片尺寸沒有變過,Chrome 還是會重新去 resize。根據目測,這問題在 Firefox 和 Safari 上是沒有的樣子,Chrome 的差距比較大,而且現在因為 responsive design 的關係,文章內的插圖很多寬高都是相對的寬高,像是很多人用的Bootstrap就是這樣,其實影響的範圍蠻廣的,而且找不到方法可以避開,搜尋一下看起來是有一張issue,希望能夠早點修復啊。


此類別所有文章