總結5種自適應方式


 

特別說明:在開始這一切之前,請開發移動界面的工程師們在頭部加上下面這條meta:

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
復制代碼

一、百分比

.test{
    width: 20%
}
復制代碼
  • 優點

    • 代碼簡單
  • 缺點

    • 需要計算,很不方便

二、media query

  • 實現思路
@media screen and (min-width: 320px) and (max-width: 650px) { .class { float: left; }} @media screen and (min-width: 650px) and (max-width: 980px) { .class { float: right; }} @media screen and (min-width: 980px) and (max-width: 1240px) { .class { float: clear; }} @media screen and (device-width: 640px) { html { font-size: 12px; } } @media screen and (device-width: 750px) { html { font-size: 16px; } } @media screen and (device-width: 1240px) { html { font-size: 20px; } } 復制代碼
  • 優點

    • 僅需要寫css代碼
  • 缺點

    • 靈活性不夠,取每個設備的精確值需要自己去計算,所以只能取范圍值

    • 考慮設備屏幕眾多,分辨率也參差不齊,把每一種機型的css代碼寫出來是不太可能的

    • 只能選擇幾個主流設備呈現完美適配

    • 斷層式的切換變化

    • 代碼量大

三、vh/vw

  • 視口的解釋

在桌面端,視口指的是在桌面端,指的是瀏覽器的可視區域;而在移動端較為復雜,它涉及到三個視口:分別是 Layout Viewport(布局視口)、 Visual Viewport(視覺視口)、Ideal Viewport。 而視口單位中的“視口”,在桌面端,毫無疑問指的就是瀏覽器的可視區域;但是在移動端,它指的則是三個 Viewport 中的 Layout Viewport 。

  • 視口單位主要包括以下4個:
  1. vw : 1vw 等於視口寬度的1%
  2. vh : 1vh 等於視口高度的1%
  3. vmin : 選取 vw 和 vh 中最小的那個
  4. vmax : 選取 vw 和 vh 中最大的那個
  • 視口和%單位的區別:

視口單位區別於%單位,視口單位是依賴於視口的尺寸,根據視口尺寸的百分比來定義的;

%單位則是依賴於元素的祖先元素。

單位度量,視口寬度為100vw,高度為100vh(左側為豎屏情況,右側為橫屏情況)

例如,在桌面端瀏覽器視口尺寸為650px,那么 1vw = 650 * 1% = 6.5px(這是理論推算的出,如果瀏覽器不支持0.5px,那么實際渲染結果可能是7px)。

方法1:僅使用vw作為CSS單位

  • 在僅使用 vw 單位作為唯一應用的一種 CSS 單位的這種做法下,我們遵守:把設計稿的尺寸轉換為vw單位
//iPhone 6尺寸作為設計稿基准 $vm_base: 375; @function vw($px) { @return ($px / 375) * 100vw; } 復制代碼
  • 無論是文本還是布局高寬、間距等都使用 vw 作為 CSS 單位
.test {
    padding: vm(15) vm(10) vm(10); font-size: vm(10); } 復制代碼
  • 物理像素線(也就是普通屏幕下 1px ,高清屏幕下 0.5px 的情況)采用 transform 屬性 scale 實現。
.test {
    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 實現
.test {
    position: relative; padding-top: percentage(100/700); // 使用padding-top height: 0; //這個不能省 overflow: hidden; img { width: 100%; height: auto; position: absolute; left: 0; top: 0; } } 復制代碼

疑問插播:

  • 當margin-top、padding-top的值是百分比時,分別是如何計算的?

不管是margin-top/margin-bottom還是margin-left/margin-right(padding一樣),百分數是相對最近父級塊級元素的width計算

  • 為什么margin-top/margin-bottom的百分數也是相對於width而不是height呢?

CSS權威指南中的解釋:

正常流中的大多數元素都會足夠高以包含其后代元素(包括外邊距),如果一個元素的上下外邊距時父元素的height的百分數,就可能導致一個無限循環,父元素的height會增加,以適應后代元素上下外邊距的增加,而相應的,上下外邊距因為父元素height的增加也會增加,這樣就無限循環。

  • 一般使用padding-top:(percentage)實現響應式背景圖片,實現的基本原理?

實現的基本原理:利用百分比,保持元素的寬高比的技巧

比如一張圖片的寬度是1024px,高度為316px;那么現在的 padding-top = (高度 / 寬度 )* 100% = (316 / 1024)* 100% = 30.85%;

<div class="wrap">
     <div class="inner"></div>
</div>
.wrap{
        max-width: 1024px;
 }
 .inner {
         padding-top:30.85%; /* 316 / 1024 */
         background: url("http://images2015.cnblogs.com/blog/561794/201603/561794-20160310002800647-50077395.jpg") no-repeat;
          background-size:cover;
          background-position:center; //IE8及以下不支持background-size:cover屬性,為了兼容IE下面的瀏覽器
    }
復制代碼

方法一實現的頁面雖然看起來適配得很好,但是你會發現由於它是利用視口單位實現的布局,依賴於視口大小而自動縮放,無論視口過大還是過小,它也隨着視口過大或者過小,失去了最大最小寬度的限制,所以考慮結合rem來實現。

方法2:搭配vw和rem,布局更優化

  1. 給根元素大小設置隨着視口變化而變化的 vw 單位,這樣就可以實現動態改變其大小。
  2. 限制根元素字體大小的最大最小值,配合 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; } 復制代碼

相對於法一,個人比較推崇法二,有以下兩點原因: 第一,法二相對來說用戶視覺體驗更好,增加了最大最小寬度的限制; 第二,更重要是,如果選擇主流的rem彈性布局方式作為項目開發的適配頁面方法,那么法二更適合於后期項目從 rem 單位過渡到 vw 單位。只需要通過改變根元素大小的計算方式,你就可以不需要其他任何的處理,就無縫過渡到另一種CSS單位,更何況vw單位的使用必然會成為一種更好適配方式,目前它只是礙於兼容性的支持而得不到廣泛的應用。

方法3:搭配vw和vh

一屏的時候可以同時使用vw和vh作為css單位設置文本、布局高寬、間距、

  • 優點

    • 體驗好,純css
  • 缺點

    • 兼容性不好 (在移動端 iOS 8 以上以及 Android 4.4 以上獲得支持,在微信 x5 內核中得到支持)

四、rem

rem屬性指的是相對於根元素設置某個元素的字體大小。它同時也可以用作為設置高度等一系列可以用px來標注的單位。

  • 實現思路

假設我們UI設計的標准是iphone5s,iphone5系列的屏幕分辨率是640。為了統一規范,我們將iphone5 分辨率下的根元素font-size設置為100px;

html {
    font-size: 100px;
}
復制代碼

那么以此為基准,可以計算出一個比例值6.4。我們可以得知其他手機分辨率的設備下根元素字體大小,需要考慮到如果是移動設備,屏幕會有一個上下限制,可以控制分辨率在某個范圍內,超過了該范圍,我們就不再增加根元素的字體大小:

var deviceWidth = document.documentElement.clientWidth > 1300 ? 1300 : document.documentElement.clientWidth; document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px'; 考慮到,如果轉屏 window.onresize = _.debounce(function() { var deviceWidth = document.documentElement.clientWidth > 1300 ? 1300 : document.documentElement.clientWidth; document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px';}, 50); 復制代碼

在head中,我們將以上代碼加入,動態地改變根節點的font-size值。

如果是320分辨率設備,1px的邊框會被壓縮成0.5px,可以為不同的設備設置不同的meta

所以最終代碼為

<meta name="viewport" content="width=device-width,user-scalable=no,maximum-scale=1" /> <script type="text/javascript"> (function() { // deicePixelRatio :設備像素 var scale = 1 / devicePixelRatio; //設置meta 壓縮界面, 模擬設備的高分辨率 (淘寶和網易新聞的手機web端就是采用的是這種方式) document.querySelector('meta[name="viewport"]').setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no'); //為提高性能,增加節流函數 var reSize = _.debounce(function() { var deviceWidth = document.documentElement.clientWidth > 1300 ? 1300 : document.documentElement.clientWidth; //按照640像素下字體為100px的標准來,得到一個字體縮放比例值 6.4 document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px'; }, 50); window.onresize = reSize; })(); </script> <style type="text/css"> html { height: 100%; width: 100%; overflow: hidden; font-size: 16px; } 復制代碼
  • 優點

    • 不需要在不同的屏幕下調整樣式 (不額外增加css代碼)
  • 缺點

    • 改html中script參數容易影響全局
    • 需要內嵌一段腳本去動態計算根元素大小,使得css和js耦合在一起

五、彈性布局flexbox

容器幾個重要屬性:

flex-direction
flex-wrap
flex-flow
justify-content
align-items
align-content
復制代碼

項目的屬性:

order
flex-grow
flex-shrink
flex-basis
flex
align-self
復制代碼

注:

order屬性定義項目的排列順序。數值越小,排列越靠前,默認為0。

flex-grow屬性定義項目的放大比例,默認為0,即如果存在剩余空間,也不放大。

flex-shrink屬性定義了項目的縮小比例,默認為1,即如果空間不足,該項目將縮小。

flex-basis屬性定義了在分配多余空間之前,項目占據的主軸空間(main size)。瀏覽器根據這個屬性,計算主軸是否有多余空間。它的默認值為auto,即項目的本來大小。

flex屬性是flex-grow, flex-shrink 和 flex-basis的簡寫,默認值為0 1 auto。后兩個屬性可選。

align-self屬性允許單個項目有與其他項目不一樣的對齊方式,可覆蓋align-items屬性。默認值為auto,表示繼承父元素的align-items屬性,如果沒有父元素,則等同於stretch。

詳細請看布局教程

  • 優點:

    • 界面所有的元素大小和高度都會根據不同分辨率和屏幕寬度的設備來調整元素、字體、圖片、高度等屬性的值。簡單來說就是在不同的屏幕下,你看到的字體和元素高寬度的大小是不一樣的。

盡管以上多種適配方式,但是如果屏幕跨度太大,可能不僅僅是改變樣式,而需要重新設計頁面布局。工作中根據場景選取相應方式。

總結

在此總結幾個關鍵的點:

5種自適應方式:

  1. 百分比
  2. vm/vh
  3. flexbox
  4. media
  5. rem

物理像素線(普通屏幕下 1px ,高清屏幕下 0.5px 的情況)解決辦法:

    1. 可采用 transform 屬性 scale 實現
    1. rem方式中可設置meta
document.querySelector('meta[name="viewport"]').setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no'); 復制代碼

不管是margin-top/margin-bottom還是margin-left/margin-right(padding一樣),百分數是相對最近父級塊級元素的width計算。

一般使用padding-top:(percentage)實現響應式背景圖片。

當控制在1屏時候,可以結合使用vw和vh作為CSS單位

參考

caibaojian.com/vw-vh.html

www.jianshu.com/p/8f7f736fb…


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM