【问题标题】:Is there a CSS workaround for Firefox' bug: inline-block + first-letter with changed size是否有针对 Firefox 错误的 CSS 解决方法:inline-block + first-letter with changed size
【发布时间】:2011-11-24 18:48:28
【问题描述】:

最好自己在 Firefox 中查看错误:http://jsfiddle.net/kizu/btdVd/

图片,显示错误:

还有错误filled in 2007 on bugzilla

当您将::first-letter 伪元素添加到display: inline-block,然后更改此first-letterfont-size 时,就会出现该错误。

第一个之后的单词中有更多字母:添加(或减去 - 如果字体大小小于块的)更多的额外空间。

float: left 添加到first-letter 会反转错误:字体大小越大,inline-block 的宽度就会缩小。

那么,问题是:有没有针对这个错误的纯 CSS 解决方法?有点想死我了。

【问题讨论】:

  • 这仍然是一个错误。我添加了另一个我认为更简单的解决方案,使用-moz-padding-end
  • 谢谢。我们今天遇到了这个确切的错误。

标签: css firefox


【解决方案1】:

我发现在整个页面(或任何有问题的块)上触发重排可以解决问题,因此我找到了一种方法,可以通过一次性 CSS 动画在每个此类块上触发它:http://jsfiddle.net/kizu/btdVd/23/

尽管如此,虽然此修复在渲染方面没有缺点,但它还有其他一些缺点:

  • 它仅适用于 Fx5+(支持动画);
  • 它仍然会在几毫秒内闪烁原始错误,所以它可能有点闪烁。

因此,这不是一个理想的解决方案,但在 Fx4- 过时时会有所帮助。当然,你可以用JS触发这样的修复onload,但不是那么好。

【讨论】:

  • 由于没有更好的答案,而且 Fx4- 有点旧,所以使用这里的动画是迄今为止最好的解决方案。
【解决方案2】:

我认为没有好的解决方案。

不过,我为你想出了一个不稳定的解决方案:

.test:first-letter {
    font-size: 2em;
    letter-spacing: -0.225em;
}

letter-spacing 样式添加到 Fiddle 中的 :first-letter 选择器中,您会发现块返回到大致正确的大小。

说明:

基本上,这个错误是由整个块的大小取自first-letter中指定的字体引起的。

我在这里对letter-spacing 所做的是尝试调整此字体的大小,而不影响其外观。在普通文本中以这种方式调整字母间距会导致字母在任一侧重叠 0.225 个字符宽度。

我最初希望 -0.25 的值就足够了——即每边四分之一个字符会将每个字符的宽度减少一半,这正是我们想要的,因为第一个字母是 @987654326 @,所以它是原来的两倍。

但是,计算并不像那样干净,因为字符串中的第一个和最后一个字符只会在一侧重叠,并且因为第一个字母实际上确实希望是双倍宽度,即使其他角色没有。

所有这一切意味着消除错误所需的确切 letter-spacing 值将根据文本的长度以及原始文本和第一个字母的字体大小而有所不同。这就是为什么我必须对字母间距的值进行一些试验以使其正常工作,同时也解释了为什么我无法完全适应 Fiddle 中的所有文本行。我需要为每个块设置一个稍微不同的值。

-0.225 的值似乎是我能得到的最接近的值,适用于您的所有示例,但实际上您需要对其进行调整以适合您的网站。

别忘了这是一个 Firefox 错误,因此您需要将其编写为某种特定于浏览器的 hack。并注意密切关注您链接的 Firefox 错误报告;当它确实得到修复时,您需要找到一种方法来为旧版本的用户保留您的 hack,但为已修复的用户删除它。

[编辑]

我想出的唯一其他可行的解决方案就是不使用触发错误的功能。即删除:first-letter 选择器,如果您想设置不同的样式,请使用单独的<span> 作为文本的第一个字母。

这确实是显而易见的答案,当然可以解决问题(也意味着您的样式首字母适用于旧版浏览器),但从语义角度来看并不理想,更重要的是不实际上回答了这个问题,这就是为什么我没有在我的原始答案中提供它作为解决方案。

我也一直在尝试寻找解决该错误的替代方法,但选项有限,而且我尝试过的任何方法都没有我最初的建议那样好的结果。

我尝试了使:first-letter 不可见的技巧,并使用:before 显示大写字母。但是,这对我不起作用。我没有在它上面逗留太久,所以你也许可以让它工作,但它有一个问题,你必须在 CSS 中定义前导字母,这并不理想。

另一种可能的解决方案是在:first-letter 上使用CSS font-stretch: condensed; 属性。这会将第一个字母的宽度减小回1em,从而解决其余文本的宽度问题。然而,这样做的不利方面是,首先它会使前导字母看起来被压扁,这可能不是您想要的,其次这种样式仅适用于支持 condensed 属性的字体。事实证明,标准字体不能很好地支持这一点,因此可能不适合您。

最后,原来的letter-spacing 解决方案仍然是我发现真正解决该错误的唯一方法。

【讨论】:

  • 投票赞成解释。很遗憾,但我需要一个更稳定的修复程序,它适用于短词和长词以及不同的第一个字符:似乎letter-spacing 必须不同,例如WI 字母。此外,负字母间距本身看起来并不好:(
  • 我知道它并不完美,但遗憾的是,这已经接近于我能够抵消该错误的影响了。我能给出的唯一其他解决方案是放弃尝试使用:first-letter 选择器,并将第一个字母拆分为自己的<span>。它不理想,不符合语义,并且实际上并没有解决错误,但它会为您的页面解决问题。
  • @kizu - 我添加了一些关于我尝试解决此问题的其他想法的注释。
  • 是的,第一个字母有额外块的那个是 100% 修复的,但这只是我想使用不常用的 :first-letter 并且不能的地方: (另外,我找到了另一种处理这个错误的方法:触发块上的回流。但是对于 Fx4- 没有 JS 是没用的。
  • 只是说,compressed 不存在。这是condensed
【解决方案3】:

此错误仍然存​​在,但某些修复程序不再起作用。即使在使用动画触发回流之后,内联块对我来说也恢复到相同的大小。我无法使用letter-spacing 技巧,因为我已经在第一个字母上使用了它,这就是导致我出现问题的原因。我通过将其添加到受影响选择器的 CSS 中解决了这个问题:

-moz-padding-end: *number of pixels to compensate*;

目前,moz-padding-end 似乎是 Firefox 特有的,它可以在 inline-block 的末尾添加或删除宽度。因为这是一个 Firefox 特有的错误,所以对我有用。

【讨论】:

    【解决方案4】:

    我知道这个帖子现在已经很老了,但显然这个错误还没有修复。

    使用animation 确实有效,但有一个明显的 FOUT(无样式文本闪烁)。我能够通过将first-letter 包装在span 中来解决这个问题。这确实解决了大小问题和 FOUT,它确实为标记添加了额外的元素,因此这取决于您的站点/应用程序的需求是否最合适。

    .test {
        background: rgba(0,0,0,0.15); /* For visualisation */
        display: inline-block;
    }
    
    .test:first-letter {
        font-size: 2em;
    }
    
    .test2:first-letter {
        float: left;
    }
    .test3:first-letter {
        font-size: .5em;
    }
    <h1>Inline-block with bigger first-letter</h1>
    
    <span class="test">Broken</span>
    <br><br>
    <span class="test"><span>F</span>ixed</span>
    
    
    <h1>+ floating to first-letter</h1>
    
    <span class="test test2">Broken</span>
    <br><br>
    <span class="test test2"><span>F</span>ixed</span>
     
    
    <h1>small size for first-letter</h1>
    
    <span class="test test3">Broken</span>
    <br><br>
    <span class="test test3"><span>F</span>ixed</span>
    
    <h1>small size, floating first-letter</h1>
    
    <span class="test test2 test3">Broken</span>
    <br><br>
    <span class="test test2 test3"><span>F</span>ixed</span>

    【讨论】:

    • 需要注意的是,将部分单词包含在 span 中会损害可访问性,例如,VoiceOver 会错误地读取此内容。有可能的解决方案在最近的最顶层元素上使用 aria-label 可以接受它,但是是的。
    猜你喜欢
    • 2011-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多