html如何解决1px显示,移动端1px问题解决方案

Document

// webpack.config.jsconst path = require('path')const HtmlPlugin = require('html-webpack-plugin')module.exports = {mode: 'development',entry: {entry1: './src/index.js'},output: {path: path.resolve(__dirname, 'dist'),filename: '[name].js'},module: {rules: [{test: /.css$/,use: ['style-loader', 'css-loader', 'postcss-loader']}]},plugins: [new HtmlPlugin({template: './src/index.html'})],devServer: {contentBase: path.resolve(__dirname, 'dist'),host: '0.0.0.0',port: 3005,compress: true,disableHostCheck: true}}

SVG

分别直接用xml的svg标签和css实现了两个100px,边框宽为1的矩形。

高清屏下效果如下。

7ba0818e00ebad79c7a0a7d2375f5ea1.png

1598073606858

width="100"height="100"fill="transparent"stroke-width="1"stroke="black"/>

stroke-width 和 border 一样,都将矩形的边设为了1px,但是用svg实现的矩形边框看起来却更细。 关键的地方是使用svg标记的 视口大小和使用rect标记的 矩形大小是 相同的。

svg中没有盒模型的概念,它的 stroke画线并 不是对应css中的border。 更像是不占空间的outline。因为不占空间,它会以rect(矩形)的边界为 中心画线,一条线一半宽度在矩形内,一半在矩形外。

而因为视口宽度正好等于矩形的大小,看到的线宽就只有一半了。

12bb11a786bb9b40f88cbfa0ce612362.png

(用 svg画一个100px大小+1px边宽的方形)

2f436f65bb920bc9d590a5730b528dab.png

(用css画一个100px大小+1px边框的方形 border-box)

如果把矩形缩小一点,不占满视口,这时候看到的border是完整的,所以和没处理过的1px一样粗。

f35505d1249c2ee2e7061612838fdd81.png

border-image

border-image是三个属性的缩写

border-image-source: url('https://misc.aotu.io/leeenx/border-image/box.png');border-image-slice: 33% 20% 3 fill;border-image-repeat: stretch;

border-image-source:图片链接或base64;

border-image-slice:图片切割的四个位置。把图片切成9块,除中间一块,其他八块分别被当成边框使用。接受1-4个参数(使用类似于padding/margin的尺寸设置)。可以是百分比(相对于图片自身),也可以是数字(单位是px)。最后的fill决定中间那块图片会不会被当成background使用。

border-image-repeat:stretch/round(平铺)/repeat(重复)上下左右四个正位的图片怎样被当成border使用。

round(平铺)会压缩,repeat(重复)会剪裁。

border-image必须配合border使用。最终 border宽度是border-width。 border-style也必须指定,border-color可以不用。

伪类元素方案

907e966ea358244a00b0709c0a8a2b12.png

完整代码

// index.html

retina border
normal border

// index.css.retina-border {position: relative;}.retina-border::before {content: '';position: absolute;width: 100%;height: 100%;transform-origin: left top;box-sizing: border-box;pointer-events: none;border-width: 1px;border-style: solid;border-color: #333;}@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx) { .retina-border::before {width: 200%;height: 200%;transform: scale(0.5);}}@media (-webkit-min-device-pixel-ratio: 3), (min-resolution: 3dppx) { .retina-border::before {width: 300%;height: 300%;transform: scale(0.33);}}.normal-border {border: 1px solid #333;}

具体实现

以两倍屏为例

.retina-border {position: relative;}.retina-border::before {content: '';position: absolute;top: 0px;right: 0px;width: 200%;height: 200%;transform: scale(0.5);transform-origin: left top;box-sizing: border-box;pointer-events: none;border-width: 1px;border-style: solid;border-color: #333;}

通过一个伪类选择器在retinaborder元素中加了一个子元素

48533290578fb1be471c792bb64b6569.png

border-width: 1px 将边框的宽度设为1px。

width:200% 然后将 伪类元素的宽高都设置成父元素的2倍。( 但是边框还是1px)

transform:scale(0.5) 将 伪类元素的x,y轴方向都缩放到0.5倍。

通过两次尺寸的设置,使这个伪类子元素保持内容的大小还是和父元素一样,但是 border:0.5px 的效果。

pointer-events: none 当有元素的层级重叠时,鼠标点击是无法穿透的。即绝对定位的伪类元素的层级更高,它底下的元素(即文字:retina border)无法被事件触发。置为none时, 绝对定位的元素不触发事件,底下的那层才能被选中。

其他css样式作用

伪类元素默认的 display:inline 。而 position:absolute 会使元素 display:block 。只有块级元素的尺寸(宽/高)设置才是有效的。

其中伪类选择器中 content 是必填项,不然无法生效

transform-origin的缩放的中心点,默认是元素中心,

transform-origin的缩放的中心点,默认是元素中心,和绝对定位的top,right一样,相对的是padding+content部分整个空间的位置

绝对定位的元素其top和right值是相对于padding+content的,默认值是从content开始,所以要规定都是0,否则当父元素有padding时,border就移位了

5698b0fd805425d2670c8e8369efeeb0.png

(如果删去position:absolute)

2818af2d2d3b2d567fd7228f1cd6b701.png

(如果删去position:absolute+display:block)

当使用百分比时,其父元素的高度必须显式指定,(20px/20view)不能是由子元素撑开的,但是宽度是可以的。两种方案比较 兼容性

svg方案经过postcss处理,最终会影响浏览器兼容性的是 border-image属性

6537ab5113de7f9c558037942415ca66.png

伪类元素元素:方案最终影响兼容性的是 transform属性

7cbe445a22029860bb757177882aa567.png

1598076296220

结论:svg方案的兼容性更好。

灵活性

由于svg只能画出特定的形状,所以无法实现圆角边框。而伪类元素方案可以。

学习成本

svg方案所用到的border-image属性、svg特性的理解成本较高,并且需要postcss-write-svg处理。伪类元素方案相较简单。

总结

通常情况,伪类元素方案更好,无论是从成本还是灵活性出发。如果是为了更高的兼容性选择svg方案,border-image属性一定要使用缩写。(不然兼容性会更差兼容性测试)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值