自适应解决方案适用pc端以及移动端,适用webpack以及vite,适用vue以及react
前提 又再次回到广告行业,发现已经是天翻地覆了 哎 怀疑自己老了,以前rem方案再也不合适了 使用vw ,在此记录下
依赖
npm i postcss cssnano cssnano-preset-advanced postcss-aspect-ratio-mini postcs-preset-env postcss-import postcss-url postcss-px-to-viewport postcss-viewport-units postcss-write-svg -D
npm i viewport-units-buggyfill -S
"postcss": "^8.4.18", // postcss扮演一个框架的角色,是一个用javaScript工具和插件转换css代码的工具。postcss将css转换为javaScript可以操作的数据结构。这些数据可以由插件理解和转换,然后处理成各种需要的格式。其本身不对css进行处理,但是通过在该平台上集成插件,如cssnano、postcss-px-to-viewport等,就可以实现对css的处理和操作
"postcss-preset-env": "^7.8.2", // 是一个postcss插件,帮助您使用最新的css语法,它将新的css规范转换为更兼容的css,所以你不需要等待浏览器的支持。(之前同功能的postcss-cssnext插件被废弃, 推荐用postcss-preset-env)
"cssnano": "^5.1.13", // cssnano是构建于postcss的插件和生态之上的,主要用来压缩和清理css代码,确保最终生成的文件 对生产环境来说体积是最小的
"cssnano-preset-advanced": "^5.3.8", // cssnano的高级优化
"postcss-aspect-ratio-mini": "^1.1.0", // 主要用来处理元素容器的固定宽高比
"postcss-import": "^15.0.0", // 主要功有是解决@import引入路径问题。使用这个插件,可以让你很轻易的使用本地文件、node_modules或者web_modules的文件。这个插件配合postcss-url让你引入文件变得更轻松
"postcss-url": "^10.1.3", // 该插件主要用来处理文件,比如图片文件、字体文件等引用路径的处理。
"postcss-px-to-viewport": "^1.1.1", // 自适应的关键所在,将px单位转换为视口单位的 (vw, vh, vmin, vmax) 的postcss插件.如果你的样式需要做根据视口大小来调整宽度,这个脚本可以将你css中的px单位转化为vw,1vw等于1/100视口宽度。
"postcss-viewport-units": "^0.1.6", // 插件主要是给css的属性添加content的属性,配合viewport-units-buggyfill库兼容一些不支持 vw、vh、vmax、vmin 这些 viewport 单位的浏览器所使用的。
"viewport-units-buggyfill": "^0.6.2", // 配合postcss-viewport-units兼容一些不支持 vw、vh、vmax、vmin 这些 viewport 单位的浏览器
"postcss-write-svg": "^3.0.1", // 这个库可以让你直接在css中写svg,也是处理移动端1px的解决方案,该插件主要使用的是border-image和background来做1px的相关处理
1.postcss: postcss扮演一个框架的角色,是一个用javaScript工具和插件转换css代码的工具。postcss将css转换为javaScript可以操作的数据结构。这些数据可以由插件理解和转换,然后处理成各种需要的格式。其本身不对css进行处理,但是通过在该平台上集成插件,如cssnano、postcss-px-to-viewport等,就可以实现对css的处理和操作
2.postcss-preset-env: 是一个postcss插件,帮助您使用最新的css语法,它将新的css规范转换为更兼容的css,所以你不需要等待浏览器的支持。(之前同功能的postcss-cssnext插件被废弃, 推荐用postcss-preset-env)
3.cssnano: cssnano是构建于postcss的插件和生态之上的,主要用来压缩和清理css代码,确保最终生成的文件 对生产环境来说体积是最小的
注意:
- 我们需要使用cssnano-preset-advanced让cssnano的特性支持最新的css特性,所以我们需要配置cssnano的预设,即cssnano-preset-advanced
- 由于cssnano-preset-advanced和cssnano都具有autoprefixer,事实上只需要一个即可,避免重复处理,所以把cssnano中的autoprefixer设置为false。
- z-index会被cssnano重新计算为1,这个巨坑,会导致之后设置z-index出现各种问题,所以需要禁用cssnano的zindex
cssnano({ // cssnano 是构建于 postcss 的插件和生态之上的,主要用来压缩和清理CSS代码,确保最终生成的文件对生产环境来说体积是最小的
preset: [
cssnanoPresetAdvanced, // cssnano-preset-advanced是cssnano的高级优化
{
autoprefixer: false, // 由于cssnano-preset-advanced和cssnano都具有autoprefixer,事实上只需要一个即可,避免重复处理,所以把cssnano中的autoprefixer设置为false。
zindex: false // z-index会被cssnano重新计算为1,这个巨坑,会导致之后设置z-index出现各种问题,所以需要禁用cssnano的zindex
}
],
})
cssnano-preset-advanced: cssnano的高级优化postcss-aspect-ratio-mini: 主要用来处理元素容器的固定宽高比
<div>
<div className={styles.exampleItemTitle}>使用postcss-aspect-ratio-mini处理元素的尺寸固定为纵横比(宽高比)</div>
<div className={styles.postcssAspectRatioMiniExample}>
<img src={aaa} alt="" />
</div>
</div>
.postcssAspectRatioMiniExample {
width: 188px;
height: 188px;
border: 1px solid #000;
position: relative;
aspect-ratio: 1/1; /*使用postcss-aspect-ratio-mini来处理元素容器的固定宽高比。加上它有神奇的力量*/
}
.postcssAspectRatioMiniExample img {
max-width:100%;
max-height:100%;
border: 1px solid #000;
/*aspect-ratio: 16/9;*/
}
6.postcss-import: 主要功有是解决@import引入路径问题。使用这个插件,可以让你很轻易的使用本地文件、node_modules或者web_modules的文件。这个插件配合postcss-url让你引入文件变得更轻松
7.postcss-url: 该插件主要用来处理文件,比如图片文件、字体文件等引用路径的处理。
8.postcss-px-to-viewport: 自适应的关键所在,将px单位转换为视口单位的 (vw, vh, vmin, vmax) 的postcss插件.如果你的样式需要做根据视口大小来调整宽度,这个脚本可以将你css中的px单位转化为vw,1vw等于1/100视口宽度。
常用配置如下:
postcssPxToViewport({ // 实现px自动转vw实现自适应的关键插件,可以将px单位转换为视口单位的 (vw, vh, vmin, vmax)
viewportWidth: 1920, // 视口宽度,对应UI设计稿的视窗宽度
viewporHeight: 1080, // 视口高度,对应UI设计稿的视窗高度
unitToConvert: 'px', // 需要转换的单位,默认为"px"
viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认vw
fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw
unitPrecision: 6, // 指定px转换之后的精度,即小数点位数
selectorBlackList: ['.ignore', '.hairlines'], // 需要忽略的 CSS 选择器,不会转为视窗单位,使用原有的 px 等单位
exclude: [/node_modules/], // 忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件
// include: /\/src\//, // 如果设置了include,那将只有匹配到的文件才会被转换 (exclude和include设置一个就行了)
replace: true, // 是否转换后直接更换属性值,而不添加备用属性
minPixelValue: 1, // 设置最小的转换数值,默认值1,小于或等于1px则不进行转换
mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false
propList: ['*'], // 指定能转化为 vw 的css属性列表,*代表全部css属性的单位都进行转换
// propList: ['*', '!font-size'],
landscape: false, // 是否根据 landscapeWidth 生成的媒体查询条件,处理横屏情况
// landscapeUnit: 'vw', // 横屏时使用的单位
// landscapeWidth: 1125, // 横屏时使用的视窗宽度
}),
9.postcss-viewport-units: 插件主要是给css的属性添加content的属性,配合viewport-units-buggyfill库兼容一些不支持 vw、vh、vmax、vmin 这些 viewport 单位的浏览器所使用的。
ps:需要注意的是: 当有元素的伪类使用了content的时候,会出现如下报错:
xxx::before already has a ‘content’ property, give up to overwrite it,这时候我们就需要配置一下postcss-viewport-units的过滤规则,让其忽略伪类,不对伪类添加content属性
postcssViewportUnits({
filterRule: rule => rule.selector.includes('::after') && rule.selector.includes('::before') && rule.selector.includes(':after') && rule.selector.includes(':before'), // 解决有伪类使用content报错 already has a ‘content’ property, give up to overwrite it.
}),
10.viewport-units-buggyfill: 配合postcss-viewport-units兼容一些不支持 vw、vh、vmax、vmin 这些 viewport 单位的浏览器
var hacks = require('viewport-units-buggyfill/viewport-units-buggyfill.hacks');
require('viewport-units-buggyfill').init({
hacks: hacks
});
viewport-units-buggyfill的兼容问题: 使用了viewport-units-buggyfill后,它会占用content属性,因此会或多或少的造成一些副作用。如img元素和伪元素的使用::before 或::after。 对于img,在部分浏览器中,content的写入会造成图片无法正常展示,这时候需要全局添加样式覆盖:
/* 解决使用了viewport-units-buggyfill的img兼容问题 */
img {
content: normal !important;
}
11.postcss-write-svg: 这个库可以让你直接在css中写svg,也是处理移动端1px的解决方案,该插件主要使用的是border-image和background来做1px的相关处理
利用postcss-write-svg实现css中写1px直线的svg示例如下
/*1px示例*/
/*使用postcss-write-svg绘制1px(仅限直线)*/
@svg square {
height: 1px;
@rect {
fill: var(--color, white);
width: 100%;
height: 50%;
}
}
/*background的形式*/
.onePxLineByPostcssWriteSvgExample {
width: 100%;
height: 20px;
background: white svg(square param(--color red));
background-size: 100% 1px;
background-repeat: no-repeat;
background-position: bottom left;
}
/*border-image的形式*/
/*
.onePxLineByPostcssWriteSvgExample {
width: 100%;
height: 20px;
border-bottom: 1px solid transparent;
border-image: svg(square param(--color $navbar-border-color)) 2 2 stretch;
}
*/
12.autoprefixer: 是用来自动处理浏览器前缀的一个插件。如果你配置了postcss-cssnext或者postcss-preset-env,其中就已具备了autoprefixer的功能,不需要再额外安装。在配置的时候,未显示的配置相关参数的话,表示使用的是Browserslist指定的列表参数,你也可以项目根目录创建.browserslistrc文件来指定last 2 versions 或者 > 5%,如下:
.browserslistrc
> 1%
last 2 versions
如此一来,你在编码时不再需要考虑任何浏览器前缀的问题,可以专心撸码。这也是postcss最常用的一个插件之一。
备注:
实现自适应最主要的功能实际只需要postcss、postcss-px-to-viewport,其他依赖只是锦上添花或者是为了解决兼容问题,可根据自身情况选择是否安装 本文主要介绍配置自适应所需要的插件,其他插件如处理less的less和less-loader等插件,自行研究和下载
vw实现自适应的优缺点 优点: 不需要 js 做适配 方案灵活技能实现整体缩放又能实现局部不缩放 缺点: 尺寸换算麻烦,不直观。 px 转换成 vw 不一定能完全整除,因此有一定的像素差; 当容器使用 vw,margin 采用 px 时,很容易造成整体宽度超过 100vw,从而影响布局效果。可以避免,例如使用 padding 代替 margin,结合 calc()函数使用等等…