【问题标题】:Is it possible to make Chrome return raw value of the CSS "content" property?是否可以让 Chrome 返回 CSS“内容”属性的原始值?
【发布时间】:2019-08-07 19:38:45
【问题描述】:

考虑以下 JavaScript、CSS 和 HTML 代码:

console.log(getComputedStyle(document.querySelector('p'), '::after').getPropertyValue('content'));
p::after {
    content: "Hello" attr(data-after);
}
<p data-after=" World"></p>

Firefox 和 IE11 都返回 CSS 中定义的原始值:"Hello" attr(data-after),这正是我所需要的。

但是 Chrome 会返回 "Hello World",解析后的值。

当我使用 Chrome DevTools 检查元素时,我可以看到它在“样式”面板中显示以下信息:

p::after {
    content: "Hello" attr(data-after);
}

所以看起来 Chrome 仍然有能力知道原始值。

是否有任何 JavaScript 解决方案可以让 Chrome 像 Firefox 和 IE11 一样返回 CSS 中定义的原始值?就算是 Chrome 独有的方法也可以,只要能在 JavaScript 中使用即可。


情况说明

针对某位会员提问的原因,情况如下:

我正在尝试在伪元素上为 CSS speak: never 创建一个“polyfill”。目前任何浏览器都不支持speak property

CSS 伪元素可以被屏幕阅读器读取,但目前无法轻松地从屏幕阅读器中隐藏它们。解决这个问题的常用方法是使用 HTML 代码,例如 <span aria-hidden="true">...</span>,而不是方便的 CSS 伪元素和 speak: never,在我看来,这种方法既不方便,也令人失望。

所以这个 polyfill 主要是关于 web 可访问性的。

这个 polyfill 的工作原理需要 CSS 开发人员编写一些额外的 CSS 代码作为指标,例如 attr(speak-never)

p::after {
    content: "please make me inaudible" attr(speak-never);
    }

然后在 JavaScript 中,polyfill 循环遍历页面上的每个元素,并检查其伪元素 ::before::after 的 CSS content 属性值是否包含 attr(speak-never)。如果找到该指标字符串,则 polyfill 修复伪元素(通过以编程方式添加自定义元素 <before aria-hidden="true">...</before><after aria-hidden="true">...</after>)。

现在的问题是 Chrome 无法在 JavaScript 中返回上述attr(speak-never)。虽然 polyfill 也可以通过要求 CSS 开发人员再添加一个指示器来工作,例如 Chrome 的 --speak: never,但 polyfill 最好让 CSS 开发人员的工作尽可能简单,并且不需要额外的 --speak: never 指示器。

这就是创建这个问题的原因。


更新

我决定改用counter-reset: speak-never 作为指示器,因为它可以被所有浏览器用 JavaScript 读取。

【问题讨论】:

    标签: javascript css google-chrome pseudo-element


    【解决方案1】:

    您可以通过document.styleSheets 查找规则。该属性促进了由多个规则组成的样式表列表,该规则由多个属性组成。然后,您可以遍历样式表和规则并从那里提取原始属性值。

    这是一种尊重在<style><link> 元素中直接定义的规则的基本方法:

    for (let sheet of document.styleSheets) {
        for (let rule of sheet.rules) {
            if (/:(before|after)$/.test(rule.selectorText)) {
                console.log(rule.style.content);
            }
        }
    }
    

    请注意@include-ed 样式表或@media-queries 不在此处处理。可以通过检查 rule.type 分别是 35 并遍历该规则的 styleSheet 属性来访问它们。请参阅list of types

    【讨论】:

    • 酷。我不知道可以使用选择器查找 CSS 规则。谢谢你。但是,我的情况是选择器是事先未知的。我已经详细解释了情况。
    • 您如何确定没有其他规则会覆盖该规则?例如p#some-id::after { content: "something else"; }
    • @Kaiido polyfill 不会那样做。相反,CSS 开发人员将对此负责。
    • @Kaiido,因为无论如何我们都必须测试所有规则,我们可以根据 RegExp 测试它们,而不是基本上匹配 /:(before|after)$/。我认为,从顺序和特异性我们也可以确定有效的规则。我将更改代码示例以使用匹配器。
    • @IanY。因为真正的 polyfill 允许在不支持它的环境中使用真正的语法。一旦他们支持它,你的 polyfill 就不再需要了。在这里,您的脚本正在使用一种解决方法来实现几乎相同的目标。但是由于你绑定的是不同的值,如果浏览器决定实现这个 speak 属性,你的用户将不得不更新他们的代码。
    【解决方案2】:

    不确定添加 attr(speak-never) 之类的内容是否比通过 HTML 标记更简洁...

    但是这个问题指向一个有趣的事情:Chrome 已经开始实现 CSSTypedom,我们应该能够使用它来找到原始值集,如 in this answer 所示。

    然而,为了定位伪元素,我们计划有一个PseudoElement interface,以及一个元素的扩展,这样我们就可以调用Element.pseudo(::type)来定位它的伪元素。但是这部分规范还没有被Chrome实现,所以目前Chrome中实际上没有办法访问伪元素的TypedValues。

    所以这留给我们自己解析样式表,以及使 w3c 开发真正 API 的所有注意事项:无法访问跨域样式表,无法直接知道规则是否在元素上处于活动状态,或者另一个更重要等等......

    【讨论】:

      猜你喜欢
      • 2022-12-17
      • 2022-12-20
      • 2011-05-29
      • 1970-01-01
      • 2010-12-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多