场景
上个版本中,H5有个需求,是在某个模块的底部,居中展示提示,类似这种:
我一想居中展示,这不是很容易吗,直接写下居中的CSS:
.tip {
position: absolute;
left: 50%;
bottom: 20px;
transform: translateX(-50%);
max-width: 220px;
}
由于我们是有多语言的,所以加了个max-width
,有些语言翻译完之后通常比较长。
中文下没问题,此时文本还没有翻译好,并且水平居中的代码left:50%;transform: translateX(-50%)
公认的好用,自己也写过很多次了,没有问题,完美!
bug
测试阶段的某天,测试给我截了一张图:
看起来样式确实有一点点问题,感觉文本并没有很长,不应该折行。
第一反应是max-width
给小了,所以产生了折行。直接把max-width
改为300px
,这下应该够了吧...
结果是啪啪打脸,完全没变。
从图上可以看出来,居中确实居中了,但是这个宽度好像不大对,并没有超过我们所设置的max-width
,就出现了折行,难道是word-break
、word-wrap(overflow-wrap)
、white-space
之流的问题?
逮着这几个和折行有关的属性试了一通,还是不行。
我想到vant
中的toast
也是居中提示,就没有这种问题,然后去看了下是怎么写的:
.vant-popup--center {
position: fixed;
left: 0;
right: 0;
width: fit-content;
margin: 0 auto;
}
没有使用translate
这种,而是用的margin: 0 auto
(第一个学的居中就是它了吧,对于block
元素来说,这个是最简单的)。
原因
为啥使用left: 50%;transform: translateX(-50%)
会有问题呢,来看看DeepSeek是咋说的:
-
由于
left: 50%
让子元素的起始位置在父元素的中间,而translateX(-50%)
只是让子元素向左回退自身宽度的一半,因此:- 子元素的右边界不能超出父元素的右边界(否则会溢出)。
- 子元素的最大宽度不能超过父元素宽度的 50% ,否则
translateX(-50%)
会让部分内容超出父元素左侧。
看起来是在不设置具体宽度的情况下,浏览器为了防止子元素宽度超过父元素,一刀切50%。
其他方法
使用width: max-content
.tip {
position: absolute;
left: 50%;
transform: translateX(-50%);
width: max-content;
max-width: 220px;
}
使用flex
.parent {
display: flex;
justify-content: center;
}
.child {...}
这种就得多包一层,使用起来不咋方便。