摘要:再談移動端適配百分比解決方案的缺點在我們的項目中大量的使用百分比來解決頁面在寬度上的自適應(yīng),其實在高度上并沒有很好的自適應(yīng)。
前言
這篇文章的內(nèi)容如題目一樣,主要分為兩個部分,
談?wù)剺I(yè)內(nèi)主流的移動端適配解決方案
點5像素的由來和實現(xiàn)方法
建議在讀這篇文章的時候先讀下這篇文章《高清屏概念解析與檢測設(shè)備像素比的方法_20161005》,因為這些文章涉及的很多概念在這篇文章中都會提到。
1.再談移動端適配 1.1百分比解決方案的缺點在我們的項目中大量的使用百分比來解決頁面在寬度上的自適應(yīng),其實在高度上并沒有很好的自適應(yīng)。所以在我們的前端頁面會出現(xiàn)一些比較奇怪的問題。比如下面這樣:
還有一個比較明顯的問題就是:在任何機(jī)型上我們的按鈕的高度是不會變化自適應(yīng)的,所以小屏手機(jī)我們的按鈕看起來很臃腫。
1.2一些常用單位的概念解析在談我為什么在我們的項目中引入rem單位的時候,先來詳細(xì)的了解幾個常用的單位概念。
px像素(Pixel)。相對長度單位。像素px是相對于顯示器屏幕分辨率而言的(也就是說是跟物理設(shè)備有關(guān)的)。拿高清屏和普通屏來做對比就是普通屏幕的1個像素點就是1個物理像素點,而高清屏的1個像素點是4個物理像素點。
em相對長度單位。相對于當(dāng)前對象內(nèi)文本的字體尺寸。如當(dāng)前對行內(nèi)文本的字體尺寸未被人為設(shè)置,則相對于瀏覽器的默認(rèn)字體尺寸。em單位的特點:1. em的值并不是固定的;2. em會繼承父級元素的字體大小。
rem相對長度單位。rem是CSS3新增的一個相對單位,這個單位引起了廣泛關(guān)注。這個單位與em有什么區(qū)別呢?區(qū)別在于使用rem為元素設(shè)定字體大小時,仍然是相對大小,但相對的只是HTML根元素。這個單位可謂集相對大小和絕對大小的優(yōu)點于一身,通過它既可以做到只修改根元素就成比例地調(diào)整所有字體大小,又可以避免字體大小逐層復(fù)合的連鎖反應(yīng)。
任意瀏覽器的默認(rèn)字體高都是16px。所有未經(jīng)調(diào)整的瀏覽器都符合: 1rem=16px。那么12px=0.75rem,10px=0.625rem。為了簡化font-size的換算,需要在css中的html選擇器中聲明font-size=62.5%,這就使rem值變?yōu)?16px*62.5%=10px, 這樣12px=1.2rem, 10px=1rem, 也就是說只需要將原來的px數(shù)值除以10,然后換上rem作為單位就行了。
注意:當(dāng)我們在根節(jié)點上設(shè)置了font-size基準(zhǔn)值以后,在文檔中有使用rem單位的屬性值都是相對于根節(jié)點font-size的一個相對值。比如說一些元素的屬性如width height margin等。也正是這個原因,現(xiàn)在很多網(wǎng)站的移動端網(wǎng)站都在使用rem單位作為適配工具。
在使用rem的時候比較麻煩的就是px和rem換算的問題。上面的除10的方案是比較簡單的。但是根據(jù)設(shè)置基準(zhǔn)值的不同換算方法也不一樣。如果我們使用scss來寫我們的樣式表的話,解決方法就比較簡單了,代碼如下:
@function px2rem($px){ @return ($px/10)/2 + rem; // 相當(dāng)于$px/20 +rem } width:px2rem(100px); //5rem height:px2rem(200px); //10rem1.3為什么引入 rem 單位
由上面的內(nèi)容已經(jīng)知道百分比單位在多屏幕適配上的缺點和rem單位的優(yōu)點。那么rem單位能為我們的開發(fā)帶來什么呢?來看一個常見的多列布局,淘寶移動端的商品列表頁,如下圖:
設(shè)計稿(不管是iphone6的二倍稿還是iphone5的二倍稿)中給展示商品的坑位的寬高比是固定的。為了能夠使這個列表在不同的屏幕上達(dá)到最佳的顯示效果,需要保持寬度和高度比一致。如果使用百分比肯定是滿足不了這個需求的,因為高度上我們沒有辦法控制。
iphone6和iphone5的屏幕寬度和高度比不一樣,當(dāng)我們使用百分比做多列布局的時候就會出現(xiàn)下面的這種情況:
所以為了滿足商品坑位在不同屏幕上的寬高比一致,淘寶使用的是rem的解決方案,也是目前最好的解決方案。
1.3為什么將計算根元素的font-size值的js放在head標(biāo)簽中設(shè)置根節(jié)點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;} }
上面的這種方式在我之前做過的項目中使用了一段時間。上面的設(shè)置方法有一個很明顯的問題font-size是在一個屏幕寬度的區(qū)間上有一個基準(zhǔn)值。像安卓手機(jī)種類的繁多,屏幕大小就更多的情況下,上面的方法很雞肋。
第二種解決方案,就是使用JavaScript根據(jù)當(dāng)前屏幕的寬度動態(tài)計算font-size值,這種方法可以保證屏幕寬度連續(xù)變化的時候,font-size基準(zhǔn)值也是連續(xù)變化的。
計算方法可以參考這篇文章《根據(jù)iPhone6設(shè)計稿動態(tài)計算rem值》
那么最后一個問題也來了:為什么將計算rem單位的js放在head標(biāo)簽里面?
一句話總結(jié):在瀏覽器中文檔流是從上往下加載渲染的。為了保證發(fā)生不必要的重繪或者是重排肯定是越早給根節(jié)點設(shè)置font-size值越好。
1.4什么情況下使用rem來布局和注意的問題整體的布局還是使用百分比
使用rem的最佳場景是,遇到例如多列帶有圖片的列表,常常需要圖片固定寬高比例
研究了一些網(wǎng)站,比如淘寶,對字體字體一般情況建議使用px
出現(xiàn)1px像素線的地方,仍舊使用border-width:1px;而不是border-width:.1rem;
2.點5像素的由來在前言中推薦閱讀的那篇文章中已經(jīng)知道在 高清屏(Retina) 中控制顯示的最小的物理單元包括4個基本的像素點,而普通屏幕1個點像素就是1個物理像素單元。所以在高清屏(Retina)出來之前,就算我們在css中寫 0.5px,對于顯示屏幕也是不識別的。但是在高清屏(Retina)中我們可以通過間接的方法實現(xiàn)0.5px的效果。
下面的這張圖可能能讓我們迅速回憶上篇文章的內(nèi)容
來看一段簡單的示例代碼加深理解:
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中做了放大后的效果。
所以,我們可以得出一個結(jié)論:對于0.5px不同瀏覽器對它的識別是存在差異的。
以下這張圖是一位網(wǎng)友對一些常用設(shè)備是否識別0.5px做的統(tǒng)計:
其實從視覺的感受上來說0.5px像素的顯示效果確實是比1px的顯示效果要好很多。大多數(shù)情況下也更符合設(shè)計稿上的1px線的效果。那么我們有沒有辦法可以讓1px在不同的瀏覽器和設(shè)備中顯示真正的1像素的效果呢?
答案是肯定定的。
2.1傳統(tǒng)的實現(xiàn)方法,也就是我們的項目中正在使用的方法:偽元素 + css3的縮放巧妙地實現(xiàn);
基本步驟就是:
設(shè)置目標(biāo)元素定位參照
給目標(biāo)元素添加一個偽元素before或者after,并設(shè)置絕對定位
給偽元素添上1px的邊框
設(shè)置偽元素的寬高為目標(biāo)元素的2倍
縮小0.5倍(變回目標(biāo)元素的大小)
使用border-box把border包進(jìn)來
先來看一個1像素和0.5像素的顯示效果,下面的截圖是在chrome中:
實現(xiàn)的代碼如下:
測試用的邊框測試用的邊框
.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中把上面的截圖放大很多倍以后我們可以看到顯示細(xì)節(jié)。縮放以后確實是使用的最小的物理像素單元來顯示邊框。如下圖:
注意:按照css3 transform 的scale的定義,理論上邊框可以任意細(xì)(1/n px)。但是上圖中已經(jīng)是物理設(shè)備能夠使用的最小的物理單元了,那么我們繼續(xù)縮放會有什么現(xiàn)象呢?
使用一下代碼
測試用的邊框
.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中顯示效果如下,可以很明顯的看到顏色變淺了,但是是否變得更細(xì)了我們?nèi)庋蹮o法分辨:
在PS中放大以后的效果:
很明顯可以看到線并沒有變細(xì),但是線的顏色確實是變淺了。這樣的結(jié)果也符合我們的預(yù)期,就是已經(jīng)到了物理設(shè)備能夠顯示一塊顏色的最小的物理單元了。
2.2js動態(tài)設(shè)置viewport的方案一些大廠(所謂的淘寶)的解決方案就是使用js動態(tài)獲取屏幕的設(shè)備像素比,然后動態(tài)設(shè)置viewport。當(dāng)然也是我認(rèn)為目前最好的解決方案。
meta.setAttribute("content", "initial-scale=" + 1/dpr + ", maximum-scale=" + 1/dpr + ", minimum-scale=" + 1/dpr + ", user-scalable=no");
我們知道,一般我們獲取到的視覺稿大部分是iphone6的,所以我們看到的尺寸一般是雙倍大小的,在使用rem之前,我們一般會自覺的將標(biāo)注/2,其實這也并無道理,但是當(dāng)我們配合rem使用時,完全可以按照視覺稿上的尺寸來設(shè)置。
設(shè)計給的稿子雙倍的原因是iphone6這種屏幕屬于高清屏,也即是設(shè)備像素比(device pixel ratio)dpr比較大,所以顯示的像素較為清晰。
一般手機(jī)的dpr是1,iphone4,iphone5這種高清屏是2,iphone6s plus這種高清屏是3,可以通過js的window.devicePixelRatio獲取到當(dāng)前設(shè)備的dpr,所以iphone6給的視覺稿大小是(*2)750×1334了。
拿到了dpr之后,我們就可以在viewport meta頭里,取消讓瀏覽器自動縮放頁面,而自己去設(shè)置viewport的content例如(這里之所以要設(shè)置viewport是因為我們要實現(xiàn)border1px的效果,在scale的影響下,高清屏中就會顯示成0.5px的效果)
總結(jié):由以上兩個部分的內(nèi)容可以知道,不管是在做多終端適配還是實現(xiàn)點5像素的線,都是存在css和js兩種解決方案的。兩種方案相比來說,我都認(rèn)為使用JavaScript的解決方案都勝一籌。唯一的缺點就是會在html的head標(biāo)簽中引入一段js代碼 。
記得剛?cè)胄械臅r候,業(yè)內(nèi)有一個叫“雅虎軍規(guī)”的東西,是好多前端做頁面優(yōu)化參考的標(biāo)準(zhǔn)。其中有一條就是要將js文件放在body標(biāo)簽的底部。到現(xiàn)在很多年了,時代在變化,我們的網(wǎng)絡(luò)帶寬也在提升,“雅虎軍規(guī)”中的一些內(nèi)容,可能有些已經(jīng)不適合我們現(xiàn)在應(yīng)用開發(fā)的場景。而且我覺的做技術(shù)不應(yīng)該拘泥于已有的一些規(guī)定,而應(yīng)該按照我們的場景選擇適合我們的技術(shù)和解決方案。
縱然有瑕疵,有些也是可以通過技術(shù)手段來解決的。比如在head標(biāo)簽中引入計算font-size和檢測設(shè)備獨立像素比的js的時候,會擔(dān)心js的執(zhí)行阻塞頁面的渲染。而我們完全可以通過review的方式確定js代碼的執(zhí)行不會出現(xiàn)阻塞,而影響文檔流的加載。
還是那句話:沒有十全十美的技術(shù)方案,只有適合不合適當(dāng)前業(yè)務(wù)場景的技術(shù)方案。。
參考文章[css3的字體大小單位[rem]到低好在哪里](https://www.zhihu.com/questio...
移動端高清、多屏適配方案
使用Flexible實現(xiàn)手淘H5頁面的終端適配
lib-flexible源代碼
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/80622.html
摘要:不要再問我的問題系列一不要再問我的指向問題了二不要再問我跨域的問題了移動端適配的問題,一般來說我們都不會去深究,因為這種東西都是配置一次就再也不用管的了,接到設(shè)計圖就按照祖?zhèn)魈茁窋]就完事了。 不要再問我XX的問題系列:一、不要再問我this的指向問題了二、不要再問我跨域的問題了 移動端適配的問題,一般來說我們都不會去深究,因為這種東西都是配置一次就再也不用管的了,接到設(shè)計圖就按照祖?zhèn)?..
摘要:不要再問我的問題系列一不要再問我的指向問題了二不要再問我跨域的問題了移動端適配的問題,一般來說我們都不會去深究,因為這種東西都是配置一次就再也不用管的了,接到設(shè)計圖就按照祖?zhèn)魈茁窋]就完事了。 不要再問我XX的問題系列:一、不要再問我this的指向問題了二、不要再問我跨域的問題了 移動端適配的問題,一般來說我們都不會去深究,因為這種東西都是配置一次就再也不用管的了,接到設(shè)計圖就按照祖?zhèn)?..
摘要:不要再問我的問題系列一不要再問我的指向問題了二不要再問我跨域的問題了移動端適配的問題,一般來說我們都不會去深究,因為這種東西都是配置一次就再也不用管的了,接到設(shè)計圖就按照祖?zhèn)魈茁窋]就完事了。 不要再問我XX的問題系列:一、不要再問我this的指向問題了二、不要再問我跨域的問題了 移動端適配的問題,一般來說我們都不會去深究,因為這種東西都是配置一次就再也不用管的了,接到設(shè)計圖就按照祖?zhèn)?..
摘要:設(shè)備像素比縮寫簡稱,也就是我們經(jīng)常在谷歌控制臺移動端調(diào)試頂端會看到的一個值。在移動端,默認(rèn)的情況下,布局視口的寬度是要遠(yuǎn)遠(yuǎn)大于瀏覽器的寬度的。手淘團(tuán)隊布局現(xiàn)今,適配手機(jī)端 meta標(biāo)簽到底做了什么事情 做過移動端適配的小伙伴一定有遇到過這行代碼: 但是,很多小伙伴只是感性的認(rèn)識:噢,我加了這行代碼,然后頁面的寬度就會跟我的設(shè)備寬度一致。然而,這種理解是很片面的。那么,這句話的本質(zhì)到底...
閱讀 3348·2021-09-30 09:47
閱讀 2731·2021-08-18 10:22
閱讀 2518·2021-08-16 10:49
閱讀 2883·2019-08-30 15:53
閱讀 2731·2019-08-29 16:14
閱讀 3185·2019-08-28 18:18
閱讀 3228·2019-08-26 13:21
閱讀 786·2019-08-26 12:02