如何突破浏览器 12px 限制
目前 Chrome 浏览器依然没有放开12px
的限制,但 Chrome 仍然是使用人数最多的浏览器。
在笔者开发某个项目时突发奇想:如果实际需要11px
的字体大小怎么办?这在 Chrome 中是实现不了的。关于字体,一开始想到的就是 rem 等非 px 单位。但是rem
只是为了响应式适配,并不能突破这一限制。
em、rem 等单位只是为了不同分辨率下展示效果提出的换算单位,常见的库
px2rem
也只是利用了 js 将px
转为rem
。包括微信小程序提出的rpx
单位也是一样!
这条路走不通,就只剩下一个方法:改变视觉大小而非实际大小。
理论基础
css 中有一个属性:transform: scale();
值的绝对值>1,就是放大,比如 2,就是放大 2 倍
值的绝对值 0<值<1,就是缩小,比如 0.5,就是原来的 0.5 倍;
值的正负,负值表示图形翻转。
默认情况下,scale(x, y)
:以 x/y 轴进行缩放;如果 y 没有值,默认y==x
;也可以分开写:scaleX() scaleY() scaleZ(),分开写的时候,可以对 Z 轴进行缩放
第二种写法:transform: scale3d(x, y, z)
该写法是上面的方法的复合写法,结果和上面的一样。
但使用这个属性要注意一点:scale 缩放的时候是以“缩放元素所在空间的中心点”为基准的。所以如果用在改变元素视觉大小的场景下,一般还需要利用另一个元素来“恢复位置”:
语法上说,transform-origin
拥有三个属性值:
默认为:
属性值可以是百分比、em、px 等具体的值,也可以是 top、right、bottom、left 和 center 这样的关键词。作用就是更改一个元素变形的原点。
实际应用
可以明确说明的是,这样的 hack 需要明确规定缩放元素的height
值 !!!
上面代码中为什么.mmcce-valid-mj-period
类中要用max-height
?为什么对展开元素中的文字类.mmcce-text
中使用height
?我将类.mmcce-text
中的height
去掉后,看下效果:
(使用min-height
是一样的效果)
OK,可以看到,占高没有按我们想的“被缩放”。影响到了下面的元素位置。
本质上是“视觉大小改变了但实际(占位)大小无变化”。这时候,宽高实际也被缩放了的。这一点通过代码中
width:200%
也可以看出来。或者你设置了overflow:hidden;
也可以有相应的效果!
这一点需要注意,一般来说,给被缩放元素显式设置一个大于等于其font-size
的height
值即可。
缩放带来的其它问题
可能在很多人使用的场景中是不会考虑到这个问题的:被缩放元素限制高度以后如果元素换行那么会出现文字重叠的现象。
为此,我采用了在mounted
生命周期中获取父元素宽度,然后动态计算是否需要换行以及换行的行数,最后用动态 style 重新渲染每一条数据的height
值。这里有三点需要注意:
这里用的是一种取巧的方法:用
每个文字的视觉font-size值*字符串长度
。因为笔者遇到的场景不会出现问题所以可以这么用。在不确定场景中更推荐用 canvas 或 dom 实际计算每个字符的宽度再做判断(需要知道文字、字母和数字的宽度是不一样的);需要注意一些特殊机型的展示,比如三星的 galaxy fold,这玩意是个折叠屏,它的计算会和一般的屏幕计算的不一致;
在 vue 生命周期中,mounted 可以操作 dom,但不能获取实际 dom 元素;你可以通过
this.$el
获取元素。但要注意:在这个时期被获取的元素不能用v-if
(即:必须存在于虚拟 tree 中)。这也是上面代码中笔者使用v-show
和opacity
的原因。
关于第三点,这里有个时机问题。比如刚进入页面时要展示弹窗,弹窗是一个组件。那你在 index.vue 中是获取不到这个组件的。(这个和
v-if
还是v-show
没有关系)但是你可以将比如 header 也拆分出来,然后在 header 组件的 mounted 中去调用弹窗组件暴露出的方法。
版权声明: 本文为 InfoQ 作者【云小梦】的原创文章。
原文链接:【http://xie.infoq.cn/article/4b92fd681ad68207147e81971】。文章转载请联系作者。
评论