基本概念
1、單位
Px(CSS pixels)
- 像素 (px) 是一種絕對單位(absolute units), 因為無論其他相關的設置怎么變化,像素指定的值是不會變化的
- 其實是相對於某個設備而言的,不同設備指定的值大小還是有區別的
em
- 1em與當前元素的字體大小相同(更具體地說,一個大寫字母M的寬度)。CSS樣式被應用之前,瀏覽器給網頁設置的默認基礎字體大小是16像素,這意味着對一個元素來說1em的計算值默認為16像素。但是要小心—em單位是會繼承父元素的字體大小,所以如果在父元素上設置了不同的字體大小,em的像素值就會變得復雜。現在不要過於擔心這個問題,我們將在后面的文章和模塊中更詳細地介紹繼承和字體大小設置。em是Web開發中最常用的相對單位。
ex, ch
- 分別是小寫x的高度和數字0的寬度。這些並不像em那樣被普遍使用或很好地被支持。
rem
- REM(root em)和em以同樣的方式工作,但它總是等於默認基礎字體大小的尺寸;繼承的字體大小將不起作用,所以這聽起來像一個比em更好的選擇,雖然在舊版本的IE上不被支持 查看關於跨瀏覽器支持 Debugging CSS.)
vw,vh
- 分別是視口寬度的1/100和視口高度的1/100,其次,它不像rem那樣被廣泛支持。 還有vmin,vmax...
百分比
rem 和 vw 兼容對比
-
rem
-
vw
2、關於window.devicePixelRatio
- 此屬性返回當前顯示設備的物理像素分辨率與CSS像素分辨率的比值。該值也可以被解釋為像素大小的比例:即一個CSS像素的大小相對於一個物理像素的大小的比值。
那么什么是設備的物理像素?
-
物理像素(physical pixel):設備能控制顯示的最小單位。設備獨立像素(DIP,device-independent pixel,density-independent pixel):獨立於設備的用於邏輯上衡量像素的單位
-
對於前端來說,可以理解成在設備上能設置的最小值。如在dpr = 1 最小值1px; dpr = 2 最小值為0.5px
PPI(pixel per inch)
- 每英寸有多少個像素點(設備像素點),PPI越高,畫質越好。
公式
// w: 橫向pixel
// h: 縱向pixel
// inch: 屏幕尺寸
PPI = Math.sqrt(w * w + h * h) / inch
console.log(Math.ceil(Math.sqrt(1920 * 1920 + 1080 * 1080) / 5.5))
// 然而我並不明白怎么要這樣算 不是應該是 w * h / inch ?????
具備足夠高像素密度而使得人體肉眼無法分辨其中單獨像素點的液晶屏
3、移動適配注意的點
-
屏幕尺寸不一樣的適配問題
- 這個可以借助vw完美解決
-
圖片模糊問題
- 圖片用三倍圖 可以保證清晰,推薦用兩倍圖+webp格式 開發和顯示效果折中的結果
-
1px 顯示問題
- 方法很多
-
api不支持的兼容問題
- vw不支持的兼容
-
高清顯示
- 是否影響渲染性能??待考證
- 縮放是否可以是網頁更高清?
- 第三方組件庫兼容問題
- 富文本顯示問題
- 前端代碼遷移單位不一致問題
適配方案
1、經典的flexble.js方案
存在問題
- 1、iframe 問題
- 2、富文本問題
// vue指令
// 1. 先獲取dpr 2獲取每個文檔對象的字體大小 乘以dpr
Vue.directive('richtext', (el, binding) => {
Vue.nextTick(() => {
let dpr = document.querySelector('html').getAttribute('data-dpr')
let f = (dom) => {
let fontPx = dom.style && dom.style.fontSize
if (fontPx) {
fontPx = fontPx.substr(0, fontPx.length - 2) * parseInt(dpr)
dom.style.fontSize = fontPx + 'px'
}
if (dom.childNodes.length > 0) {
for (let i = 0; i < dom.childNodes.length; i++) {
f(dom.childNodes[i])
}
}
}
f(el)
})
})
// 使用方法
.richtext(v-html="content" v-richtext='')
3、高清方案存在的誤區
dpr越高越清晰 是源自設備本身和縮放關系不大或者說當dpr為1時清晰度已經足夠了,不需要再通過縮放來是網頁顯示更清晰(實踐總結,未找到資料支持)
4、兼容問題
https://juejin.im/post/5b9cb9d26fb9a05d1b2e44a3
2、vw方案
3、rem + vw (推薦方案)
設置html根font-size的值
// 設計稿 750 * 1334
html {
height: 100%;
font-size: 50px; // 向下兼容 不止vw時候 寫死font-size
font-size: 13.33333333vw; // 7.5rem === 100vw
margin: 0 auto;
}
@media (min-width: 560px) { // pc兼容
html,body {
font-size: 54px;
max-width: 540px;
}
}
@media (max-width: 1024px) { // ipad兼容:ipad最大1024px
html,body {
max-width: 1024px;
}
}
1px顯示問題 物理像素 dpr>=2 取2倍
.border-bottom {
position: relative;
&::after {
content: '';
position: absolute;
z-index: 1;
pointer-events: none;
background-color: red;
height: 1px;
left: 0;
right: 0;
bottom: 0;
@media only screen and (min-resolution: 2dppx) { // 非標准的
-webkit-transform: scaleY(0.5);
-webkit-transform-origin: 50% 0%;
}
}
}
// only操作符僅在媒體查詢匹配成功的情況下被用於應用一個樣式,這對於防止讓選中的樣式在老式瀏覽器中被應用到
// -webkit-device-pixel-ratio 是一個非標准的布爾類型CSS媒體類型,是標准
// resolution 媒體類型的一個替代方案.
單位要怎么寫
方法一:postcss-px2rem(vue-cli3)
這里不推薦 因為px2rem: 寫px時需要加上 /*no*/ 感覺比較麻煩
const px2rem = require('postcss-px2rem')
const postcssPx2rem = new px2rem({
remUnit: 50 // 基准大小
})
css: {
loaderOptions: {
postcss: {
plugins: [postcssPx2rem]
},
}
},
方法二:目前方案是直接寫 7.5rem=100vw 設計稿除以100即可
方法三:px2rem的編輯器插件如vscode的cssrem
除不盡的問題 (calc)
涉及到兼容問題
總結 vw + rem的好處
- 實現簡單
- 不依賴插件及第三方庫
- 幾行css代碼 就可以實現
- 開發方便
- 100vw === 設計稿 / 100 rem 方便換算
- 不影響px使用,完美兼容第三方組件庫
- 不存在富文本和iframe等兼容問題