修改 HTML5 網站

Eric Bidelman

簡介

開發行動版網站是現今的熱門話題。今年,智慧型手機數量已突破極限,有越來越多使用者透過行動裝置瀏覽網路,因此開發人員若要針對行動瀏覽器最佳化網站,將成為開發人員的一大重點。

對大量開發人員而言,「行動」戰場仍然很陌生。許多人將現有的舊版網站完全忽略行動裝置使用者。相反地,網站是專為電腦瀏覽而設計,在行動瀏覽器中的效能不佳。此網站 (html5rocks.com) 也不例外。我們推出行動版網站時

建立適合行動裝置瀏覽的 html5rocks.com

根據我目前的練習,如果採用 html5rocks (現有的 HTML5 網站),再擴充適合行動裝置的版本,成效會很有趣。我主要在意智慧型手機鎖定所需的最低工作量。我的運動目標是建立全新的行動版網站,並維護兩組程式碼集。這可能算是永久性的,並浪費時間。我們已經定義網站的結構 (標記)。我們有了外觀和風格 (CSS) 設計而核心功能 (JS)。其中許多景點都位於同一船上

本文將介紹我們如何打造針對 Android 和 iOS 裝置最佳化的 HTML5rocks 行動版。只要在支援其中一種作業系統的裝置上載入 html5rocks.com,就可以看到差異。 不會重新導向到 m.html5rocks.com 或其他這類的惡意內容。和 html5rocks 一樣,另外還有一項優點,那就是 內容美觀、適合在行動裝置上使用。

電腦 html5rocks.com 行動版 html5rocks.com
在電腦 (左側) 和行動裝置上顯示 html5rocks.com (右側)

CSS 媒體查詢

HTML4 和 CSS2 支援媒體相依樣式表。例如:

<link rel="stylesheet" media="print" href="printer.css">

都會指定列印裝置,並在列印頁面時提供特定樣式。CSS3 更深入地瞭解媒體類型,並透過媒體查詢提升成效。媒體查詢可讓樣式表更準確地加上標籤,進而提升媒體類型的實用性。如此一來,就能根據特定範圍的輸出裝置自訂內容的呈現方式,不必變更內容本身。音效非常適合用於需要修改的現有版面配置!

您可以在外部樣式表的 media 屬性中使用媒體查詢,指定螢幕寬度、裝置寬度、方向等。如需完整清單,請參閱「W3C 媒體查詢規格」。

指定螢幕大小

在以下範例中,phone.css 會套用至瀏覽器視為「手持裝置」或螢幕寬度小於 320 像素的裝置。

 <link rel='stylesheet'
  media='handheld, only screen and (max-device-width: 320px)' href='phone.css'>

如果在媒體查詢前面加上「only」關鍵字,會導致非 CSS3 相容瀏覽器忽略這項規則。

以下程式碼會指定 641 像素到 800 像素之間的螢幕尺寸:

 <link rel='stylesheet'
  media='only screen and (min-width: 641px) and (max-width: 800px)' href='ipad.css'>

媒體查詢也可以顯示在內嵌 <style> 標記中。下列函式會在直向螢幕方向指定 all 媒體類型:

 <style>
  @media only all and (orientation: portrait) { ... }
 </style>

media="handheld"

我們需要暫停一點並討論 media="handheld",事實上,Android 和 iOS 會忽略 media="handheld"。該聲明就是使用者會遺漏以 media="screen" 為目標的樣式表提供的高階內容,且開發人員較不可能維護低品質的 media="handheld" 版本。因此,在「完整網路」座右銘中,大多數的現代智慧型手機瀏覽器都只會忽略手持式樣式表。

這個功能非常適合用來指定行動裝置,但各種瀏覽器已採用不同的實作方式:

  • 有些只會讀取手持樣式表。
  • 如果有手持樣式表的話,有些人只會讀取,但預設為螢幕樣式表。
  • 有些人會同時讀取手持樣式表和螢幕樣式表。
  • 部分只有讀取畫面樣式工作表。

Opera Mini 不忽略 media="handheld"。讓 Windows Mobile 辨識 media="handheld" 的秘訣是將螢幕樣式表的媒體屬性值大寫:

 <!-- media="handheld" trick for Windows Mobile -->
 <link rel="stylesheet" href="screen.css" media="Screen">
 <link rel="stylesheet" href="mobile.css" media="handheld">

HTML5rocks 如何使用媒體查詢

媒體查詢在行動 HTML5 環境中使用率相當高。這些方法讓我們可以調整版面配置,而無需大幅變更 Django 範本標記...真正的救星!此外,對各種瀏覽器的支援功能也很不錯。

在每個網頁的 <head> 中,您會看到下列樣式表:

 <link rel='stylesheet'
  media='all' href='/static/css/base.min.css' />
 <link rel='stylesheet'
  media='only screen and (max-width: 800px)' href='/static/css/mobile.min.css' />

base.css 一向定義了 html5rocks.com 的主要外觀和風格,但現在我們會針對低於 800 像素的螢幕寬度套用新樣式 (mobile.css)。這項媒體查詢涵蓋智慧型手機 (約 320 像素) 和 iPad (約 768 像素),效果:我們會逐步覆寫 base.css 中的樣式 (僅必要時),讓內容在行動裝置上看起來更美觀。

mobile.css 強制執行的部分樣式變更:

  • 減少網站上多餘的空白字元/邊框間距。小螢幕意味著空間所費不貲!
  • 移除 :hover 狀態。觸控裝置一律不會顯示這些錶面。
  • 將版面配置調整為單一資料欄。稍後會再詳細討論。
  • 移除網站主要容器 div 周圍的 box-shadow。大型方塊陰影會降低網頁效能。
  • 使用 CSS Flexbox 模型 box-ordinal-group,變更首頁上每個區段的順序。您會注意到,首頁上的「教學」部分位於「教學」部分之前,而是位於行動版首頁之後。這種順序比較適合行動裝置,也不需要變更標記。CSS Flexbox FTW!
  • 移除 opacity 項變更。變更 Alpha 值對行動裝置成效很有幫助。

行動中繼標記

行動網路 Kit 支援一些功能,可在特定裝置上為使用者提供更優質的瀏覽體驗。

可視區域設定

第一個中繼設定 (以及您最常使用的中繼設定) 是可視區域屬性。 設定可視區域後,瀏覽器就能知道內容在裝置螢幕上的適合程度,並告知瀏覽器網站已針對行動裝置進行最佳化處理。例如:

 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">

指示瀏覽器將可視區域設為裝置的寬度,初始比例為 1。本例也允許縮放,讓網站 (而非網頁應用程式) 可能更需要。我們可避免使用 user-scalable=no 縮放,或者將縮放比例限制在特定的等級:

 <meta name=viewport
  content="width=device-width, initial-scale=1.0, minimum-scale=0.5 maximum-scale=1.0">

Android 擴展可視區域中繼標記,可讓開發人員指定要開發網站適合哪種螢幕解析度:

 <meta name="viewport" content="target-densitydpi=device-dpi">

target-densitydpi 可能的值為 device-dpihigh-dpimedium-dpilow-dpi

如要針對不同的螢幕密度修改網頁,請使用 -webkit-device-pixel-ratio CSS 媒體查詢和/或 JavaScript 中的 window.devicePixelRatio 屬性,然後將 target-densitydpi 中繼標記設為 device-dpi。這種做法可避免 Android 針對您的網頁執行縮放作業,並允許您透過 CSS 和 JavaScript 為每個密度進行必要的調整。

如要進一步瞭解如何指定裝置解析度,請參閱 Android 的 WebView 說明文件

全螢幕瀏覽

除了 iOS-sfic 之外,還有兩種中繼值。apple-mobile-web-app-capableapple-mobile-web-app-status-bar-style 會在應用程式類似全螢幕模式下轉譯網頁內容,並將狀態列設為半透明:

 <meta name="apple-mobile-web-app-capable" content="yes">
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">

如要進一步瞭解所有可用的中繼選項,請參閱 Safari 參考說明文件

主畫面圖示

iOS 和 Android 裝置也接受連結的 rel="apple-touch-icon" (iOS) 和 rel="apple-touch-icon-precomposed" (Android)。當使用者將你的網站加入書籤時,會在使用者的主畫面上看到一個與應用程式相似的圖示:

 <link rel="apple-touch-icon"
      href="/static/images/identity/HTML5_Badge_64.png" />
 <link rel="apple-touch-icon-precomposed"
      href="/static/images/identity/HTML5_Badge_64.png" />

html5rocks 如何使用行動中繼標記

總而言之,以下是 html5rocks 的 <head> 區段的程式碼片段:

 <head>
  ...
   <meta name="viewport"
        content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />

   <link rel="apple-touch-icon"
        href="/static/images/identity/HTML5_Badge_64.png" />
   <link rel="apple-touch-icon-precomposed"
        href="/static/images/identity/HTML5_Badge_64.png" />
  ...
 </head>

垂直版面配置

在較小的螢幕上,垂直捲動會比水平捲動較為方便。將內容保持在單欄內,直向版面配置則適合行動裝置。針對 html5rocks,我們使用 CSS3 媒體查詢建立這種版面配置。同樣地,不須變更標記

教學課程索引。 教學課程 HTML5 功能頁面。 作者個人資料頁面。
整個網站中的單欄垂直版面配置。

行動裝置最佳化

我們所做的最佳化作業,大多都應一開始就完成。像是減少網路要求數量、JS/CSS 壓縮、gzipping (由 App Engine 免費提供),以及盡量減少 DOM 操縱性。這些技巧是常見的最佳做法,但有時候可能會遭到忽略。

自動隱藏網址列

行動瀏覽器的螢幕空間不足。為了在不同平台上造成效能更糟,有時即使頁面已載入完畢,畫面頂端也可能會顯示大型的網址列。

最簡單的處理方法就是使用 JavaScript 捲動頁面。即使只加一個像素,也能繼續處理煩人的網址列。如要在 html5rocks 上強制隱藏網址列,我已將 onload 事件處理常式附加至 window 物件,並將頁面垂直捲動一個像素:

網址列,
網址列會佔據螢幕空間。
  // Hides mobile browser's address bar when page is done loading.
  window.addEventListener('load', function(e) {
    setTimeout(function() { window.scrollTo(0, 1); }, 1);
  }, false);

我們也會納入這個事件監聽器為 is_mobile 範本變數,因為電腦版不需要。

減少網路要求,節省頻寬

目前已知減少 HTTP 要求數量可以大幅提升效能。行動裝置進一步限制瀏覽器可以同時進行的並行連線數量,因此能減少這類額外的要求,行動版網站的成效會更好。此外,切除每個位元組非常重要,因為手機頻寬通常有限。您可能需要支付費用!

為了盡量減少網路要求及降低 HTML5rocks 的頻寬,我們採用下列幾種方法:

  • 移除 iframe - iframe 運作緩慢!我們大量的延遲情況,是來自教學課程頁面上的第三方分享小工具 (Buzz、GoogleFriend Connect、Twitter、Facebook)。這些 API 是透過 <script> 代碼加入,而且建立的 iframe 會拖慢網頁載入速度。已移除行動版小工具。

  • display:none:在某些情況下,如果標記不符合行動裝置設定檔,我們會隱藏標記。首頁頂端的四個圓角方塊就是很好的例子:

首頁上的方塊按鈕。
首頁上的方塊按鈕。

缺少行動版網站。請務必記得,儘管其容器是以 display:none 隱藏,瀏覽器仍會為每個圖示發出要求。因此,僅隱藏這些按鈕並不足夠。這不僅會造成頻寬浪費,使用者甚至不會看見浪費頻寬的水果!解決方法是在 Django 範本中建立「is_mobile」布林值,以便有條件略過 HTML 的部分。 使用智慧型裝置查看網站時,畫面上不會顯示按鈕。

  • 應用程式快取 - 這不僅讓我們可以離線支援,還能加快啟動速度。

  • CSS/JS 壓縮 - 我們主要使用 YUI 壓縮工具,而不是 Closure 編譯器,主要原因是這麼做會處理 CSS 和 JS。我們遇到一個問題,就是內嵌媒體查詢 (在樣式表中的媒體查詢) 隱藏在 YUI 壓縮工具 2.4.2 中 (請參閱這個問題)。使用 YUI Compressor 2.4.4+ 修正問題。

  • 盡可能使用 CSS 圖片合併圖片。

  • 使用 pngcrush 進行圖片壓縮。

  • 針對小型圖片使用 dataURI。Base64 編碼會使圖片的大小增加約 30%以上,但會儲存網路要求。

  • 使用單一指令碼標記自動載入 Google 自訂搜尋,而非使用 google.load() 動態載入。後者則提出額外要求。

<script src="//www.google.com/jsapi?autoload={"modules":[{"name":"search","version":"1"}]}"> </script>
  • 我們的程式碼相當精緻印表機和 Modernizr (即使不曾使用) 在每一頁中。Modernizr 固然不錯,但會在每次負載上執行大量測試。有些測試會耗費大量成本修改 DOM,並減慢網頁載入速度。現在,我們只在需要的網頁中加入這些程式庫。-2 個要求 :)

其他效能調整:

  • 在可能的情況下,將所有 JS 移至頁面底部。
  • 已移除內嵌 <style> 標記。
  • 快取 DOM 查詢並盡量減少 DOM 操縱 - 每次您輕觸 DOM 時,瀏覽器都會執行「重排」。在行動裝置上,回流的成本也更高。
  • 將浪費浪費的用戶端程式碼卸載到伺服器。具體而言,系統會執行檢查以查看目前網頁的導覽樣式設定:js var lis = document.querySelectorAll('header nav li'); var i = lis.length; while (i--) { var a = lis[i].querySelector('a'); var section = a.getAttribute("data-section"); if (new RegExp(section).test(document.location.href)) { a.className = 'current'; } }
  • 寬度固定的元素已替換為浮動 width:100%width:auto

應用程式快取

行動版 html5rocks 使用應用程式快取加快初始載入,並允許使用者離線閱讀內容。

在網站上導入 AppCache 時,請勿快取您的資訊清單檔案 (無論是在資訊清單檔案中明確快取,或是透過大量快取控制標頭以隱含方式快取)。如果瀏覽器快取您的資訊清單,就難以進行偵錯。iOS 和 Android 可以特別妥善地快取這個檔案,但無法像電腦瀏覽器一樣方便清除快取。

為了防止我們的網站使用此類快取,我們首先將 App Engine 設定為永不快取資訊清單檔案:

- url: /(.*\.(appcache|manifest))
  static_files: \1
  mime_type: text/cache-manifest
  upload: (.*\.(appcache|manifest))
  expiration: "0s"

第二,在新的資訊清單下載完畢後,我們使用 JS API 通知使用者。系統會提示他們重新整理頁面:

window.applicationCache.addEventListener('updateready', function(e) {
  if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
    window.applicationCache.swapCache();
    if (confirm('A new version of this site is available. Load it?')) {
      window.location.reload();
    }
  }
}, false);

為節省網路流量,請簡化資訊清單。換句話說,請勿提及網站上的每個網頁只要列出重要的圖片、CSS 和 JavaScript 檔案即可。最後一個想要做的事,就是在每次應用程式快取更新時,強制行動瀏覽器下載大量資產。而是請注意,使用者造訪 HTML 網頁時,瀏覽器會以隱含方式快取 HTML 網頁 (且其中包含 <html manifest="..."> 屬性)。