背景
移動(dòng)端設(shè)計(jì)稿一般是750px,如果沒(méi)有用taro或者uniapp這類的框架,就需要自己來(lái)進(jìn)行css的適配。
方案
一、Rem
rem是相對(duì)于根元素html字體大小的一個(gè)css單位,默認(rèn)情況下html的font-size=16px,所以1rem = 16px??梢詣?dòng)態(tài)設(shè)置html的字體大小,比如設(shè)置html的font-size=100px,那么1rem=100px。重點(diǎn)就是動(dòng)態(tài)設(shè)置html字體大小。
第一步
先在html的head標(biāo)簽中加一個(gè)meat標(biāo)簽
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
意思是讓當(dāng)前視口的寬度等于設(shè)備的寬度,同時(shí)不允許用戶手動(dòng)縮放。
第二步
如果只是簡(jiǎn)單的一兩個(gè)頁(yè)面,html直接梭了,甚至都不需要用react、vue,那么可以繼續(xù)在head中引入這段js
<script>
function setSize() {
var baseWidth = 750 // 設(shè)計(jì)稿尺寸
var clientWidth = document.documentElement.clientWidth
if (clientWidth >= 750) {
clientWidth = 750
}
var fontSize = (clientWidth / baseWidth) * 100 // 乘以100是為了方便計(jì)算
window.document.documentElement.style.fontSize = fontSize + 'px'
}
setSize()
window.addEventListener('resize', setSize)
</script>
寫樣式的時(shí)候,100px*100px的寬高可以寫成width:1rem;height:1rem
,50px*50px的寬高可以寫成width:0.5rem;height:0.5rem
,其實(shí)就是設(shè)計(jì)稿里的尺寸/100
如果是正常開發(fā)一個(gè)項(xiàng)目,這么去換算肯定麻煩,肯定是需要自動(dòng)換算,插件postcss-pxtorem
可以滿足這個(gè)需求,這時(shí)候需要加入另一段js。用上面一段也沒(méi)什么大問(wèn)題,核心就是設(shè)計(jì)稿尺寸下的字體大小,上面的js在iPhone6下fontSize是50px,那么插件rootValue值要設(shè)置成50,下面這段js在iPhone6下fontSize是16px,那么插件rootValue值要設(shè)置成16
<script>
function setSize() {
var baseFontSize = 16; // 這個(gè)值要和下面插件的rootValue值一樣
var baseWidth = 375; // 設(shè)計(jì)稿尺寸
var clientWidth = document.documentElement.clientWidth;
if (clientWidth > 750) {
clientWidth = 750;
}
document.documentElement.style.fontSize =
baseFontSize * (clientWidth / baseWidth) + "px";
}
setSize();
window.addEventListener("resize", setSize);
</script>
1、安裝
使用postcss-pxtorem
前提是需要安裝 postcss postcss-loader
npm i postcss postcss-loader postcss-pxtorem -D
2、webpack配置
或者新建一個(gè) postcss.config.js 文件也行(.json,.yaml格式的文件都行,看個(gè)人習(xí)慣)
// 引入插件
const Pxtorem = require('postcss-pxtorem');
module.export = {
module:{
rules:[
{
test: /\.css$/i,
use: [
"style-loader",
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
Pxtorem({
rootValue: 16,
unitPrecision: 5,
propList: ['*'],
selectorBlackList: [],
replace: true,
mediaQuery: false,
minPixelValue: 0,
// exclude: /node_modules/i
})
],
},
},
},
],
},
]
}
}
postcss-pxtorem
的默認(rèn)配置如下
{
rootValue: 16,
unitPrecision: 5,
propList: ['font', 'font-size', 'line-height', 'letter-spacing'],
selectorBlackList: [],
replace: true,
mediaQuery: false,
minPixelValue: 0,
exclude: /node_modules/i
}
-
rootValue
:根結(jié)點(diǎn)的字體大小,默認(rèn)16,可以設(shè)置一個(gè)具體的數(shù)值,或者可以是一個(gè)函數(shù),返回一個(gè)數(shù)值。如果用到了UI庫(kù),可能UI庫(kù)是按照375,設(shè)計(jì)稿是750,就可以通過(guò)函數(shù)來(lái)設(shè)置rootValue。該函數(shù)有一個(gè)參數(shù),是一個(gè)對(duì)象,可以通過(guò)file
字段來(lái)判斷是自己寫的樣式還是UI庫(kù)的樣式,file
是當(dāng)前文件的路徑。function ({file}) { return file.indexOf('exclude') !== -1; }
-
unitPrecision
:保留幾位小數(shù) -
propList
:一個(gè)數(shù)組。表示哪些屬性能轉(zhuǎn)化成rem- 屬性必須完成匹配。比如
height
,width
- 使用通配符 * 啟用所有屬性。[‘*’]
- 在單詞的開頭或結(jié)尾使用 *來(lái)匹配。比如[“*positons*”,“*height”]會(huì)匹配到
background-position-y
和min-height
、max-height
- 使用!不匹配屬性。比如 [“!height”] 就不會(huì)轉(zhuǎn)換height
- 可以將!和* 結(jié)合使用。比如 [“!font*”] font-size將不會(huì)轉(zhuǎn)換
- 屬性必須完成匹配。比如
-
selectorBlackList
:一個(gè)數(shù)組,要忽略的選擇器,保留為px。- 如果是一個(gè)字符串,那么會(huì)檢查選擇器是否包含該字符串,比如[‘body’] 會(huì)匹配到
.body-main
- 如果是一個(gè)正則,會(huì)檢查該選擇器和正則是否匹配,比如[/^body$/] 會(huì)匹配
body
但是不會(huì)匹配.body
- 如果是一個(gè)字符串,那么會(huì)檢查選擇器是否包含該字符串,比如[‘body’] 會(huì)匹配到
-
replace
:Boolean,是否替換包含rem的規(guī)則,而不是添加回退 -
mediaQuery
:Boolean,是否允許在媒體查詢中轉(zhuǎn)換px -
minPixelValue
:數(shù)值,設(shè)置要替換的最小像素值 -
exclude
:(String, Regexp, Function) 要忽略并保留為px的文件路徑- 如果是string,則檢查文件路徑是否包含該字符串
- 如果是regexp,則檢查文件路徑是否與regexp匹配
- 如果是function,則可以使用函數(shù)返回true,文件將被忽略,回調(diào)函數(shù)將文件路徑作為參數(shù)傳遞
function (file) { return file.indexOf('exclude') !== -1; }
如果只是單個(gè)屬性需要忽略,最簡(jiǎn)單的是大寫PX
// `px` 會(huì)轉(zhuǎn)成 `rem`
.convert {
font-size: 16px; // 會(huì)被轉(zhuǎn)成rem
}
// `Px` or `PX` 會(huì)被忽略,但是在瀏覽器里面仍然可以用
.ignore {
border: 1Px solid; // ignored
border-width: 2PX; // ignored
}
二、vw vh
vw和vh是瀏覽器視口(viewport)的單位,簡(jiǎn)單理解就是1vw是屏幕寬度的1%,1vh是屏幕高度的1%,此外還有vmin:vw和vh中較小的那個(gè),vmain:vw和vh中較大的那個(gè)。
vw也不用自己手動(dòng)去換算,現(xiàn)在瀏覽器都支持vw、vh,可以用postcss-px-to-viewport
插件進(jìn)行轉(zhuǎn)換,和rem的插件用法類似(本身也是受postcss-pxtorem
啟發(fā))
1、安裝
npm i postcss postcss-loader postcss-px-to-viewport -D
2、webpack配置
// 引入插件
const postcssPxToViewport = require("postcss-px-to-viewport");
module.export = {
module:{
rules:[
{
test: /\.css$/i,
use: [
"style-loader",
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
postcssPxToViewport({
viewportWidth: 320, // 設(shè)計(jì)稿寬度
unitPrecision: 5, // px轉(zhuǎn)換后的小數(shù)保留位數(shù)
minPixelValue: 1, // 小于多少像素不轉(zhuǎn)換
selectorBlackList: ["ignore-"], // 有ignore-* 的類名不會(huì)被轉(zhuǎn)換
}),
],
},
},
},
],
},
]
}
}
postcss-px-to-viewport
的默認(rèn)配置如下
{
unitToConvert: 'px',
viewportWidth: 320,
unitPrecision: 5,
propList: ['*'],
viewportUnit: 'vw',
fontViewportUnit: 'vw',
selectorBlackList: [],
minPixelValue: 1,
mediaQuery: false,
replace: true,
exclude: undefined,
include: undefined,
landscape: false,
landscapeUnit: 'vw',
landscapeWidth: 568
}
-
unitToConvert
(String) 需要轉(zhuǎn)換的單位,默認(rèn)為"px" -
viewportWidth
(Number) 設(shè)計(jì)稿的視口寬度 -
unitPrecision
(Number) 單位轉(zhuǎn)換后保留的精度 -
propList
(Array) 能轉(zhuǎn)化為vw的屬性列表- 傳入特定的CSS屬性;
- 可以傳入通配符""去匹配所有屬性,例如:[‘’];
- 在屬性的前或后添加"*",可以匹配特定的屬性. (例如[‘position’] 會(huì)匹配
background-position-y
) - 在特定屬性前加 “!”,將不轉(zhuǎn)換該屬性的單位 . 例如: [‘*’, ‘!letter-spacing’],將不轉(zhuǎn)換
letter-spacing
- “!” 和 ""可以組合使用, 例如: [‘’, ‘!font*’],將不轉(zhuǎn)換
font-size
以及font-weight
等屬性
- viewportUnit (String) 希望使用的視口單位
-
fontViewportUnit
(String) 字體使用的視口單位 -
selectorBlackList
(Array) 需要忽略的CSS選擇器,不會(huì)轉(zhuǎn)為視口單位,使用原有的px等單位。- 如果傳入的值為字符串的話,只要選擇器中含有傳入值就會(huì)被匹配,例如 selectorBlackList 為 [‘body’] 的話, 那么
.body-class
就會(huì)被忽略 - 如果傳入的值為正則表達(dá)式的話,那么就會(huì)依據(jù)CSS選擇器是否匹配該正則 ,例如 selectorBlackList 為 [/^body$/] , 那么
body
會(huì)被忽略,而.body
不會(huì).
- 如果傳入的值為字符串的話,只要選擇器中含有傳入值就會(huì)被匹配,例如 selectorBlackList 為 [‘body’] 的話, 那么
-
minPixelValue
(Number) 設(shè)置最小的轉(zhuǎn)換數(shù)值,如果為1的話,只有大于1的值會(huì)被轉(zhuǎn)換 -
mediaQuery
(Boolean) 媒體查詢里的單位是否需要轉(zhuǎn)換單位 -
replace
(Boolean) 是否直接更換屬性值,而不添加備用屬性 -
exclude
(Array or Regexp) 忽略某些文件夾下的文件或特定文件,例如 ‘node_modules’ 下的文件- 如果值是一個(gè)正則表達(dá)式,那么匹配這個(gè)正則的文件會(huì)被忽略
- 如果傳入的值是一個(gè)數(shù)組,那么數(shù)組里的值必須為正則
-
include
(Array or Regexp) 如果設(shè)置了include,那將只有匹配到的文件才會(huì)被轉(zhuǎn)換,例如只轉(zhuǎn)換 ‘src/mobile’ 下的文件 (include: /\/src\/mobile\//
)- 如果值是一個(gè)正則表達(dá)式,將包含匹配的文件,否則將排除該文件
- 如果傳入的值是一個(gè)數(shù)組,那么數(shù)組里的值必須為正則
-
landscape
(Boolean) 是否添加根據(jù) landscapeWidth 生成的媒體查詢條件 @media (orientation: landscape) -
landscapeUnit
(String) 橫屏?xí)r使用的單位 -
landscapeWidth
(Number) 橫屏?xí)r使用的視口寬度
exclude和include是可以一起設(shè)置的,將取兩者規(guī)則的交集。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-761989.html
最后
個(gè)人感覺(jué)移動(dòng)端適配這兩種方案都行,rem算是大家用的比較久的,vw是后發(fā)展的方案文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-761989.html
到了這里,關(guān)于移動(dòng)端適配 rem、postcss-pxtorem、postcss-px-to-viewport、vw vh的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!