首页 > 解决方案 > 使用 ::first-letter 将字符串中的第一个字母大写。漏洞?

问题描述

我最近在尝试找到一种通用的前端方法来将字符串中的第一个字母大写时偶然发现了这种奇怪的行为。通常,我会称之为退出,但我一直在努力寻找解决方案。但是,就在那时我遇到了这种奇怪的行为。

片段:

.capitalizeWord::first-letter {
  text-transform: uppercase;
}
<!-- example 1 -->
<p class="capitalizeWord">
  <span>
    <i></i>
  test1></span>hello
</p>

<!-- example 2 -->
<p class="capitalizeWord">
  <span style="float:left;"> <!--float causes it to work -->
    <i></i>
  test2></span>hello
</p>

根据caniuse ::first-letter chrome 支持这一点。

所以,我的第一个问题是:是什么导致了这种行为? This has been "somewhat" answered in the comments

我最初的想法是编译器将<i>-tags 解释为字符。但是不,当它们被删除时,这个问题仍然很普遍。其他人可以验证他们正在经历相同的结果吗?如果您的浏览器没有看到我的图片,请发布图片以供参考:

在此处输入图像描述

无论如何,我的第二个问题:有没有一种前端的方式来完成test2but withtest1结构的结果?

题外话,但仍然与回答我的第一个问题有关。见下文

更新:

在评论中进行了一些讨论之后,问题已经缩小到关于<i>-tag 的问题。

但是,我仍然会将其归类为错误。原因如下:

<i></i> 不应该触发::first-letter。就像,这应该是不言而喻的,只需查看selector的名称。

为什么::first-letter由非字母字符(在这种情况下为EMPTYhtml-标记)触发,然后在 EMPTY 中没有找到任何内容时停止在该范围内查找标签,这不是根元素(p / div)范围结束的地方......就像,为什么yyyyyyyyy?

我可以通过这样做来破坏整个选择器:

.box::first-letter {
  text-transform: uppercase;
}
<div class="box">
  some text
  <!-- wooohoo, works! -->
</div>

<div class="box">
  <i></i>some text
  <!-- doesn't work now... I broke it, without adding ANY characters/letters to the dom -->
</div>

<span class="box">
   some text 
<!-- doesn't work now... I broke it again, just changed to a span-tag -->
</span>

<span class="box" style="display:block;">
   some text 
<!-- wooohoo, works! -->
</span>

也许这是我的固执,但是,我真的很讨厌他们对这个选择器采取的这种方法。它确实可以用作在 Web 上大写字符串的“必经之路”,而不是必须在其位置创建所有这些 javascript 变通方法。

标签: htmlcss

解决方案


您要问两个具体的不同问题,所以我将同时回答它们。

我的问题是:是什么导致了这种行为?

回答您的问题:当您浮动元素时,它会从文档流中取出,并且不再算作关于伪元素选择器的块内容的一部分。来自 CSS 视觉格式规范:

如果一个元素是浮动的、绝对定位的或者是根元素,那么它就被称为 out of flow。

视觉格式化模型 - W3

所以按照规范,如果我们使用不同的方法将元素从流中取出,我们可以看到完全相同的结果,例如绝对定位:

.capitalizeWord::first-letter {
  text-transform: uppercase;
}
<!-- example 1 -->
<p class="capitalizeWord">
  <span>
    <i></i>
  test1></span>hello
</p>

<!-- example 2 -->
<p class="capitalizeWord">
  <span style="float:left;"> <!-- float causes it to work -->
    <i></i>
  test2></span>hello
</p>

<!-- example 3 -->
<p class="capitalizeWord">
  <span style="position: absolute; left: 50px"> <!-- absolute positioning causes it to work -->
    <i></i>
  test3></span>hello
</p>

有没有一种前端方法可以完成 test2 的结果但使用 test1 的结构?

据我所知,在纯 CSS 中没有办法做到这一点,因为您必须将有问题的元素从流程中取出,以让选择器找到所需的伪元素。通过将元素从流程中取出,您的元素将不再具有相同的视觉层次结构。

我仍然会将其归类为错误

该行为遵循规范,因此它不是错误。您可能会争辩说这是一个糟糕的设计选择。


推荐阅读