大遷世界 1周前
大遷世界
我要先堅(jiān)持分享20年,大家來一起見證吧。
564篇原創(chuàng)內(nèi)容
公眾號(hào)
作者: suoyuesmile https://github.com/suoyuesmile/suo-blog/edit/master/articals/h5/0002.md前言
最近寫第三個(gè)移動(dòng)端 H5 的項(xiàng)目了,準(zhǔn)備記錄下自己在 H5 項(xiàng)目中的一些實(shí)踐探索。移動(dòng)端 H5 與 PC 端開發(fā)最大的區(qū)別之一,大概就是響應(yīng)式布局問題。
那么下面我們來聊聊移動(dòng)端響應(yīng)式布局,了解他的來龍去脈,對(duì)現(xiàn)有的最佳解決方案探索。
問題
全文將圍繞下面幾個(gè)問題進(jìn)行論述和展開:
寫移動(dòng)端 H5 相關(guān)頁面,相比 PC 端有哪些值得注意的點(diǎn)?
關(guān)于H5 響應(yīng)式布局有哪些解決方案?
什么是 rem?如何在項(xiàng)目中完美使用它?
vh/vw 是最佳解決方案嗎?它有什么優(yōu)勢(shì)和缺陷
大型開源庫里面常用解決方案是什么?
怎樣快速搭建一套移動(dòng)端布局解決方案?
由來
概念
什么是 H5 技術(shù)?
H5 這個(gè)命名本身是一個(gè)很不討巧的命名,咋一眼看上去認(rèn)為 HTML5,或者第 5 級(jí)標(biāo)題的標(biāo)簽,對(duì)一些造成一些不小的誤解。
比如:我的一個(gè)某后端同事,談?wù)摰?H5 很簡單,HTML 之前我也學(xué)過一些,以后要是你請(qǐng)假,我來幫你寫。
我是一臉蒙蔽,H5 === HTML?
再看看,搜索引擎中H5是什么?(引用來自谷歌詞條第一頁)
如此看來,將 H5 視作 HTML 的大有人在,而 H5 這個(gè)概念只在中國特有,所以對(duì)外國人來說他們也認(rèn)為是 HTML, 所以,對(duì)于外國人和非這個(gè)領(lǐng)域的人來說,他們存在一樣的誤解。
目前的 H5 算是一個(gè)比較大的概念了,我認(rèn)為的 H5 技術(shù)是一系列移動(dòng)端 web 前端技術(shù)的集合 大致用一個(gè)韋恩圖表示如下
我們這里只談 web 前端中 H5 技術(shù),H5 技術(shù)本身是用于移動(dòng)端的 web 網(wǎng)頁。由于App本身有個(gè) “ webview ” 的容器,在容器里可以運(yùn)行 web 前端相關(guān)代碼,由此 H5 和原生 App 結(jié)合又衍生出來了 Hybrid App 技術(shù)。
Hybrid App 技術(shù)大致原理
這是我給公司同事普及 H5 知識(shí)繪制的圖像。
實(shí)踐
解決方案一:rem + pxToRem
概念
css 中用于計(jì)量的單位有兩種,一種是絕對(duì)單位,另一種是相對(duì)單位
絕對(duì)單位
對(duì)于絕對(duì)單位,一般來說常用的也就 px, 其他的可能打印需要用到
相對(duì)單位
對(duì)于相對(duì)單位來說,em 和 rem 屬于一對(duì),vw 和 vh 屬于一對(duì)。
前一對(duì)相對(duì)于字體大小,區(qū)別在于 rem 相對(duì)于根字體,對(duì)于我們控制整體的大小相對(duì)容易些,所以我們可以使用它來控制整個(gè)頁面的縮放。
后一對(duì),相對(duì)于視窗的大小,這個(gè)將在下一個(gè)節(jié)中發(fā)揮主要作用。
原理
監(jiān)聽屏幕視窗的寬度,通過一定比例換算賦值給html的font-size。此時(shí),根字體大小就會(huì)隨屏幕寬度而變化。
將 px 轉(zhuǎn)換成 rem, 常規(guī)方案有兩種,一種是利用sass/less中的自定義函數(shù) pxToRem,寫px時(shí),利用pxToRem函數(shù)轉(zhuǎn)換成 rem。另外一種是直接寫px,編譯過程利用插件全部轉(zhuǎn)成rem。這樣 dom 中元素的大小,就會(huì)隨屏幕寬度變化而變化了。
實(shí)現(xiàn)
動(dòng)態(tài)更新根字體大小
const MAX_FONT_SIZE = 420
// 定義最大的屏幕寬度
document.addEventListener('DOMContentLoaded', () => {
const html = document.querySelector('html')
let fontSize = window.innerWidth / 10
fontSize = fontSize > MAX_FONT_SIZE ? MAX_FONT_SIZE : fontSize
html.style.fontSize = fontSize + 'px'
})
px 轉(zhuǎn) rem
pxToRem 方案一
$rootFontSize: 375 / 10;
// 定義 px 轉(zhuǎn)化為 rem 的函數(shù)
@function px2rem ($px) {
@return $px / $rootFontSize + rem;
}
.demo {
width: px2rem(100);
height: px2rem(100);
}
pxToRem方案二
vue-cli3 中配置 裝 postcss-pxtorem 插件就可以了,其他平臺(tái)大致差不多
const autoprefixer = require('autoprefixer')
const pxtorem = require('postcss-pxtorem')
module.exports = {
// ...
css: {
sourceMap: true,
loaderOptions: {
postcss: {
plugins: [
autoprefixer(),
pxtorem({
rootValue: 37.5,
propList: ['*']
})
]
}
}
}
}
點(diǎn)擊快速配置 H5 項(xiàng)目工程
繼續(xù)探索postcss-pxtorem插件源碼,查看它實(shí)現(xiàn)的原理
function createPxReplace (rootValue, unitPrecision, minPixelValue) {
return function (m, $1) {
if (!$1) return m;
var pixels = parseFloat($1);
if (pixels < minPixelValue) return m;
var fixedVal = toFixed((pixels / rootValue), unitPrecision);
return (fixedVal === 0) ? '0' : fixedVal + 'rem';
};
}
px變換成 rem 主要是這個(gè)函數(shù),當(dāng)然里面有很多可配置的參數(shù), 核心原理和我們方案一差不多,方便在于,不需要每次寫px都要加上一個(gè)函數(shù),代碼也清晰很多
是不是所有元素 px 都要轉(zhuǎn)換成 rem呢?,那可不一定哦,border 中的 px 不應(yīng)該轉(zhuǎn) rem,涉及到另外一個(gè) 1px 的問題,上一篇文章詳細(xì)論述過,避免 px 轉(zhuǎn) rem,將 border 中的 px 大寫成 PX/Px/pX
1px 適配問題請(qǐng)移至 吃透移動(dòng)端 1px
解決方案二:vh + vw
原理
vw 相對(duì)于視窗寬度的單位,隨寬度變化而變化。由此看來,方案一其實(shí)是方案二的一種 Hack, 通過使用監(jiān)聽實(shí)現(xiàn)了方案二的效果
實(shí)現(xiàn)
與 rem 類似做法,直接使用 postcss-px-to-viewport 插件進(jìn)行配置, 配置方式也是和 postcss-pxtorem 大同小異
我們看看插件的原理是不是也是一樣的
function createPxReplace(opts, viewportUnit, viewportSize) {
return function (m, $1) {
if (!$1) return m;
var pixels = parseFloat($1);
if (pixels <= opts.minPixelValue) return m;
var parsedVal = toFixed((pixels / viewportSize * 100), opts.unitPrecision);
return parsedVal === 0 ? '0' : parsedVal + viewportUnit;
};
}
果然呢,連方法名、變量名、代碼邏輯,都一摸一樣哈哈哈,誰抄誰,我就不指出來啦 - -
其他解決方案
方案缺陷
1百分比高度無法百分比
2媒體查詢 + meta 中 viewport不同設(shè)備寬度不同,縮放比無法完全確定
3flex還是無法解決寬度超出問題
上面方案均存在致命缺陷,不推薦使用它完成移動(dòng)端布局計(jì)算。
flex 與 rem 結(jié)合使用更佳
兼容性
上述兩種方案,兼容性主要在于 rem,vh,vw 關(guān)鍵詞上
rem在移動(dòng)端表現(xiàn)高達(dá) 100%,令人驚嘆!
vh vw 表現(xiàn)慘不忍睹
不得不說 rem 仍然是移動(dòng)端 h5 布局的最佳方案
開源庫解決方案
vant 組件庫
vant 組件庫中,默認(rèn)采用 px 做計(jì)量單位,如果需要使用 rem,直接使用插件完美適配。
對(duì)于 vw 方案,vant 也是可以通過插件將 px 轉(zhuǎn)成 vw,對(duì)于 vw 可能會(huì)存在一些坑點(diǎn)。
ant-design-mobile 組件庫
ant-design-mobile 組件庫仍然使用 px 單位
@hd: 1px; // 基本單位
// 字體尺寸
// ---
@font-size-icontext: 10 * @hd;
@font-size-caption-sm: 12 * @hd;
@font-size-base: 14 * @hd;
@font-size-subhead: 15 * @hd;
@font-size-caption: 16 * @hd;
@font-size-heading: 17 * @hd;
// 圓角
// ---
@radius-xs: 2 * @hd;
@radius-sm: 3 * @hd;
@radius-md: 5 * @hd;
@radius-lg: 7 * @hd;
@radius-circle: 50%;
// 邊框尺寸
// ---
@border-width-sm: 1PX;
@border-width-md: 1PX;
@border-width-lg: 2 * @hd;
與 vant 組件一樣,還是由開發(fā)者來決定到底用哪一種方案 這種把選擇權(quán)交給開發(fā)者,算是一種開源庫的最靈活的做法了。
總結(jié)
通過該文,你大概了解 H5 問題的來龍去脈了吧,也明白了如何解決移動(dòng)端響應(yīng)式布局問題,如果這票文章能解決你的疑問或者工作中問題,不妨點(diǎn)個(gè)贊收藏下。
由于技術(shù)水平有限,文章中如有錯(cuò)誤地方,請(qǐng)?jiān)谠u(píng)論區(qū)指出,感謝!
上一篇文章 解決了 1px 問題,這篇文章解決了響應(yīng)式布局問題, 接下我應(yīng)該會(huì)繼續(xù)研究下關(guān)于 H5 一些踩坑總結(jié),之后應(yīng)該回去研究下 vue 最新的源碼再進(jìn)行分享,想持續(xù)了解更多,不妨點(diǎn)個(gè)關(guān)注。
大遷世界
我要先堅(jiān)持分享20年,大家來一起見證吧。
564篇原創(chuàng)內(nèi)容
公眾號(hào)
喜歡此內(nèi)容的人還喜歡
推薦幾款 Redis 可視化工具
推薦幾款 Redis 可視化工具
...
Hollis
不喜歡
不看的原因
確定
內(nèi)容質(zhì)量低
不看此公眾號(hào)
GitHub 熱榜:谷歌大佬又一開源神作,Python 調(diào)試?yán)鳎?div style="height:15px;">