響應式佈局指的是同一頁面在不一樣屏幕尺寸下有不一樣的佈局。傳統的開發方式是PC端開發一套,手機端再開發一套,而使用響應式佈局只要開發一套就夠,缺點就是CSS
比較重。下面是博客網站對不一樣設備適配後的結果,分別是iPhone5/SE
,iphone6/7/8
,iphone 6/7/8 plus
,ipad pro
,dell臺式寬屏(1440 X 900)
。javascript
響應式設計與自適應設計的區別:響應式開發一套界面,經過檢測視口分辨率,針對不一樣客戶端在客戶端作代碼處理,來展示不一樣的佈局和內容;自適應須要開發多套界面,經過檢測視口分辨率,來判斷當前訪問的設備是pc端、平板、手機,從而請求服務層,返回不一樣的頁面。css
CSS3
媒體查詢可讓咱們針對不一樣的媒體類型定義不一樣的樣式,當重置瀏覽器窗口大小的過程當中,頁面也會根據瀏覽器的寬度和高度從新渲染頁面。html
如何肯定媒體查詢的分割點也是一個開發中會遇到的問題,下面是市場上的移動設備和電腦屏幕分辨率的分佈狀況,能夠發現不一樣品牌和型號的設備屏幕分辨率通常都不同前端
若是咱們選擇600px
,900px
,1200px
,1800px
做爲分割點,能夠適配到常見的14個機型:java
固然這只是其中的一種分割方案,咱們還能夠這樣劃分:480px
,800px
,1400px
,1400px
ios
而做爲曾經典型的響應式佈局框架,Bootstrap
是怎麼進行斷點的呢?css3
上面的分割方案不必定知足項目中的實際需求,咱們能夠先用跨度大的分割點進行分割,若是出現不適配的狀況能夠再根據實際狀況增長新的分割點。git
不論是移動優先仍是PC優先,都是依據當隨着屏幕寬度增大或減少的時候,後面的樣式會覆蓋前面的樣式。所以,移動端優先首先使用的是min-width
,PC端優先使用的max-width
。github
移動優先:web
/* iphone6 7 8 */
body {
background-color: yellow;
}
/* iphone 5 */
@media screen and (max-width: 320px) {
body {
background-color: red;
}
}
/* iphoneX */
@media screen and (min-width: 375px) and (-webkit-device-pixel-ratio: 3) {
body {
background-color: #0FF000;
}
}
/* iphone6 7 8 plus */
@media screen and (min-width: 414px) {
body {
background-color: blue;
}
}
/* ipad */
@media screen and (min-width: 768px) {
body {
background-color: green;
}
}
/* ipad pro */
@media screen and (min-width: 1024px) {
body {
background-color: #FF00FF;
}
}
/* pc */
@media screen and (min-width: 1100px) {
body {
background-color: black;
}
}
複製代碼
PC優先:
/* pc width > 1024px */
body {
background-color: yellow;
}
/* ipad pro */
@media screen and (max-width: 1024px) {
body {
background-color: #FF00FF;
}
}
/* ipad */
@media screen and (max-width: 768px) {
body {
background-color: green;
}
}
/* iphone6 7 8 plus */
@media screen and (max-width: 414px) {
body {
background-color: blue;
}
}
/* iphoneX */
@media screen and (max-width: 375px) and (-webkit-device-pixel-ratio: 3) {
body {
background-color: #0FF000;
}
}
/* iphone6 7 8 */
@media screen and (max-width: 375px) and (-webkit-device-pixel-ratio: 2) {
body {
background-color: #0FF000;
}
}
/* iphone5 */
@media screen and (max-width: 320px) {
body {
background-color: #0FF000;
}
}
複製代碼
經過百分比單位,可使得瀏覽器中組件的寬和高隨着瀏覽器的高度的變化而變化,從而實現響應式的效果。Bootstrap裏面的柵格系統就是利用百分比來定義元素的寬高,CSS3
支持最大最小高,能夠將百分比和max(min)
一塊兒結合使用來定義元素在不一樣設備下的寬高。
/* pc width > 1100px */
html, body { margin: 0;padding: 0;width: 100%;height: 100%;}
aside {
width: 10%;
height: 100%;
background-color: red;
float: left;
}
main {
height: 100%;
background-color: blue;
overflow: hidden;
}
/* ipad pro */
@media screen and (max-width: 1024px) {
aside {
width: 8%;
background-color: yellow;
}
}
/* ipad */
@media screen and (max-width: 768px) {
aside {
float: none;
width: 100%;
height: 10%;
background-color: green;
}
main {
height: calc(100vh - 10%);
background-color: red;
}
}
/* iphone6 7 8 plus */
@media screen and (max-width: 414px) {
aside {
float: none;
width: 100%;
height: 5%;
background-color: yellow;
}
main {
height: calc(100vh - 5%);
background-color: red;
}
}
/* iphoneX */
@media screen and (max-width: 375px) and (-webkit-device-pixel-ratio: 3) {
aside {
float: none;
width: 100%;
height: 10%;
background-color: blue;
}
main {
height: calc(100vh - 10%);
background-color: red;
}
}
/* iphone6 7 8 */
@media screen and (max-width: 375px) and (-webkit-device-pixel-ratio: 2) {
aside {
float: none;
width: 100%;
height: 3%;
background-color: black;
}
main {
height: calc(100vh - 3%);
background-color: red;
}
}
/* iphone5 */
@media screen and (max-width: 320px) {
aside {
float: none;
width: 100%;
height: 7%;
background-color: green;
}
main {
height: calc(100vh - 7%);
background-color: red;
}
}
複製代碼
可是咱們必需要弄清楚css中子元素的百分比究竟是相對誰的百分比。直接上結論吧:
子元素的height
或width
中使用百分比,是相對於子元素的直接父元素,width
相對於父元素的width
,height
相對於父元素的height
;子元素的top
和bottom
若是設置百分比,則相對於直接非static
定位(默認定位)的父元素的高度,一樣子元素的left
和right
若是設置百分比,則相對於直接非static
定位(默認定位的)父元素的寬度;子元素的padding
若是設置百分比,不管是垂直方向或者是水平方向,都相對於直接父親元素的width
,而與父元素的height
無關。跟padding
同樣,margin
也是如此,子元素的margin
若是設置成百分比,不管是垂直方向仍是水平方向,都相對於直接父元素的width
;border-radius
不同,若是設置border-radius
爲百分比,則是相對於自身的寬度,除了border-radius
外,還有好比translate
、background-size
等都是相對於自身的;
從上述對於百分比單位的介紹咱們很容易看出若是所有使用百分比單位來實現響應式的佈局,有明顯的如下兩個缺點:
width
和height
相對於父元素的width
和height
,而margin
、padding
無論垂直仍是水平方向都相對比父元素的寬度、border-radius
則是相對於元素自身等等,形成咱們使用百分比單位容易使佈局問題變得複雜。REM
是CSS3
新增的單位,而且移動端的支持度很高,Android2.x+,ios5+都支持。rem
單位都是相對於根元素html的font-size
來決定大小的,根元素的font-size
至關於提供了一個基準,當頁面的size發生變化時,只須要改變font-size
的值,那麼以rem
爲固定單位的元素的大小也會發生響應的變化。 所以,若是經過rem
來實現響應式的佈局,只須要根據視圖容器的大小,動態的改變font-size
便可(而em
是相對於父元素的)。
rem響應式的佈局思想:
rem
作單位(首先在HTML總設置一個基準值:px
和rem
的對應比例,而後在效果圖上獲取px
值,佈局的時候轉化爲rem
值)rem佈局的缺點:
在響應式佈局中,必須經過js來動態控制根元素font-size
的大小,也就是說css樣式和js代碼有必定的耦合性,且必須將改變font-size
的代碼放在css
樣式以前
/*上述代碼中將視圖容器分爲10份,font-size用十分之一的寬度來表示,最後在header標籤中執行這段代碼,就能夠動態定義font-size的大小,從而1rem在不一樣的視覺容器中表示不一樣的大小,用rem固定單位能夠實現不一樣容器內佈局的自適應。*/
function refreshRem() {
var docEl = doc.documentElement;
var width = docEl.getBoundingClientRect().width;
var rem = width / 10;
docEl.style.fontSize = rem + 'px';
flexible.rem = win.rem = rem;
}
win.addEventListener('resize', refreshRem);
複製代碼
REM
佈局也是目前多屏幕適配的最佳方式。默認狀況下咱們html標籤的font-size
爲16px,咱們利用媒體查詢,設置在不一樣設備下的字體大小。
/* pc width > 1100px */
html{ font-size: 100%;}
body {
background-color: yellow;
font-size: 1.5rem;
}
/* ipad pro */
@media screen and (max-width: 1024px) {
body {
background-color: #FF00FF;
font-size: 1.4rem;
}
}
/* ipad */
@media screen and (max-width: 768px) {
body {
background-color: green;
font-size: 1.3rem;
}
}
/* iphone6 7 8 plus */
@media screen and (max-width: 414px) {
body {
background-color: blue;
font-size: 1.25rem;
}
}
/* iphoneX */
@media screen and (max-width: 375px) and (-webkit-device-pixel-ratio: 3) {
body {
background-color: #0FF000;
font-size: 1.125rem;
}
}
/* iphone6 7 8 */
@media screen and (max-width: 375px) and (-webkit-device-pixel-ratio: 2) {
body {
background-color: #0FF000;
font-size: 1rem;
}
}
/* iphone5 */
@media screen and (max-width: 320px) {
body {
background-color: #0FF000;
font-size: 0.75rem;
}
}
複製代碼
css3
中引入了一個新的單位vw/vh
,與視圖窗口有關,vw
表示相對於視圖窗口的寬度,vh
表示相對於視圖窗口高度,除了vw
和vh
外,還有vmin
和vmax
兩個相關的單位。各個單位具體的含義以下:
單位 | 含義 |
---|---|
vw | 相對於視窗的寬度,1vw 等於視口寬度的1%,即視窗寬度是100vw |
vh | 相對於視窗的高度,1vh 等於視口高度的1%,即視窗高度是100vh |
vmin | vw和vh中的較小值 |
vmax | vw和vh中的較大值 |
用視口單位度量,視口寬度爲100vw,高度爲100vh(左側爲豎屏狀況,右側爲橫屏狀況)。例如,在桌面端瀏覽器視口尺寸爲650px,那麼 1vw = 650 * 1% = 6.5px(這是理論推算的出,若是瀏覽器不支持0.5px,那麼實際渲染結果多是7px)。
那麼vw或者vh很相似百分比單位。vw和%的區別爲:
單位 | 含義 |
---|---|
% | 大部分相對於祖先元素,也有相對於自身的狀況好比(border-radius、translate等) |
vw/vh | 相對於視窗的尺寸 |
從對比中咱們能夠發現,vw
單位與百分比相似,單確有區別,前面咱們介紹了百分比單位的換算困難,這裏的vw
更像"理想的百分比單位"。任意層級元素,在使用vw
單位的狀況下,1vw都等於視圖寬度的百分之一。
使用視口單位來實現響應式有兩種作法:
對於設計稿的尺寸轉換爲爲單位,咱們使用Sass
函數編譯
//iPhone 6尺寸做爲設計稿基準
$vm_base: 375;
@function vw($px) {
@return ($px / 375) * 100vw;
}
複製代碼
不管是文本仍是佈局寬度、間距等都使用vw
做爲單位
.mod_nav {
background-color: #fff;
&_list {
display: flex;
padding: vm(15) vm(10) vm(10); // 內間距
&_item {
flex: 1;
text-align: center;
font-size: vm(10); // 字體大小
&_logo {
display: block;
margin: 0 auto;
width: vm(40); // 寬度
height: vm(40); // 高度
img {
display: block;
margin: 0 auto;
max-width: 100%;
}
}
&_name {
margin-top: vm(2);
}
}
}
}
複製代碼
1物理像素線(也就是普通屏幕下1px,高清屏幕下0.5px的狀況)採用transform
屬性scale
實現
.mod_grid {
position: relative;
&::after {
// 實現1物理像素的下邊框線
content: '';
position: absolute;
z-index: 1;
pointer-events: none;
background-color: #ddd;
height: 1px;
left: 0;
right: 0;
top: 0;
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
-webkit-transform: scaleY(0.5);
-webkit-transform-origin: 50% 0%;
}
}
...
}
複製代碼
對於須要保持寬高比的圖,應該用padding-top
實現
.mod_banner {
position: relative;
padding-top: percentage(100/700); // 使用padding-top
height: 0;
overflow: hidden;
img {
width: 100%;
height: auto;
position: absolute;
left: 0;
top: 0;
}
}
複製代碼
雖然採用vw
適配後的頁面效果很好,可是它是利用視口單位實現的佈局,依賴視口大小而自動縮放,不管視口過大仍是太小,它也隨着時候過大或者太小,失去了最大最小寬度的限制,此時咱們能夠結合rem
來實現佈局
給根元素大小設置隨着視口變化而變化的vw
單位,這樣就能夠實現動態改變其大小
限制根元素字體大小的最大最小值,配合body
加上最大寬度和最小寬度
// rem 單位換算:定爲 75px 只是方便運算,750px-75px、640-64px、1080px-108px,如此類推
$vm_fontsize: 75; // iPhone 6尺寸的根元素大小基準值
@function rem($px) {
@return ($px / $vm_fontsize ) * 1rem;
}
// 根元素大小使用 vw 單位
$vm_design: 750;
html {
font-size: ($vm_fontsize / ($vm_design / 2)) * 100vw;
// 同時,經過Media Queries 限制根元素最大最小值
@media screen and (max-width: 320px) {
font-size: 64px;
}
@media screen and (min-width: 540px) {
font-size: 108px;
}
}
// body 也增長最大最小寬度限制,避免默認100%寬度的 block 元素跟隨 body 而過大太小
body {
max-width: 540px;
min-width: 320px;
}
複製代碼
這裏的圖片響應式包括兩個方面,一個就是大小自適應,這樣可以保證圖片在不一樣的屏幕分辨率下出現壓縮、拉伸的狀況;一個就是根據不一樣的屏幕分辨率和設備像素比來儘量選擇高分辨率的圖片,也就是當在小屏幕上不須要高清圖或大圖,這樣咱們用小圖代替,就能夠減小網絡帶寬了。
圖片自適應意思就是圖片能隨着容器的大小進行縮放,能夠採用以下代碼:
img {
display: inline-block;
max-width: 100%;
height: auto;
}
複製代碼
inline-block
元素相對於它周圍的內容之內聯形式呈現,但與內聯不一樣的是,這種狀況下咱們能夠設置寬度和高度。 max-width
保證了圖片可以隨着容器的進行等寬擴充(即保證全部圖片最大顯示爲其自身的 100%。此時,若是包含圖片的元素比圖片固有寬度小,圖片會縮放佔滿最大可用空間),而height
爲auto
能夠保證圖片進行等比縮放而不至於失真。若是是背景圖片的話要靈活運用background-size
屬性。
那麼爲何不能用width:100%
呢?由於這條規則會致使它顯示得跟它的容器同樣寬。在容器比圖片寬得多的狀況下,圖片會被無謂地拉伸。
<img srcset="photo_w350.jpg 1x, photo_w640.jpg 2x" src="photo_w350.jpg" alt="">
複製代碼
若是屏幕的dpi = 1的話則加載1倍圖,而dpi = 2則加載2倍圖,手機和mac基本上dpi都達到了2以上,這樣子對於普通屏幕來講不會浪費流量,而對於視網膜屏來講又有高清的體驗。
若是瀏覽器不支持srcset
,則默認加載src裏面的圖片。
可是你會發現實際狀況並非如此,在Mac上的Chrome它會同時加載srcset
裏面的那張2x的,還會再去加載src裏面的那張,加載兩張圖片。順序是先把全部srcset
裏面的加載完了,再去加載src的。這個策略比較奇怪,它竟然會加載兩張圖片,若是不寫src,則不會加載兩張,可是兼容性就沒那麼好。這個多是由於瀏覽器認爲,既然有srcset
就不用寫src了,若是寫了src,用戶多是有用的。而使用picture
就不會加載兩張
.banner{
background-image: url(/static/large.jpg);
}
@media screen and (max-width: 767px){
background-image: url(/static/small.jpg);
}
複製代碼
picturefill.min.js :解決IE等瀏覽器不支持 的問題
<picture>
<source srcset="banner_w1000.jpg" media="(min-width: 801px)">
<source srcset="banner_w800.jpg" media="(max-width: 800px)">
<img src="banner_w800.jpg" alt="">
</picture>
<!-- picturefill.min.js 解決IE等瀏覽器不支持 <picture> 的問題 -->
<script type="text/javascript" src="js/vendor/picturefill.min.js"></script>
複製代碼
picture
必需要寫img標籤,不然沒法顯示,對pictur
e的操做最後都是在img上面,例如onload事件是在img標籤觸發的,picture
和source
是不會進行layout的,它們的寬和高都是0。
另外使用source
,還能夠對圖片格式作一些兼容處理:
<picture>
<source type="image/webp" srcset="banner.webp"> <img src="banner.jpg" alt=""> </picture> 複製代碼
總結:響應式佈局的實現能夠經過媒體查詢+px
,媒體查詢+百分比,媒體查詢+rem
+js
,vm/vh
,vm/vh
+rem
這幾種方式來實現。但每一種方式都是有缺點的,媒體查詢須要選取主流設備寬度尺寸做爲斷點針對性寫額外的樣式進行適配,但這樣作會比較麻煩,只能在選取的幾個主流設備尺寸下呈現完美適配,另外用戶體驗也不友好,佈局在響應斷點範圍內的分辨率下維持不變,而在響應斷點切換的瞬間,佈局帶來斷層式的切換變化,如同卡帶的唱機般「咔咔咔」地一下又一下。經過百分比來適配首先是計算麻煩,第二各個屬性中若是使用百分比,其相對的元素的屬性並非惟一的,這樣就形成咱們使用百分比單位容易使佈局問題變得複雜。經過採用rem
單位的動態計算的彈性佈局,則是須要在頭部內嵌一段腳原本進行監聽分辨率的變化來動態改變根元素字體大小,使得CSS
與JS
耦合了在一塊兒。經過利用純css
視口單位實現適配的頁面,是既能解決響應式斷層問題,又能解決腳本依賴的問題的,可是兼容性尚未徹底能結構接受。
如今的css,UI框架等都已經考慮到了適配不一樣屏幕分辨率的問題,實際項目中咱們能夠直接使用這些新特性和框架來實現響應式佈局。能夠有如下選擇方案:
在實際項目中,咱們可能須要綜合上面的方案,好比用rem
來作字體的適配,用srcset
來作圖片的響應式,寬度能夠用rem
,flex
,柵格系統等來實現響應式,而後可能還須要利用媒體查詢來做爲響應式佈局的基礎,所以綜合上面的實現方案,項目中實現響應式佈局須要注意下面幾點:
參考文章: