本文響應式開發中合理選定CSS媒體查詢分割點翻譯自David Gilbertson的The-100%-Correct-Way-To-Do-CSS-breakpoints一文。本文唔看上去有些拗口,不過其核心是在於給出合適的Media Query命名與編寫方式。
本文從屬於筆者的Web 前端入門與最佳實踐中的Web 響應式開發系列文章。css
在閱讀本文的時候,反而但願你能先忘卻關於CSS、Web開發那些你已經知道的東西,咱們今天討論的並非多麼複雜深奧的內容,若是你以爲準備好了那咱們能夠從下面這個簡單的點圖開始:
上面這些點分佈的有些隨意,分分合合,有近有遠,咱們的問題就是如何將這些點劃分入到五個組中。最簡單的,咱們能夠在那些相距較遠的兩個點之間設置爲分隔區劃分到不一樣的組合中。
上面這幾個圈都是我隨手畫出來的,你固然能夠選擇其餘的劃分方式,譬如將最右邊的兩個點劃分到一個分組中。其實這個問題並沒有所謂錯誤答案,不過若是你以以下方式劃分的話:
看上去是否是以爲怪怪的?我問這個問題也不是無中生有,當咱們須要爲不一樣尺寸的屏幕設置不一樣的CSS樣式稿時,會有人喜歡按照最多見的尺寸做爲分割點,即320px,768px與1024px。
不知道你有沒有聽過或者說過下面這些話:中等屏幕的話是否是按照768px來劃分?仍是應該把768px也劃分到中等屏幕的範圍內?不過這個尺寸是iPad橫屏狀態下的尺寸,應該算是大屏幕了吧?唔那大屏幕就是768px和以上尺寸咯?而後320px左右的是小屏幕?那319px算啥?區分螞蟻的嗎?本文的主旨即便討論如何選擇合適的分割點與分隔組。前端
你在幼兒園裏就會畫上面的這些圓吧,我如今用矩形度量來詳細闡述下:
咱們在這裏選擇了600px,900px,1200px以及1800px做爲分割點,這些分隔組包含了最多見的14個機型:
咱們把這兩張圖合併下,能夠得出下面這個更適合你的老闆、設計師、開發者以及測試人員看的一張圖:
git
你願意的話,也可使用Papa-Bear與Baby-Bear來稱呼你選定的分割點。不過當你和設計師一塊兒討論網站在不一樣屏幕上的展現效果時,確定但願雙方都可以在腦海中造成感性直觀的認知。若是你用平板豎屏尺寸來形容的話,那究竟是iPad仍是Surface呢?特別是如今這種手機愈來愈大,平板愈來愈小的狀況,你很難用單純的平板或者手機來劃分尺寸。不過好消息是蘋果已經不作新產品了,他們只是不斷地將按鈕、耳機口從如今的產品中移除。這邊我也很差給出什麼建議,只能說設計師和產品之間須要多多溝通。github
聲明式的概念在前端非常流行,譬如著名的React就是典型的聲明式組件庫。聲明式編程應用到CSS中便是CSS應當定義What it wants,而不是How it should。咱們上面討論過的一個關於分割點的容易混淆之處就是分割點同時表明了某個範圍。譬如$large:600px
這種定義在large
這個詞自己表明一個範圍值的時候就會混淆。所以在具體的某個組件或者標籤中,咱們應該對其隱藏具體的尺寸設置,譬如:編程
@mixin for-phone-only { @media (max-width: 599px) { @content; } } @mixin for-tablet-portrait-up { @media (min-width: 600px) { @content; } } @mixin for-tablet-portait-only { @media (min-width: 600px) and (max-width: 899px) { @content; } } @mixin for-tablet-landscape-up { @media (min-width: 900px) { @content; } } @mixin for-tablet-landscape-only { @media (min-width: 900px) and (max-width: 1199px) { @content; } } @mixin for-desktop-up { @media (min-width: 1200px) { @content; } } @mixin for-desktop-only { @media (min-width: 1200px) and (max-width: 1799px) { @content; } } @mixin for-big-desktop-up { @media (min-width: 1800px) { @content; } } // usage .my-box { padding: 10px; @include for-desktop-up { padding: 20px; } }
你會發如今上面的定義中我很推薦使用-up
與-only
後綴,在具體使用樣式的地方:segmentfault
.phone-only { @include for-phone-only { background: purple; } } .tablet-portait-only { @include for-tablet-portait-only { background: purple; } } .tablet-portrait-up { @include for-tablet-portrait-up { background: purple; } } .tablet-landscape-only { @include for-tablet-landscape-only { background: purple; } } .tablet-landscape-up { @include for-tablet-landscape-up { background: purple; } } .desktop-only { @include for-desktop-only { background: purple; } } .desktop-up { @include for-desktop-up { background: purple; } } .big-desktop-up { @include for-big-desktop-up { background: purple; } }
不過這種方式在須要大量自定義媒介查詢搭配的時候就顯得不是那麼靈活,咱們能夠提供更加細粒度的控制方式:佈局
@mixin for-size($size) { @if $size == phone-only { @media (max-width: 599px) { @content; } } @else if $size == tablet-portrait-up { @media (min-width: 600px) { @content; } } @else if $size == tablet-portait-only { @media (min-width: 600px) and (max-width: 899px) { @content; } } @else if $size == tablet-landscape-up { @media (min-width: 900px) { @content; } } @else if $size == tablet-landscape-only { @media (min-width: 900px) and (max-width: 1199px) { @content; } } @else if $size == desktop-up { @media (min-width: 1200px) { @content; } } @else if $size == desktop-only { @media (min-width: 1200px) and (max-width: 1799px) { @content; } } @else if $size == big-desktop-up { @media (min-width: 1800px) { @content; } } } // usage .my-box { padding: 10px; @include for-size(desktop-up) { padding: 20px; } }
這種方式天然可以達成預期的效果,不過若是某個粗心的開發者傳入了某個未預約義的範圍名,那麼久尷尬了,所以咱們仍是建議不要傳入某個具體的尺寸,而是傳入某個範圍:測試
@mixin for-size($range) { $phone-upper-boundary: 600px; $tablet-portrait-upper-boundary: 900px; $tablet-landscape-upper-boundary: 1200px; $desktop-upper-boundary: 1800px; @if $range == phone-only { @media (max-width: #{$phone-upper-boundary - 1}) { @content; } } @else if $range == tablet-portrait-up { @media (min-width: $phone-upper-boundary) { @content; } } @else if $range == tablet-portait-only { @media (min-width: $phone-upper-boundary) and (max-width: #{$tablet-portrait-upper-boundary - 1}) { @content; } } @else if $range == tablet-landscape-up { @media (min-width: $tablet-landscape-upper-boundary) { @content; } } @else if $range == tablet-landscape-only { @media (min-width: $tablet-portrait-upper-boundary) and (max-width: $tablet-landscape-upper-boundary - 1px) { @content; } } @else if $range == desktop-up { @media (min-width: $tablet-landscape-upper-boundary) { @content; } } @else if $range == desktop-only { @media (min-width: $tablet-landscape-upper-boundary) and (max-width: $desktop-upper-boundary - 1px) { @content; } } @else if $range == big-desktop-up { @media (min-width: $desktop-upper-boundary) { @content; } } } // usage .my-box { padding: 10px; @include for-size(desktop-up) { padding: 20px; } }