针对iphone X等刘海屏,需要写多个padding-top属性,大致如下:
.body {
padding-top: 44px;
padding-top: calc(~'44px + env(safe-area-inset-top)');
padding-top: calc(~'44px + constant(safe-area-inset-top)');
padding-bottom: 0;
padding-bottom: env(safe-area-inset-bottom);
padding-bottom: constant(safe-area-inset-bottom);
}
本地开发没有啥问题,然而项目经过build之后,发现样式变成了:
.body {
padding-top: calc(~'44px + constant(safe-area-inset-top)');
padding-bottom: constant(safe-area-inset-bottom);
}
同名属性莫名被吃了??? 于是开始坎坷的解决之路。
- 先搜索相关问题,问题其实都不知道出现在哪,于是搜索也没有结论。绝望
- 然后再问别人看看是否有类似问题。没有人遇到过。绝望 + 1
- 开始分析打包配置,然后修改打包入口文件,指向一个最简单的Demo,就只包含上述这些样式。
- 分步注释打包对CSS的配置,排除变量。
- 最终发现是
optimize-css-assets-webpack-plugin
中引入一个cssnano
这样一个包,里面又包含了mergeLonghand
这种一个功能模块,会将 padding/margin等属性的子属性(padding-top、padding-bottom)尝试合并为一个。然而不知道为何没有合并,反而将同名的padding-top、padding-bottom属性吃了几个。
知道原因后,解决方案也很简单,修改webpack的配置:
...
optimization: {
moduleIds: 'hashed',
minimizer:[
new OptimizeCSSPlugin({
cssProcessorPluginOptions: {
preset: ['default', { mergeLonghand: false }] // 不使用 mergeLonghand 这个功能
}
}),
new UglifyJsPlugin({
cache: true,
parallel: true
})
]
}
再次打包就不会出现 padding-top 属性被吃的情况了。
解决过程中陷入了一个僵局,因为使用mini-css-extract-plugin
这个插件,如果不使用,也就是css in js这种方式时,就不会出现被吃情况,故误以为是这个插件的问题,看了好半天源码,发现没那个地方存在这种可能性。。故回过头继续看配置文件。