物理像素
iphone 6 的寬度有750給物理像素
邏輯像素
也叫設備的獨立像素,css像素也是邏輯像素的一種
邏輯像素比(dpr)
物理像素➗邏輯像素,iphone6 的dpr=2
常見問題
- 圖片模糊
- 1px問題
1.圖片模糊
一個圖片大小200px * 200px(邏輯像素) 在dpr爲1的屏幕下顯示正常,在dpr爲2的情況下那麼在200px * 200px(邏輯像素)下物理像素是400px * 400px(物理像素)
本來一個物理像素點就好了現在變成了(2*2)個,那麼問題來了,其他的物理像素點會去找相近的顏色去填充,所以就變的模糊了
2.1px問題
這個問題很有意思,真的給我上了一課以後看文章,真的要多看一些在做出選擇爲什麼呢?
網上很多人的說法:因爲dpr>1所以導致邊框線變粗,我就很奇怪1px變粗,那爲什麼沒有2px問題,3px問題,4px問題...,爲什麼2px,3px,4px不會變粗,然道他們的dpr不是>1嗎?明顯他們就說錯了,但是哇,就很誇張很多人寫的都是因爲dpr的原因?
我認爲:其實就是在一個750px的設計圖上的邊框爲1px那麼按照比例在iphone6-375px-下顯示的的邊框按比例是0.5px其實就是作用而已,其實有些公司會把這個1px在移動端變成.5px(阿里巴巴,JD)都是變了的,但是也有沒有變的爲什麼呢?應爲其實邊框本來就是不支持百分比的所以其實我認爲按照css規範其實設計圖1px那麼不管在什麼屏幕下應該都是1px,而不是去縮放邊框(閱文的官網,google)我看的就是1px還是1px,其實這個和UI說的算的咯,解決就網上好多文章哈哈
國內知名互聯網企業移動端H5尺寸適配方案
1.很多年前淘寶的lib-flexible移動端配置方案
原理:通過dpr,去動態生成縮放視口,從而邏輯像素等於物理像素,那麼在動態生成html下的字體大小就可以控制rem了,比如在750的設計稿下,一個div爲75px,那麼我們可以1rem,
縮放視圖
var scale = 1 / devicePixelRatio;
document.querySelector('meta[name="viewport"]').setAttribute('content','initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
根據不同移動設備動態計算font-size
document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';
但是這個已經被淘汰了,由於viewport
單位得到衆多瀏覽器的兼容,lib-flexible
這個過渡方案已經可以放棄使用
JD
/* JD的移動端刷屏 */
html {
font-size: 20px;
font-size: 5.33333vw
/* 3.75px * 5.33333 ~ 20px */
}
@media screen and (max-width:320px) {
html {
font-size: 17.06667px
}
}
@media screen and (min-width:540px) {
html {
font-size: 28.8px
}
}
其實這個就很有意思,不會根據屏幕大小改變一點就去變一點,而是在一個範圍,然後再彈性佈局
百度
html {
font-size: 100px
}
@media screen and (max-width: 360px) {
html {
font-size:90px;
line-height: 90px
}
}
body {
font-size: 16px;
}
網易
(1)以iphone6作爲參照,iphone6的寬度是375px,dpr爲2,所以對於上面顯示的375px的圖,我們需要的圖片大小是750px,所以我們拿到的psd設計圖的寬度必須是750px。爲了方便書寫rem,我們希望psd設計圖上750px對應的rem是7.5rem。而設計圖上面750px在iphone6上面的實際大小是375px,所以我們需要設置iphone6的font-size=375/7.5px=50px。更一般地,由於移動端的font-size的默認值是16px,所以我們更傾向於用一個百分比來設置font-size:font-size=50/16=312.5%。(注意:用px和百分比沒有本質上的不同。)
(2)在其它屏幕上進行縮放,爲了解決這個問題,我們用js來讀取屏幕的寬度,然後利用這個寬度來進行縮放,代碼如下:
var initScreen=function(){
$("html").css("font-size", document.documentElement.clientWidth / 375 * 312.5 + "%");
}
最後,我們需要解決橫屏問題和用戶手動縮放問題,他們本質上都是改變屏幕寬度的問題,所以我們監聽resize事件或者onorientationchange事件,當發生的時候,重新調用initScreen方法。代碼如下:
$(window).on('onorientationchange' in window ? 'orientationchange' : 'resize', function () {
setTimeout(initScreen, 200);
});
注意:上面的代碼並不是原生js,要引入zepto庫!也可以用原生js實現,不過要考慮兼容性問題,我就不貼出代碼了。
注意:我這種適配方案中,1rem的實際大小是50px,而不是100px。所以0.12rem的字體,在設計稿上面是12px,但是在手機上的實際大小是6px
另外,爲了增加代碼的健壯性,在js加載不成功的時候也能進行適配,建議在css加上媒體查詢:
@media screen and (max-width: 320px) {
html {
font-size:42.667px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 321px) and (max-width:360px) {
html {
font-size:48px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 361px) and (max-width:375px) {
html {
font-size:50px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 376px) and (max-width:393px) {
html {
font-size:52.4px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 394px) and (max-width:412px) {
html {
font-size:54.93px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 413px) and (max-width:414px) {
html {
font-size:55.2px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 415px) and (max-width:480px) {
html {
font-size:64px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 481px) and (max-width:540px) {
html {
font-size:72px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 541px) and (max-width:640px) {
html {
font-size:85.33px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 641px) and (max-width:720px) {
html {
font-size:96px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 721px) and (max-width:768px) {
html {
font-size:102.4px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 769px) {
html {
font-size:102.4px;
font-size: 13.33333vw
}
}
目前淘寶
解讀
1.開始函數先來匿名函數
2.找到HTML文檔對象,因爲後面要給他定義fontSize的值;
3.找到dpr的值,如果大於等於2,就給這個設備設置0.5px的邊框
4.除以3.75的解釋:如果設計圖爲750那麼就是除以7.5爲什麼是7.5 ? 因爲我們以100px爲1rem那麼750的設計圖爲7.5rem,那麼我們要求出不同設備的rem的值就是用n.clientWidth/7.5就是rem的值
5.函數i給html定義fontSize的值
6.最後if()中的條件:
6-1:判斷 是否存在document.body 再設置html標籤的font-size的值
6-2:設置html標籤的font-size的值,
6-3:設置監聽橫屏事件,和判斷是否是緩存
6-4:最後判斷drp的值:是否設置.5px的邊框
7.if{}中的代碼是判斷是否支持.5px,支持添加屬性hairlines
// 解讀
// e = window ; t = document
// n === document.documentElement 是一個會返回文檔對象(document)的根元素的只讀屬性(如HTML文檔的 <html> 元素
// d === window.devicePixelRatio 返回當前顯示設備的dpr
// 這裏 / 3.75 的解釋
// 設計圖以iPhone6的分辨率爲標準(750x1334)
// 把上面代碼中的3.75改爲7.5(如果設計圖以375x667爲標準則不用改)
// 前端寫CSS時把設計圖的單位統一以除以100,然後使用rem單位。
!function (e, t) {
var n = t.documentElement // document.documentElement
, d = e.devicePixelRatio || 1; // dpr
function i() {
var e = n.clientWidth / 3.75;
n.style.fontSize = e + "px"
}
// 判斷 是否存在document.body 再設置html標籤的font-size的值,監聽橫屏事件,和判斷是否是緩存,和判斷drp的值
if (function e() {
t.body ? t.body.style.fontSize = "16px" : t.addEventListener("DOMContentLoaded", e)
}(),
i(),
e.addEventListener("resize", i), // 當屏幕變成橫屏的時候觸發事件
// onpageshow 事件類似於 onload 事件,onload 事件在頁面第一次加載時觸發, onpageshow 事件在每次加載頁面時觸發,即 onload 事件在頁面從瀏覽器緩存中讀取時不觸發
e.addEventListener("pageshow", function (e) {
// e.persisted : 返回boolead類型 是否是來自緩存數據,如果是那麼也會觸發i()
e.persisted && i()
}),
// 當 drp 大於等於2的時候
2 <= d) {
// 以下代碼是再處理.5xp的兼容問題
// createElement//創建元素節點
var o = t.createElement("body")
, a = t.createElement("div");
a.style.border = ".5px solid transparent",
// appendChild//讓他成爲這個文檔現有節點的一個子節點
o.appendChild(a),
n.appendChild(o),
// offsetHeight 元素再垂直方向上的時間 offsetHeight=height+padding+border
// 判斷是否支持.5px支持,添加屬性
// classList.add 添加屬性
1 === a.offsetHeight && n.classList.add("hairlines"),
// removeChild() //方法可從子節點列表中刪除某個節點
n.removeChild(o)
}
}(window, document)