一、CSS3 Media Queries
- Media Queries定义
其作用就是允许添加表达式用以确定媒体的环境情况,以此来应用不同的样式表。(换句话说,其允许我们在不改变内容的情况下,改变页面的布局以精确适应不同的设备。 ) - 使用方式(两种)
- 方式一:直接在link中判断设备的尺寸,然后引用不同的css文件:
// 当屏幕的宽度大于600小于800时,应用styleB.css
<link rel="stylesheet" type="text/css" href="styleB.css" media="screen and (min-width: 600px) and (max-width: 800px)">
在media属性里:
(1)screen 是媒体类型里的一种,CSS2.1定义了10种媒体类型;
(2)and 被称为关键字,其他关键字还包括 not(排除某种设备),only(限定某种设备);
(3)(min-width: 400px) 就是媒体特性,其被放置在一对圆括号中。
- 方式二:即是直接写在<style>标签里:
@media screen and (max-width: 600px) { /*当屏幕尺寸小于600px时,应用下面的CSS样式*/
.class {
background: #ccc;
}
}
写法是前面加@media,其它跟link里的media属性相同。
其实基本上就是样式覆盖~,判断设备,然后引用不同的样式文件覆盖。
要注意的是由于网页会根据屏幕宽度调整布局,所以不能使用绝对宽度的布局,也不能使用具有绝对宽度的元素。这一条非常重要,否则会出现横向滚动条。
二、calc()
calc()使用通用的数学运算规则,但是也提供更智能的功能:
>使用“+”、“-”、“*” 和 “/”四则运算;
>可以使用百分比、px、em、rem等单位;
>可以混合使用各种单位进行计算;
>表达式中有“+”和“-”时,其前后必须要有空格,如"widht: calc(12%+5em)"这种没有空格的写法是错误的;
>表达式中有“*”和“/”时,其前后可以没有空格,但建议留有空格。
例如 :设置div元素的高度为当前窗口高度-80px
div{
height: calc(100vh - 80px);
}
或者利用%计算宽度
如: width: calc(100% - 10px);
vw Viewport宽度, 1vw 等于viewport宽度的1%
vh Viewport高度, 1vh 等于viewport高的的1%
三、rem
在JS引入rem,动态改变html的font-size。用rem动态改变字体大小:
;(function(win) {
var tid;
function refreshRem() {
let designSize = 1920; // 设计图尺寸
let html = document.documentElement;
let wW = html.clientWidth;// 窗口宽度
let rem = wW * 100 / designSize;
document.documentElement.style.fontSize = rem + 'px';
}
win.addEventListener('resize', function() {
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
}, false);
win.addEventListener('pageshow', function(e) {
if (e.persisted) {
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
}
}, false);
refreshRem();
})(window);
四、px 转 rem 方案
- less,sass,stylus三种预处理器px2rem
- less
//定义一个变量和一个mixin
@baseFontSize: 75;//基于视觉稿横屏尺寸/100得出的基准font-size
.px2rem(@name, @px){
@{name}: @px / @baseFontSize * 1rem;
}
//使用示例:
.container {
.px2rem(height, 240);
}
//less翻译结果:
.container {
height: 3.2rem;
}
- sass
//定义一个变量和一个mixin
$baseFontSize: 16;//默认基准font-size
@mixin px2rem($name, $px){
#{$name}: $px / $baseFontSize * 1rem;
}
// 使用示例:
.container {
@include px2rem(height, 240);
}
// scss翻译结果:
.container {
height: 3.2rem;
}
- stylus
//定义一个变量和一个mixin
$baseFontSize = 16; //默认基准font-size
px2rem(name, px){
{name}: px / $baseFontSize * 1rem;
}
// 使用示例:
.container {
px2rem('height', 240);
}
// stylus翻译结果:
.container {
height: 3.2rem;
}
建议将mixin放入单独文件夹下,例如webpack中的common,之后使用只需要在style中引入,以scss为例:
@import "../common/scss/mixin.scss";
.all {
@include px2rem(padding, 32);
}
- flexible插件
此处案例属于vue项目中引用
- 安装
npm i lib-flexible --save
2.引入lib-flexible
在main.js中引入lib-flexible:
import 'lib-flexible'
- 使用px2rem-loader自动将css中的px转换成rem
- 安装px2rem-loader:
npm install px2rem-loader --save-dev
- 配置px2rem-loader:
(1)打开build/utils.js文件,找到exports.cssLoaders方法,在里面添加如下代码:
const px2remLoader = {
loader: 'px2rem-loader',
options: {
remUint: 75, //设计稿宽度/10, 以设计稿750为例, 750 / 10 = 75
}
}
(2)打开build/utils.js文件,找到generateLoaders方法, 添加px2remLoader 插件:
function generateLoaders (loader, loaderOptions) {
const loaders = options.usePostCSS ? [cssLoader, postcssLoader, px2remLoader] : [cssLoader, px2remLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
//...
(3)build/utils.js文件 添加 generateSassResourceLoader方法:
function generateSassResourceLoader () {
const loaders = [
cssLoader,
px2remLoader,
'less-loader'
]
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
(4)修改 build/utils.js文件 return
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateSassResourceLoader() // 修改less的值
}
- 如果是大屏需要修改flexible源码
打开./node_modules/lib-flexible/flexible.js,找到如下片段源码:
function refreshRem(){
var width = docEl.getBoundingClientRect().width;
if (width / dpr > 540) {
width = width * dpr;
}
var rem = width / 10;
docEl.style.fontSize = rem + 'px';
flexible.rem = win.rem = rem;
}
- 重启,完成
修改完成后,重启项目,则会适配到相应的尺寸。此外还有一个提示,当脱离掉node_modules重新npm install项目依赖时还是需要重新修改一遍的,千万别忘了! - 为解决重新安装依赖需要再次配置,按以下方法:
先把flexible.js源码文件拷贝到项目下,然后修改改文件,此处提到了src文件下,然后需要修改main.js里的引入路劲:
import './flexible'
此处在提出的文件如出现eslint报错问题,可在文件顶部加上/* eslint-disable */即可。
- 问题1:1px的边框也会帮你转成rem。
//对于有些地方不用转换的我们可以在样式后面添加/*no*/这样就不会给我们转化了;
.box{
width:200px;
height:200px;
border-radius: 50%;
border:1px solid red;/*no*/
}
在px后面添加/no/,不会转化px,会原样输出。 — 一般border需用这个
在px后面添加/px/,会根据dpr的不同,生成三套代码。—- 一般字体需用这个
- 使用px2rem配合scss时,/px/、/no/失效:
(1)可以把px写成大写PX,这样px2rem也不会转换,同时大写在浏览器上也是生效的。
(2)使用普通css写,也可以生效。
但是使用px2rem-loader修改build/utils.js文件之后会影响css样式中的背景图片的加载,为解决该问题选择卸载px2rem-loader,使用postcss-pxtorem。
postcss-pxtorem是PostCSS的插件,用于将像素单元生成rem单位。
- 安装
npm install postcss-pxtorem --save-dev
- 配置
可以通过3个地方来添加配置,配置文件皆位于vue 项目根目录中,若文件不存在可以自行建立。 - 权重
vue.config.js > .postcssrx.js > postcss.config.js
其中 postcssrc.js 和 postcss.config.js 可以热更新, vue.config.js 中做的修改要重启devServer。 - 属性
rootValue (Number)
根元素的值,即1rem的值
用于设计稿元素尺寸/rootValue
比如 rootValue = 192 时,设计稿是1920*1080比例,在css中width: 960px; 最终会换算成width: 5rem;
还有一些其他的配置:
propList (Array) 需要做单位转化的属性.
必须精确匹配
用 * 来选择所有属性. Example: ['']
在句首和句尾使用 * (['position'] 会匹配 background-position-y)
使用 ! 来配置不匹配的属性. Example: ['', '!letter-spacing']
组合使用. Example: ['', '!font']
minPixelValue(Number) 可以被替换的最小像素.
unitPrecision(Number) rem单位的小数位数上限.
- 配置示例
vue.config.js
module.exports = {
//...其他配置
css: {
loaderOptions: {
postcss: {
plugins: [
require('postcss-pxtorem')({
rootValue: 192,
minPixelValue: 2,
propList: ['*'],
})
]
}
}
},
}
.postcssrc.js
module.exports = {
plugins: {
'postcss-pxtorem': {
rootValue: 16,
minPixelValue: 2,
propList: ['*'],
}
}
}
postcss.config.js
module.exports = {
plugins: {
'postcss-pxtorem': {
rootValue: 192,
minPixelValue: 2,
propList: ['*'],
}
}
}
这样配合flexible即可实现px转rem的适配。
如果不适用flexible,则新建rem.js文件,于main.js中引用。
// 设计稿以1920px为宽度,而我把页面宽度设计为10rem的情况下
const baseSize = 192; // 这个是设计稿中1rem的大小,此处要和postcss-pxtorem配置中的rootValue一致。
function setRem() {
// 实际设备页面宽度和设计稿的比值
const scale = document.documentElement.clientWidth / 1920 || document.body.clientWidth / 1920;
// 计算实际的rem值并赋予给html的font-size
document.documentElement.style.fontSize = (baseSize * scale) + 'px';
}
setRem();
window.addEventListener('resize', () => {
setRem();
});
网友评论