這篇文章的內容如題目同樣,主要分爲兩個部分,javascript
談談業內主流的移動端適配解決方案css
點5像素的由來和實現方法html
建議在讀這篇文章的時候先讀下這篇文章《高清屏概念解析與檢測設備像素比的方法_20161005》,由於這些文章涉及的不少概念在這篇文章中都會提到。前端
在咱們的項目中大量的使用百分比來解決頁面在寬度上的自適應,其實在高度上並無很好的自適應。因此在咱們的前端頁面會出現一些比較奇怪的問題。好比下面這樣:java
還有一個比較明顯的問題就是:在任何機型上咱們的按鈕的高度是不會變化自適應的,因此小屏手機咱們的按鈕看起來很臃腫。css3
在談我爲何在咱們的項目中引入rem
單位的時候,先來詳細的瞭解幾個經常使用的單位概念。git
px像素(Pixel)
。相對長度單位。像素px
是相對於顯示器屏幕分辨率而言的(也就是說是跟物理設備有關的)。拿高清屏和普通屏來作對比就是普通屏幕的1個像素點就是1個物理像素點,而高清屏的1個像素點是4個物理像素點。github
em
相對長度單位。相對於當前對象內文本的字體尺寸。如當前對行內文本的字體尺寸未被人爲設置,則相對於瀏覽器的默認字體尺寸。em
單位的特色:1. em的值並非固定的;2. em會繼承父級元素的字體大小。web
rem
相對長度單位。rem是CSS3新增的一個相對單位,這個單位引發了普遍關注。這個單位與em有什麼區別呢?區別在於使用rem爲元素設定字體大小時,仍然是相對大小,但相對的只是HTML根元素。這個單位可謂集相對大小和絕對大小的優勢於一身,經過它既能夠作到只修改根元素就成比例地調整全部字體大小,又能夠避免字體大小逐層複合的連鎖反應。chrome
任意瀏覽器的默認字體高都是16px。全部未經調整的瀏覽器都符合: 1rem=16px。那麼12px=0.75rem,10px=0.625rem。爲了簡化font-size的換算,須要在css中的html選擇器中聲明font-size=62.5%,這就使rem值變爲 16px*62.5%=10px, 這樣12px=1.2rem, 10px=1rem, 也就是說只須要將原來的px數值除以10,而後換上rem做爲單位就好了。
注意:當咱們在根節點<html>
上設置了font-size
基準值之後,在文檔中有使用rem
單位的屬性值都是相對於根節點font-size
的一個相對值。好比說一些元素的屬性如width
height
margin
等。也正是這個緣由,如今不少網站的移動端網站都在使用rem
單位做爲適配工具。
在使用rem
的時候比較麻煩的就是px
和rem
換算的問題。上面的除10的方案是比較簡單的。可是根據設置基準值的不一樣換算方法也不同。若是咱們使用scss來寫咱們的樣式表的話,解決方法就比較簡單了,代碼以下:
@function px2rem($px){ @return ($px/10)/2 + rem; // 至關於$px/20 +rem } width:px2rem(100px); //5rem height:px2rem(200px); //10rem
由上面的內容已經知道百分比單位在多屏幕適配上的缺點和rem
單位的優勢。那麼rem
單位能爲咱們的開發帶來什麼呢?來看一個常見的多列布局,淘寶移動端的商品列表頁,以下圖:
設計稿(不論是iphone6的二倍稿仍是iphone5的二倍稿)中給展現商品的坑位的寬高比是固定的。爲了可以使這個列表在不一樣的屏幕上達到最佳的顯示效果,須要保持寬度和高度比一致。若是使用百分比確定是知足不了這個需求的,由於高度上咱們沒有辦法控制。
iphone6和iphone5的屏幕寬度和高度比不同,當咱們使用百分比作多列布局的時候就會出現下面的這種狀況:
因此爲了知足商品坑位在不一樣屏幕上的寬高比一致,淘寶使用的是rem
的解決方案,也是目前最好的解決方案。
font-size
值的js放在head
標籤中設置根節點font-size
值的方法,第一種是使用css的Media queries
,示例代碼以下:
@media (min-device-width : 375px) and (max-device-width : 667px) and (-webkit-min-device-pixel-ratio : 2){ html{font-size: 37.5px;} }
上面的這種方式在我以前作過的項目中使用了一段時間。上面的設置方法有一個很明顯的問題font-size
是在一個屏幕寬度的區間上有一個基準值。像安卓手機種類的繁多,屏幕大小就更多的狀況下,上面的方法很雞肋。
第二種解決方案,就是使用JavaScript根據當前屏幕的寬度動態計算font-size
值,這種方法能夠保證屏幕寬度連續變化的時候,font-size
基準值也是連續變化的。
計算方法能夠參考這篇文章《根據iPhone6設計稿動態計算rem值》
那麼最後一個問題也來了:爲何將計算rem單位的js放在head標籤裏面?
一句話總結:在瀏覽器中文檔流是從上往下加載渲染的。爲了保證發生沒必要要的重繪或者是重排確定是越早給根節點設置font-size
值越好。
總體的佈局仍是使用百分比
使用rem的最佳場景是,遇到例如多列帶有圖片的列表,經常須要圖片固定寬高比例
研究了一些網站,好比淘寶,對字體字體通常狀況建議使用px
出現1px
像素線的地方,仍舊使用border-width:1px;
而不是border-width:.1rem;
在前言中推薦閱讀的那篇文章中已經知道在 高清屏(Retina)
中控制顯示的最小的物理單元包括4個基本的像素點,而普通屏幕1個點像素就是1個物理像素單元。因此在高清屏(Retina)
出來以前,就算咱們在css中寫 0.5px
,對於顯示屏幕也是不識別的。可是在高清屏(Retina)
中咱們能夠經過間接的方法實現0.5px
的效果。
下面的這張圖可能能讓咱們迅速回憶上篇文章的內容
來看一段簡單的示例代碼加深理解:
<div class="item1"></div> <div class="item2"></div>
css代碼以下:
.item1{ width:100px; height:50px; border-top:1px solid #000; float: left; margin-top:10px; } .item2{ width:100px; height:50px; margin-top:10px; border-top:.5px solid #de1dfb; float: left; }
chrome中的顯示效果以下圖:
我把這張圖截取下來放到 PS 中放大能夠很明顯的看到一些問題。就是高清屏其實是用了兩排的物理像素點來顯示1px
的像素線。且不作特殊處理的話1px
和0.5px
的在Chrome瀏覽器中顯示效果是相同的。也就是說Chrome瀏覽器不識別0.5px
。
可是相同的代碼我在 safari瀏覽器中的效果倒是下面的效果:
下面的效果是我在PS中作了放大後的效果。
因此,咱們能夠得出一個結論:對於0.5px
不一樣瀏覽器對它的識別是存在差別的。
如下這張圖是一位網友對一些經常使用設備是否識別0.5px
作的統計:
其實從視覺的感覺上來講0.5px
像素的顯示效果確實是比1px
的顯示效果要好不少。大多數狀況下也更符合設計稿上的1px
線的效果。那麼咱們有沒有辦法可讓1px
在不一樣的瀏覽器和設備中顯示真正的1像素的效果呢?
答案是確定定的。
僞元素 + css3的縮放巧妙地實現;
基本步驟就是:
設置目標元素定位參照
給目標元素添加一個僞元素before或者after,並設置絕對定位
給僞元素添上1px的邊框
設置僞元素的寬高爲目標元素的2倍
縮小0.5倍(變回目標元素的大小)
使用border-box把border包進來
先來看一個1像素
和0.5像素
的顯示效果,下面的截圖是在chrome中:
實現的代碼以下:
<div class="item4">測試用的邊框</div> <div class="item5">測試用的邊框</div>
.item4, .item5 { width: 200px; height: 100px; position: relative; } .item4 { border: 1px solid #000; } .item5::before { content: ''; position: absolute; width: 200%; height: 200%; border: 1px solid #000; transform-origin: 0 0; transform: scale(0.5, 0.5); box-sizing: border-box; }
能夠很明顯的看到縮放前和縮放後的效果。在ps中把上面的截圖放大不少倍之後咱們能夠看到顯示細節。縮放之後確實是使用的最小的物理像素單元來顯示邊框。以下圖:
注意:按照css3 transform
的scale
的定義,理論上邊框能夠任意細(1/n px)。可是上圖中已是物理設備可以使用的最小的物理單元了,那麼咱們繼續縮放會有什麼現象呢?
使用一下代碼
<div class="item6">測試用的邊框</div>
.item6::before { content: ''; position: absolute; width: 400%; height: 400%; border: 1px solid #000; transform-origin: 0 0; transform: scale(0.25, 0.25); box-sizing: border-box; }
chrome中顯示效果以下,能夠很明顯的看到顏色變淺了,可是是否變得更細了咱們肉眼沒法分辨:
在PS中放大之後的效果:
很明顯能夠看到線並無變細,可是線的顏色確實是變淺了。這樣的結果也符合咱們的預期,就是已經到了物理設備可以顯示一塊顏色的最小的物理單元了。
viewport
的方案一些大廠(所謂的淘寶)的解決方案就是使用js動態獲取屏幕的設備像素比,而後動態設置viewport
。固然也是我認爲目前最好的解決方案。
meta.setAttribute('content', 'initial-scale=' + 1/dpr + ', maximum-scale=' + 1/dpr + ', minimum-scale=' + 1/dpr + ', user-scalable=no');
咱們知道,通常咱們獲取到的視覺稿大部分是iphone6的,因此咱們看到的尺寸通常是雙倍大小的,在使用rem以前,咱們通常會自覺的將標註/2,其實這也並沒有道理,可是當咱們配合rem使用時,徹底能夠按照視覺稿上的尺寸來設置。
設計給的稿子雙倍的緣由是iphone6這種屏幕屬於高清屏,也便是設備像素比(device pixel ratio)dpr比較大,因此顯示的像素較爲清晰。
通常手機的dpr是1,iphone4,iphone5這種高清屏是2,iphone6s plus這種高清屏是3,能夠經過js的window.devicePixelRatio獲取到當前設備的dpr,因此iphone6給的視覺稿大小是(*2)750×1334了。
拿到了dpr以後,咱們就能夠在viewport meta頭裏,取消讓瀏覽器自動縮放頁面,而本身去設置viewport的content例如(這裏之因此要設置viewport是由於咱們要實現border1px的效果,在scale的影響下,高清屏中就會顯示成0.5px的效果)
由以上兩個部分的內容能夠知道,不論是在作多終端適配仍是實現點5像素的線,都是存在css和js兩種解決方案的。兩種方案相比來講,我都認爲使用JavaScript的解決方案都勝一籌。惟一的缺點就是會在html的head標籤中引入一段js代碼 。
記得剛入行的時候,業內有一個叫「雅虎軍規」的東西,是好多前端作頁面優化參考的標準。其中有一條就是要將js文件放在body
標籤的底部。到如今不少年了,時代在變化,咱們的網絡帶寬也在提高,「雅虎軍規」中的一些內容,可能有些已經不適合咱們如今應用開發的場景。並且我覺的作技術不該該拘泥於已有的一些規定,而應該按照咱們的場景選擇適合咱們的技術和解決方案。
縱然有瑕疵,有些也是能夠經過技術手段來解決的。好比在head
標籤中引入計算font-size
和檢測設備獨立像素比
的js的時候,會擔憂js的執行阻塞頁面的渲染。而咱們徹底能夠經過review
的方式肯定js代碼的執行不會出現阻塞,而影響文檔流的加載。
仍是那句話:沒有十全十美的技術方案,只有適合不合適當前業務場景的技術方案。。
[css3的字體大小單位[rem]到低好在哪裏](https://www.zhihu.com/questio...
移動端高清、多屏適配方案
使用Flexible實現手淘H5頁面的終端適配
lib-flexible源代碼