移動端適配方案
阿新 • • 發佈:2018-12-29
dev rem 單位 長度 tco create 正常的 edi alt Flexible適配方案
最早的文章,是15年阿裏手淘團隊的移動端適配方案。
設計師常選擇iPhone6作為基準設計尺寸,交付給前端的設計尺寸是按750px * 1334px為準(高度會隨著內容多少而改變)。
前端開發人員通過一套適配規則自動適配到其他的尺寸。
先了解一些基本概念
視窗viewport
簡單理解,viewport是嚴格等於瀏覽器的窗口,在桌面瀏覽器中,viewport就是瀏覽器窗口的寬度高度。
但是在移動端的viewport太窄,為了能更好的為css布局服務,所以提供了兩個viewport:虛擬的viewportvisualviewport和布局的viewportlayoutviewport(了解這兩種viewport概念的可以查看這裏)
設備像素比(device pixel ratio)
設備像素比簡稱為dpr,其定義了物理像素和設備獨立像素的對應關系。
viewport的meta標簽,主要是用來告訴瀏覽器如何規範渲染web頁面,在開發移動端頁面,我們需要設置meta標簽為:
手淘團隊根據以上的概念,出了一套針對移動端的適配方案`amfe-flexible`庫。
使用方法
前提是需要設置頁面的viewport
設備像素比 = 物理像素 / 設備獨立像素
在JavaScript中,可以通過`window.devicePixelRatio`獲取到當前設備的dpr。而在CSS中,可以通過`-webkit-device-pixel-ratio`,`-webkit-min-device-pixel-ratio`和 `-webkit-max-device-pixel-ratio`進行媒體查詢,對不同dpr的設備,做一些樣式適配(這裏只針對webkit內核的瀏覽器和webview) 在不同的屏幕上,CSS像素所呈現的物理尺寸是一致的,而不同的是CSS像素所對應的物理像素具數是不一致的。在普通屏幕下1個CSS像素對應1個物理像素,而在Retina屏幕下,1個CSS像素對應的卻是4個物理像素。 所以在移動端除了布局的適配外,還需要考慮到圖片的顯示質量,這就是我們所說的2倍圖或者3倍圖 meta標簽
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
css單位rem font size of the root element. 來自w3c規範 簡單的理解,rem就是相對於根元素<html>的font-size來做計算。而我們的方案中使用rem單位,是能輕易的根據<html>的font-size計算出元素的盒模型大小。 實現方案
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">然後引入功能文件
# 阿裏CDN引入 <script src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.4/??flexible_css.js,flexible.js"></script> # 下載對應的文件,直接在頁面中引入。 # 當然也可以 npm i -S amfe-flexible需要註意的一點那就是:在Flexible中,只對iOS設備進行dpr的判斷,對於Android系列,始終認為其dpr為1。 lexible實際上就是能過JS來動態改寫meta標簽,類似這樣:
# 動態改寫<meta>標簽#
給<html>元素添加data-dpr屬性,並且動態改寫data-dpr的值#
給<html>元素添加font-size屬性,並且動態改寫font-size的值
var metaEl = doc.createElement(‘meta‘); var scale = isRetina ? 0.5:1;metaEl.setAttribute(‘name‘, ‘viewport‘); metaEl.setAttribute(‘content‘, ‘initial-scale=‘ + scale + ‘, maximum-scale=‘ + scale + ‘, minimum-scale=‘ + scale + ‘, user-scalable=no‘); if (docEl.firstElementChild) { document.documentElement.firstElementChild.appendChild(metaEl); } else { var wrap = doc.createElement(‘div‘); wrap.appendChild(metaEl); documen.write(wrap.innerHTML); }
接下來要做的事情就是`px`->`rem` 1.可以通過在編輯器中安裝插件實現單位的換算 2.可以通過配置postCSS進行自動的單位轉換,還按照正常的px進行布局,代碼執行後會自動轉成對應的rem數值。(具體的配置方法,需要看另外的關於postCSS的文章(待完善)) 這套方案,在實際構建M站的過程中,我遇到的一個問題是,1px的border無法正常顯示,目前網上沒有一個很完美的解決方案,更多提到的是轉為svg的方式實現。 不同的終端,我們面對的屏幕分辨率、DPR、1px、2x圖等一系列的問題。那麽這個布局方案也是針對性的解決這些問題,只不過解決這些問題不再是使用Hack手段來處理,而是直接使用原生的CSS技術來處理的。 vw是基於viewport視窗的長度單位。指的是瀏覽器可視化的區域,也就是window.innerWidth/window.innerHeight的大小。
1vw = window.innerWidth 的 1%目前出視覺設計稿,我們都是使用750px寬度的,從上面的原理來看,那麽100vw = 750px,即1vw = 7.5px。那麽我們可以根據設計圖上的px值直接轉換成對應的vw值。 這裏當然我們也去可以手動去轉化單位,但是我們可以在項目的配置項中添加`postCSS`相關的配置,可以為我們自動去轉化。我們也只需要按照設計稿給的px去進行布局即可。 下面介紹在`grunt`上配置`postCSS` 安裝postCSS插件
# grunt npm install grunt-postcss --save-dev #webpack npm install postcss-loader --save-devgrunt中配置 在`gruntfile.js`中配置,通過`grunt.loadNpmTasks()`函數加載`grunt-postcss`插件
module.exports = function(grunt) { grunt.initConfig({ postcss:{ options:{ // 配置postCSS所需插件 processors:[ // 這是postCSS插件 // 自動添加前綴 require(‘autoprefixer‘), // 適配方案 require(‘postcss-px-to-viewport‘)({ viewportWidth: 750, viewportHeight: 1670, unitPrecision: 5, viewportUnit: ‘vw‘, selectorBlackList: [], minPixelValue: 1, mediaQuery: false }) ] }, dist:{ // 設置CSS的源文件和postCSS編譯後的CSS文件 src: ‘src/style.css‘, // 源文件 dest: ‘dest/style.css‘ // 輸出文件 } } }); grunt.loadNpmTasks(‘grunt-postcss‘); }
webpack中配置 配置webpack.config.js(即你的基本公用配置中)
module: { loaders: [ { test: /\.css$/, // 如果使用了 ExtractTextPlugin loader: ExtractTextPlugin.extract(‘style‘, ‘css!postcss‘) // 否則 // loader: "style-loader!css-loader!postcss-loader" } ] }, // 當然,你也可以在根目錄下設置.postcssrc.js中添加對postCSS的配置,會自動識別。 postcss: function () { return [ // 裏面是我們要用的插件 // 自動添加前綴 require(‘autoprefixer‘), // 適配方案 require(‘postcss-px-to-viewport‘)({ viewportWidth: 750, viewportHeight: 1670, unitPrecision: 5, viewportUnit: ‘vw‘, selectorBlackList: [], minPixelValue: 1, mediaQuery: false }) ]; }
註意的是,配置postCSS插件的時候,需要提前安裝依賴。點擊這裏。看看postCSS的強大之處吧。 針對第二套適配方案,`vw`已經廣泛被移動端瀏覽器良好的支持了。所以幾乎是沒有什麽問題. 現有項目中的適配方案 現有的項目采用的適配方案,其實和第一種的原理是一樣的。
// 動態計算px的大小,比如設計稿的尺寸寬是750px (function(dew){ var winW = document.documentElement.clientWidth; var ratio = winW/desW; document.documentElement.style.fontSize = ratio * 100 + ‘px‘; })(750); //在css中對根字體大小進行設置: // html,body{ // font-size:100px; // } // 這樣我們在對UI給的尺寸直接除以100,就是對應的rem單位了。
當然,px和rem之間的轉換,可以通過編輯器自己的插件,也可以去配置postCSS去自動轉換。 總結 PostCSS是一種工具,一款已成長為像Sass和LESS一樣主流的處理器,這一切都歸功於它的強大、速度和易用性。 將 PostCSS 視為後處理器,或者將其視作是預處理器的相反處理,都是一種誤導;PostCSS 有能力應對各種不同的使用場景,既可以處理已經被預處理器編譯過的代碼,也可以處理純粹的 CSS 代碼;它可以在開發者的開發工作流中處理更多的任務 postCSS其實算不上什麽適配方案,1和3兩套方案的本質是一樣的。至於第2種適配方案,本質就是把我們經常用的rem變成了vw視窗單位。 對於postCSS,這個東西帶給了我很多新的關於web自動化流程的設計感想。他可以實現很多我們針對CSS方面兼容性的處理。事實上頁面的布局總是令人蛋疼的。但技術是不斷革新的,我們可以隨著保持對新技術的關註,嘗試這些新特性運用到實際項目中,只有這樣,我們解決問題的方案才會越來越完善。
移動端適配方案