根據UI圖對移動端的h5頁面作樣式重構,是前端工程師的本職工做,看似簡單,不過想作好卻並不容易。下面總結一下其中要點。css
rem是一種相對長度單位,參考的基準是<html>
標籤訂義的font-size
。好比:html
html { font-size: 16px; } .intro { font-size: 1.2rem; margin-top: 0.2rem; }
那麼實際效果就是:前端
.intro { font-size: 16px * 1.2rem = 19.2px; margin-top: 16px * 0.2rem = 3.2px; }
作移動端的h5,一般會在HTML文件中指定一個<meta>
標籤:sass
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximun-scale=1.0, user-scalable=no">
關於Viewport,能夠參考更專業的教程:前端工程師
http://www.cnblogs.com/chengkun101/p/5461500.html函數
http://www.cnblogs.com/2050/p/3877280.html工具
手機屏幕的分辨率愈來愈高,好比iPhone 5爲640*1136 px
、iPhone 6/6S爲750*1334 px
。我拿到的UI圖,其參考分辨率爲1440*2560 px
。字體
而在寫CSS時,一般是以屏幕寬度爲參考的。打開Chrome的響應式設計工具,就能夠看到各類設備的屏幕寬度,好比iPhone 5的屏幕寬度是320*568 px
,iPhone 6/6S的屏幕寬度爲375*667 px
。分辨率和屏幕寬度之間,是有一個倍屏係數換算的。scala
設計師給了一張寬爲1440px的UI圖,而作不一樣設備的適配,就是前端工程師的職責了。設計
好比UI圖上標註了某個段落的字體大小爲64px。爲了保證在各類屏幕上的不失真,就要根據實際屏幕寬度作等比例換算,才能寫進CSS,即知足:
寫入CSS的尺寸/屏幕寬度 = UI圖標註的尺寸/UI圖寬度 所以: 寫入CSS的尺寸 = UI圖標註的尺寸/UI圖寬度*屏幕寬度
好比上例,當標註尺寸爲64px、UI圖寬度爲1440px時,針對不一樣屏幕寬度,寫入CSS的屬性分別爲:
font-size: 64/1440*320 = 14.22px
font-size: 64/1440*360 = 16px
font-size: 64/1440*375 = 16.67px
font-size: 64/1440*1440 = 64px
因而天然想到媒體查詢:
@media (min-width: 320px) { p.intro { font-size: 14.22px; } } @media (min-width: 360px) { p.intro { font-size: 16px; } } @media (min-width: 375px) { p.intro { font-size: 16.67px; } } @media (min-width: 1440px) { p.intro { font-size: 64px; } }
天啊,若是這樣寫,若是UI圖上標註了另外一個段落的字體大小爲60px
,豈不又要寫一遍媒體查詢!
解決方法是,在<html>
標籤上只作一次媒體查詢,而在p.intro
上使用rem單位。
// 對html作媒體查詢,定義基準的font-size @media (min-width: 320px) { html { font-size: 14.22px; } } @media (min-width: 360px) { html { font-size: 16px; } } @media (min-width: 375px) { html { font-size: 16.67px; } } @media (min-width: 1440px) { html { font-size: 64px; } } // CSS單位使用rem p.intro { font-size: 1rem; }
這樣一來,其餘元素也能夠共享<html>
的基準font-size
,無需媒體查詢,只需引入rem單位,如:
// 另外一個段落 p.another-intro { font-size: 0.9375rem; // UI圖上標註60px height: 1.5625rem; // UI圖上標註100px margin: 0.5rem; // UI圖上標註32px }
有點匪夷所思?先來看看如上換算是否知足等比例性。再回顧一下公式:
寫入CSS的尺寸/屏幕寬度 = UI圖標註的尺寸/UI圖寬度
以p.another-intro
的margin
屬性爲例:
margin: 14.22*0.5 = 7.11px
,而7.11/320 = 32/1440
margin: 16*0.5 = 8px
,而8/360 = 32/1440
margin: 16.67*0.5 = 8.335px
,而8.335/375 = 32/1440
margin: 64*0.5 = 32px
,而32/1440 = 32/1440
完美。
能夠發現一個規律:在媒體查詢中,min-width: 1440px
時定義了html { font-size: 64px; }
,那麼UI圖上標註的尺寸,直接除以64,就能夠帶個rem尾巴,寫入到CSS中。記住64這個參考值,很是有用,下文會常常用到。
固然,你也能夠不使用64做爲參考值,只要符合等比例規則就能夠。下文均是以64爲例的。
以上只以320px、360px、375px爲例,獲得了<html>
的基準font-size
。對於iPhone 6s Plus,其屏幕寬度爲414px,如何計算font-size
?
很簡單:屏幕寬度/UI圖寬度*64
。
因而,又多了一條媒體查詢規則:
@media (min-width: 414px) { html { font-size: 18.4px; // 414/1440*64 } }
查閱常見移動設備的屏幕尺寸規格,能夠獲得一個較爲完整的媒體查詢規則:
html { font-size: 12px; } @media (min-width:320px){ html{ font-size: 14.2222px; } } @media (min-width:360px){ html{ font-size: 16px; } } @media (min-width:375px){ html{ font-size: 16.6667px; } } @media (min-width:412px){ html{ font-size: 18.2857px; } } @media (min-width:480px){ html{ font-size: 21.3333px; } } @media (min-width:640px){ html{ font-size: 28.4444px; } } @media (min-width:720px){ html{ font-size: 32px; } } @media (min-width:768px){ html{ font-size: 34.1333px; } } @media (min-width:1440px){ html{ font-size: 64px; } }
以前所講的內容,已經可使你作出移動端適配的h5頁面了,但並不優雅。由於CSS是不支持計算的,「標註尺寸/64」只能手工計算,也就意味着UI圖上的每一個標註都要手動換算,你會瘋掉。
不過,藉助CSS預編譯工具,如Less/Sass,能夠避免這種重複勞動。如下以Scss爲例,好比:
p.intro { font-size: 64px/64px * 1rem; } p.another-intro { font-size: 60px/64px * 1rem; // UI圖上標註60px height: 100px/64px * 1rem; // UI圖上標註100px margin: 32px/64px * 1rem; // UI圖上標註32px }
固然也可使用變量:
// 計算rem的基準字體 $rem-base-font-size: 64px; p.intro { font-size: 64px/$rem-base-font-size * 1rem; } p.another-intro { font-size: 60px/$rem-base-font-size * 1rem; // UI圖上標註60px height: 100px/$rem-base-font-size * 1rem; // UI圖上標註100px margin: 32px/$rem-base-font-size * 1rem; // UI圖上標註32px }
這樣作的好處是,若是某一天不使用64px做爲參考值,只需修改$rem-base-font-size
變量。
以上代碼看着很冗餘,不如寫一個函數,隱藏計算過程:
// 將設計圖標註的px尺寸,轉換爲相應的CSS @function convertPxFormUI($px) { $rem-base-font-size: 64px; @return $px / $rem-base-font-size * 1rem; } p.intro { font-size: convertPxFormUI(64px); } p.another-intro { font-size: convertPxFormUI(60px); // UI圖上標註60px height: convertPxFormUI(100px); // UI圖上標註100px margin: convertPxFormUI(32px); // UI圖上標註32px }
這樣作的好處是,若是某一天摒棄了rem,使用了其餘換算規則,只需修改convertPxFormUI()
函數體便可。
既然Sass幫助咱們計算,那麼媒體查詢中的一堆font-size
,Sass是否能夠代勞呢?
以前介紹了計算規則:屏幕寬度/UI圖寬度*64
。OK,看來能夠這樣寫:
// 計算rem的基準字體 $rem-base-font-size: 64px; // UI設計圖的分辨率寬度 $UI-resolution-width: 1440px; @mixin html-font-size() { @media (min-width:320px){ html{ font-size: 320px / $UI-resolution-width * $rem-base-font-size; } } @media (min-width:360px){ html{ font-size: 360px / $UI-resolution-width * $rem-base-font-size; } } @media (min-width:375px){ html{ font-size: 375px / $UI-resolution-width * $rem-base-font-size; } } @media (min-width:412px){ html{ font-size: 412px / $UI-resolution-width * $rem-base-font-size; } } @media (min-width:480px){ html{ font-size: 480px / $UI-resolution-width * $rem-base-font-size; } } @media (min-width:640px){ html{ font-size: 640px / $UI-resolution-width * $rem-base-font-size; } } @media (min-width:720px){ html{ font-size: 720px / $UI-resolution-width * $rem-base-font-size; } } @media (min-width:768px){ html{ font-size: 768px / $UI-resolution-width * $rem-base-font-size; } } @media (min-width:1440px){ html{ font-size: 1440px / $UI-resolution-width * $rem-base-font-size; } } }
很冗餘,用循環來實現:
// 計算rem的基準字體 $rem-base-font-size: 64px; // UI設計圖的分辨率寬度 $UI-resolution-width: 1440px; // 須要適配的屏幕寬度 $device-widths: 320px, 360px, 375px, 412px, 480px, 640px, 720px, 768px, 1440px; @mixin html-font-size() { @each $current-width in $device-widths { @media (min-width: $current-width) { html { $x: $UI-resolution-width / $current-width; // 計算出是幾倍屏 font-size: $rem-base-font-size / $x; } } } }
這樣作的好處是,若是某一天老闆說,屏幕寬度450px時效果不理想。你只需在$device-widths
中新增一個寬度便可。
_variables.scss
:定義變量// 計算rem的基準字體 $rem-base-font-size: 64px; // UI設計圖的分辨率寬度 $UI-resolution-width: 1440px; // 須要適配的屏幕寬度 $device-widths: 240px, 320px, 360px, 375px, 412px, 480px, 540px, 640px, 720px, 768px, 1024px, 1440px;
_utils.scss
:定義函數與mixin// 根據不一樣設備的屏幕寬度,定義<html>的基準font-size @mixin html-font-size() { @each $current-width in $device-widths { @media (min-width: $current-width) { html { $x: $UI-resolution-width / $current-width; // 計算出是幾倍屏 font-size: $rem-base-font-size / $x; } } } } // 將設計圖標註的px尺寸,轉換爲相應的CSS @function convertPxFormUI($px) { @return $px / $rem-base-font-size * 1rem; }
index.scss
:Scss入口文件@import 'utils', 'variables'; @include html-font-size(); p.intro { font-size: convertPxFormUI(64px); } p.another-intro { font-size: convertPxFormUI(60px); height: convertPxFormUI(100px); margin: convertPxFormUI(32px); }
rem + viewport + 媒體查詢 + Sass