簡介
針對行動網路開發產品,是時下的熱門話題。今年,智慧型手機是首次售出電腦。使用行動裝置瀏覽網路的使用者越來越多,因此開發人員必須設法針對行動瀏覽器最佳化自己的網站。
對許多開發人員而言,「行動」戰場仍是未知領域。許多人現有的舊版網站完全忽略了行動裝置使用者。 相反地,該網站主要設計用於電腦瀏覽,在行動瀏覽器中顯示效果不佳。這個網站 (html5rocks.com) 也不例外。剛推出時,我們並不加工打造行動版網站。
建立行動裝置版 html5rocks.com
我認為,將 html5rocks (現有的 HTML5 網站) 改為行動裝置版會很有趣。我主要擔心鎖定智慧型手機 需要最少的工作量我的運動目標不是建立全新的行動版網站及維護兩個程式碼集。這個願景可無限發生 而且耗費大量時間我們已定義網站的結構 (標記)。我們曾經嘗試使用外觀和樣式 (CSS),其中的核心功能 (JS) 就是一例。重點是,許多網站都面臨同樣的問題。
本文將探討如何建立行動版 html5rocks,並針對 Android 和 iOS 裝置進行最佳化。只要在支援其中一個作業系統的裝置上載入 html5rocks.com,即可看到差異。不會重新導向至 m.html5rocks.com 或其他類似的惡作劇網站。您可以使用 html5rocks,而且還能享有在行動裝置上顯示效果佳且運作良好的額外優勢。
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 使用媒體查詢的方式
媒體查詢在行動版 html5rocks 中大量使用。我們可以調整版面配置,而不必大幅變更 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
變更首頁中每個區塊的排序。 您會發現,在首頁上,「LEARN BY MAJOR HTML5 FEATURE GROUPS」會出現在「TUTORIALS」專區之前,但在行動版中則是出現在後面。這種排序方式較適合行動裝置,不需要變更標記。CSS flexbox 讚! - 移除
opacity
變更。變更 alpha 值會影響行動裝置的效能。
行動版中繼標記
Mobile WebKit 支援一些實用功能,可為使用者提供更優質的瀏覽體驗。
可視區域設定
第一個設定 (也是最常用的設定) 是 viewport 屬性。設定可視區域,可讓瀏覽器瞭解內容應以何種方式顯示在裝置螢幕上,並告知瀏覽器網站已針對行動裝置進行最佳化。例如:
<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-dpi
、high-dpi
、medium-dpi
、low-dpi
。
如要針對不同螢幕密度修改網頁,請使用 -webkit-device-pixel-ratio
CSS 媒體查詢和/或 JavaScript 中的 window.devicePixelRatio
屬性,然後將 target-densitydpi
中繼屬性設為 device-dpi
。這樣 Android 就不會在網頁上進行縮放,讓您透過 CSS 和 JavaScript 針對各個密度進行必要調整。
如要進一步瞭解如何指定裝置解析度,請參閱 Android 的 WebView 說明文件。
全螢幕瀏覽
還有兩個 iOS-sfic 中繼資料值。apple-mobile-web-app-capable
和 apple-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 媒體查詢建立這種版面配置。同樣地,不變更標記。
行動最佳化
我們做出的大部分最佳化措施,都是原本就應該執行的。例如減少網路要求次數、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、Google Friend 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 manifest="...">
屬性) 隱含快取 HTML 網頁。