1. px与视口
2. %
3. 媒体查询
4. rem
5. vm/vh
首先来看,什么是rem单位。rem是一个灵活的、可扩展的单位,由浏览器转化像素并显示。与em单位不同,rem单位无论嵌套层级如何,都只相对于浏览器的根元素(HTML元素)的font-size。默认情况下,html元素的font-size为12px,所以:
1 rem = 12px
为了计算方便,通常可以将html的font-size设置成:
html{ font-size: 67.5% }
这种情况下:
1 rem = 10px
rem单位都是相对于根元素html的font-size来决定大小的,根元素的font-size相当于提供了一个基准,当页面的size发生变化时,只需要改变font-size的值,那么以rem为固定单位的元素的大小也会发生响应的变化。
如果通过rem来实现响应式的布局,只需要根据视图容器的大小,动态的改变font-size即可。
function refreshRem() {
var docEl = doc.documentElement;
var width = docEl.getBoundingClientRect().width;
var rem = width / 10;
docEl.style.fontSize = rem + 'px';
flexible.rem = win.rem = rem;
}
win.addEventListener('resize', refreshRem);
上述代码中将视图容器分为10份,font-size用十分之一的宽度来表示,最后在header标签中执行这段代码,就可以动态定义font-size的大小,从而1rem在不同的视觉容器中表示不同的大小,用rem固定单位可以实现不同容器内布局的自适应。
如果在响应式布局中使用rem单位,那么存在一个单位换算的问题,rem2px表示从rem换算成px,这个就不说了,只要rem乘以相应的font-size中的大小,就能换算成px。更多的应用是px2rem,表示的是从px转化为rem。
比如给定的视觉稿为750px(物理像素),如果我们要将所有的布局单位都用rem来表示
一种比较笨的办法就是对所有的height和width等元素,乘以相应的比例,现将视觉稿换算成rem单位,然后一个个的用rem来表示。
另一种比较方便的解决方法就是,在css中我们还是用px来表示元素的大小,最后编写完css代码之后,将css文件中的所有px单位,转化成rem单位。
px2rem的原理也很简单,重点在于预处理以px为单位的css文件,处理后将所有的px变成rem单位。可以通过两种方式来实现:
<!--1) webpack loader的形式:-->
npm install px2rem-loader
<!--在webpack的配置文件中:-->
module.exports = {
// ...
module: {
rules: [{
test: /\.css$/,
use: [{
loader: 'style-loader'
}, {
loader: 'css-loader'
}, {
loader: 'px2rem-loader',
// options here
options: {
remUni: 75,
remPrecision: 8
}
}]
}]
}
}
<!--2)webpack中使用postcss plugin-->
npm install postcss-loader
<!--在webpack的plugin中:-->
var px2rem = require('postcss-px2rem');
module.exports = {
module: {
loaders: [
{
test: /\.css$/,
loader: "style-loader!css-loader!postcss-loader"
}
]
},
postcss: function() {
return [px2rem({remUnit: 75})];
}
}
1)vue2 中
Vue-cli2.x中的用法
1)下载lib-flexible
npm i lib-flexible --save
2)引入lib-flexible
<!--在main.js中引入lib-flexible-->
import 'lib-flexible/flexible'
3)设置meta标签
<!--通过meta标签,设置设备宽度以及缩放比例-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
4)安装px2rem-loader
npm install px2rem-loader --save-dev
<!--在build文件中找到util.js,将px2rem-loader添加到cssLoaders中-->
const cssLoader = {
loader: 'css-loader',
options: {
minimize: process.env.NODE_ENV === 'production',
sourceMap: options.sourceMap
}
}
const px2remLoader = {
loader: 'px2rem-loader',
options: {
remUnit: 75
}
}
<!--在generateLoaders方法中添加px2remLoader-->
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
// const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
var loaders = [cssLoader,px2remLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
2)vue3 中的用法
lib-flexible:让网页根据设备dpr和宽度,利用viewport和html根元素的font-size配合rem来适配不同尺寸的移动端设备
1)安装lib-flexible
yarn add lib-flexible
2)引入lib-flexible
<!--在main.js中引入lib-flexible-->
import 'lib-flexible/flexible'
pxtorem:将项目中css的px转成rem单位,免去计算烦恼
1)安装postcss-pxtorem
yarn add postcss-pxtorem
2) 配置postcss-pxtorem
<!--package.json内,在postcss内添加-->
"postcss": {
"plugins": {
"autoprefixer": {},
"postcss-pxtorem": {
"rootValue": 75 // 设计稿宽度的1/10,
"propList":['*'],
// 需要做转化处理的属性,如`hight`、`width`、`margin`等,`*`表示全部
}
}
}
1、pxtorem中,对于想忽略的px写成大写即可,诸如 border:1PX solid #fff。
2、也可以选择postcss-px2rem,我更喜欢pxtorem的忽略方式,方便我vscode的beautify自动格式化代码。
3. rem 布局的缺点
通过rem单位,可以实现响应式的布局,特别是引入相应的postcss相关插件,免去了设计稿中的px到rem的计算。
rem单位在国外的一些网站也有使用,这里所说的rem来实现布局的缺点,或者说是小缺陷是:
在响应式布局中,必须通过js来动态控制根元素font-size的大小。
也就是说css样式和js代码有一定的耦合性。且必须将改变font-size的代码放在css样式之前。