# CSS3媒體查詢
響應式網站設計只有彈性布局這一個技巧是不夠用的,媒體查詢( media queries )也是響應式設計的核心技巧之一。媒體查詢是可應用于 CSS 樣式的簡單過濾器。有了這些過濾器,我們可以根據設備呈現內容的特點輕松更改樣式,包括顯示屏類型、寬度、高度、方向甚至是分辨率。

在 CSS2.1 中定義了媒體類型,通過給 <link> 元素添加 media 屬性,可以為不同的媒體類型加載不同的樣式表。
<link rel="stylesheet" href="main.css" media="screen">
媒體查詢( media queries )是對媒體類型( media types )的一次擴展,通常媒體類型會出現在鏈接 css 樣式文件的時候。媒體查詢可以為單個瀏覽器和設備類型指定不同的樣式,諸如視窗( viewport )寬度或者設備方向, 對設備的判斷能力進一步加強了。這種給不同設備使用其專屬樣式的能力,為響應式網站設計開啟了一片新的天地。
## 如何使用媒體查詢
那我們如何使用媒體查詢呢?這里有三種不同的使用方法
* 在已有樣式表中使用@media規則
* 使用@import規則導入一張新的樣式表
* 在HTML文檔中連接到一個獨立的樣式表文件
這里推薦使用在已有的樣式表文件中使用@media規則,避免增加額外的HTTP請求,導致網站性能下降。
1. Separate CSS File
<link href="main.css" rel="stylesheet" media="screen and (min-width: 480px)">
2. @media Rule
@media screen and (min-width: 480px) {...}
3. @import Rule
@import url(main.css) screen and (min-width: 480px) {...}
每一個媒體查詢可能會包含一個媒體類型,緊接著是一個或多個表達式。常見的媒體類型包括 all、screen、print、tv 和 braille。HTML5 規范包含了新的媒體類型,甚至包括三維眼鏡。若媒體查詢中沒有指定媒體類型,則默認為 screen。
媒體查詢表達式可能包含不同的媒體特性與值,表達式計算結果是 true 或 false。若結果為 true 的話,就會應用其包裹的樣式。若結果為 false,則忽略其包裹的樣式。
## 媒體查詢操作符
接著再來看看媒體查詢操作符,通過它可以構建強大的表達式,總共有三個邏輯操作符,分別是and、not和only。
在媒體查詢中使用 and 邏輯操作符可以添加新的表達式,并且瀏覽器或設備必須滿足列出的所有條件,才能執行相關的 css 樣式。多個媒體查詢之間用逗號分隔開。舉例說明,若選擇寬度介于800像素到1024像素之間的所有媒體類型,該如何表示呢?
@media all and (min-width: 800px) and (max-width: 1024px) {...}
not 邏輯操作符對后面的表達式取反操作。下面的示例,css 樣式將應用于非彩色屏幕的設備:
@media not screen and (color) {...}
only 邏輯操作符是一個新出現的運算符,使用 HTML4 算法的瀏覽器并不支持它,這樣一些較老的,不支持媒體查詢的瀏覽器就不能使用它所給定的樣式了。
@media only screen and (color) {...}
注意:
1. 當使用 not 和 only 邏輯操作符的時候,如果沒有指明媒體類型,則默認值為 all。
2. 媒體查詢是大小寫敏感的,若媒體查詢語句中包含未命名的媒體類型,則計算結果為 false。
## 媒體特征
雖然已經知道了媒體查詢的語法,邏輯操作符的用途,再來學習一下,真正起作用的媒體特征( media features )。在媒體查詢表達式中,媒體特征能夠識別設備的屬性。下面我們就介紹最常見的一個媒體特征,
就是用來確定設備或瀏覽器視窗( viewport )的高度和寬度。借助 height、width、device-height、device-width 媒體特征可以得到瀏覽器視窗( viewport )和設備的高度和寬度。其中的每一個媒體特征都可以加上前綴 min 或 max 標識符,從而構建一個新特征,比如 min-width 或 max-device-width。
這個 height 和 width 特征來自于視窗渲染區域的高度和寬度,比方說瀏覽器窗口。另外兩個,device-height 和 device-width 特征是基于輸出設備的高度和寬度的,可能要比實際的渲染區域大一些。這些代表高度和寬度的媒體特征,其值既可以用相對單位表示,也可以用絕對單位表示。
@media screen and (min-width: 320px) and (max-width: 780px) {...}
在響應式網站設計中,最常用的媒體特征包括 min-width 和 max-width。與設備特性區分開來,有助于在桌面或移動設備上建立風格一致的網站。
那為什么使用 min 和 max 前綴?
min 和 max 前綴可以用于相當多的媒體特征。min 前綴的意思是 “大于或等于”,max 前綴的意思是 “小于或等于”。使用 min 和 max 前綴,就不必使用 < 和 > 符號了,從而避免與普通的 html 語法產生沖突。
另外還有長寬比,像素比,分辨率,以及一些其他的媒體特征可供查詢。
## 瀏覽器對媒體查詢的支持情況
不幸的是,IE 8 及其之前的瀏覽器,還有其它一些比較老的瀏覽器,都不支持媒體查詢。然而,有兩個不錯的 javascript 庫可以解決這個問題。
Respond.js 是一個輕量級庫,它只查找 min/max-width 媒體特征,若網站中只使用了 min/max-width 媒體特征,那這個解決方案就是完美的。
CSS3-MediaQueries.js 是一個功能比較全,代碼量比較大的 js 庫,它能支持更多更復雜的媒體查詢語句。另外,始終要記住,使用 js 庫可能會帶來性能問題,減緩網站加載速度,所以要評估一下,是否值得犧牲網站性能來使用額外的 js 庫。
## 如何確定臨界點( Break Point )
使用media-query 最重要的是要確定“臨界點”,也就是頁面布局不得不做出改變的那個閾值。直觀上我們可能會這么想,嗯,設備基本有三類,手機,平板和桌面電腦。那我可以按照這三類設備寬度來設置臨界點(也有人翻譯為斷點)。但是實際上,對于此時此刻,這種想法其實是錯誤的。因為新的設備不斷涌現,各種寬度都會有的。參考 [google 的設備寬度圖表](https://www.google.com/design/tool/devices/)
正確的方式是,應該按內容設置斷點,而不是按設備寬度設置臨界點,所以無需考慮成千上萬的設備。具體的做法是,還是本著移動優先的思想,先考慮最小寬度的設備,例如 iphone6 ,來進行頁面布局。好,這個基本設計稿定下來之后,就可以來把屏幕往寬處拽了(可以使用 Chrome 瀏覽器的,移動設備調試工具來輔助這一過程)

直到我們看到,我們的內容看起來已經變得難看了,那么在這個位置,就要來設置一個臨界點了。
引用 Responsive Design Workflow 作者 Stephe Hay 的話來說:
>Start with the small screen first, then expand until it looks like shit. Time for a breakpoint!
>從你需要適配的最小屏幕寬度開始測試,慢慢地拉伸,當你發現頁面像坨屎的時候,一個新的斷點就確定了。
最好的方案是,先出手機版的頁面,這樣內容基本上都是單列布局的。接下來不斷拉伸寬度,每當內容看上去很難看松散了,這時候就要確定新的斷點,直到你所需要適配的最大屏幕寬度為止。最后,你會發現通過“按內容設置斷點”所使用的斷點數量遠比“屏幕分辨率確定斷點”要少。

來舉一個簡單的例子,比如在小屏幕設備上,我們希望字體是 16px 大小,但是到了大屏設備上我們希望字體也大一些,變成 18px ,那么如果把臨界點設置為 480px ,代碼就應該寫成這樣:
body {
font-size: 16px; /* 移動優先,這個默認值是為移動設備而生 */
}
@media (min-width: 500px) {
body {
font-size: 18px; /* 大屏設備 */
}
}
也有人提出了“主要臨界點”和“次要臨界點”的概念。例如我可以給我的頁面設置3個“主要臨界點”,每到一個,頁面結構就會有“大”的調整,例如內容由一列變為兩列。在兩個臨界點之間,有時候需要做一些小的頁面調整,比如改變一下按鈕大小,這樣可以通過設置“次要臨近點”來實現。
總之,并沒有一套“最佳臨近點”可以供每個網站都去使用,隨著內容不同,每個網站開發者要自己去“找”適合自己的各個臨近點。
## 參考資源
* [http://learn.shayhowe.com/advanced-html-css/responsive-web-design/](http://learn.shayhowe.com/advanced-html-css/responsive-web-design/)
* [定義臨界點](https://responsivedesign.is/strategy/page-layout/defining-breakpoints)
* [google&udacity 課程的“選擇斷點”章節](https://www.udacity.com/course/viewer#!/c-ud893/l-3533879576/m-3492369998)
* [http://bradfrost.com/blog/post/7-habits-of-highly-effective-media-queries/](http://bradfrost.com/blog/post/7-habits-of-highly-effective-media-queries/)