text-transform
是一个可以将文字进行大小写转换或单词首字符大写的 CSS 属性。自从知道了它,我就开始偷懒不在 js 中去在调用相关的转换函数了。
昨天在给多说扩展用户 UA 功能时遇到一个 text-transform: capitalize
失效的问题,经过一番测试,找到了问题的原因。
场景还原
根据当时场景,抽取关键 css 属性:
|
现有如下的 HTML,你们猜最终会是什么结果?
|
结果:
|
问题DEMO链接:text-transform: capitalize 失效demo
问题解析
通过运行结果可以发现全小写单词组合时,转换没有任何问题,略过。
大写单词组合
全大写单词组合,转换失效?真的是这样吗?
通过查阅相关文档,关于 capitalize
的介绍为:将每个单词的第一个字母转换成大写。
看来是我们对它期望太高了,text-transform: capitalize
并不能像 lodash
库中的转换函数那样,将全大写的的 AAA
转换成你期望的 Aaa
。
含有伪元素
这也是我面临到的问题,每个 UA 标签上的 tootip 都是我用伪类模拟的。
由于当时伪元素是绝对定位的,在视觉上真的是当作了另外的元素看待。
而在问题 DEMO 中,我们还原了伪元素默认显示的位置::before
就是在原始内容前追加内容,:after
就是在原始内容后追加内容。
由于最后生成的内容之间没有间隙,导致 text-transform
转换时将其当作一个单词。
为了验证我的结论,我在含有伪元素的内容前或后加了个空格:
|
最后转换成功:
|
解决方案
虽然找到了问题的原因,但是实际场景中使用伪元素的初衷就是要将一个元素当作多个元素使用,HTML 中加空格会有半个中文字符宽度的空白,也就等于产生了不必要的边距。
做到这里真是感觉不如直接写个 js 转换函数算了。
|
写出来后忽然发现这段代码完全可以用 CSS 去“实现”。
|
上个月旭哥博客有篇很详细的 :first-letter
介绍:张鑫旭:深入CSS :first-letter伪元素及其实例等
其中提到了 :first-letter
和 :before
之间的猫腻,就是说 :first-letter
也生效于 :before
伪元素。
不过我测试后发现,当 :before
伪元素设置为绝对定位时,:first-letter
将只作用于原始内容。
利用这个机制,总算可以给自己一个完美的答复了。
|
- 附加内容在
:before
时,使用:first-letter
+uppercase
解决,如果原始内容有大写,需要再给原标签加lowercase
; - 附加内容在
:after
时,给:after
再加capitalize
。