CSS content: attr() 在 HTML5 进度条上不起作用

22

HTML

<progress max="100" value="80" data-value="5"></progress>

CSS

progress { margin: 50px; width:250px; border:0; }

CSS(尝试一)

progress:before, progress:after { content: attr(data-value); }

CSS(尝试2)

progress::-webkit-progress-bar:before,
progress::-webkit-progress-bar:after { content: attr(data-value); }

progress::-moz-progress-bar:before,
progress::-moz-progress-bar:after { content: attr(data-value); }

CSS(第三次尝试)

progress::-webkit-progress-value:before,
progress::-webkit-progress-value:after { content: attr(data-value); }

progress::-moz-progress-value:before,
progress::-moz-progress-value:after { content: attr(data-value); }

以上所有尝试均未成功。还尝试了使用不同的CSS代码块,用于:before:after

目标

在HTML5的<progress>元素之前和之后注入CSS生成内容。这可能吗?

JsFiddle演示

http://jsfiddle.net/pankajparashar/MNL2C/

更新

当我使用以下CSS时,它可以工作。

progress::-webkit-progress-bar:before,
progress::-webkit-progress-bar:after { content: '123'; }    

结论

显然,当我们在 CSS 中注入静态内容时,它可以正常工作。但是如果我们使用 data-* 中的内容,则无法正常工作。


4
如果浏览器已经能够绘制进度条,类似于objectiframe元素内的内容,progress元素中的内容将不会被显示,因此我认为这是不可能的。 - BoltClock
3
@Pankaj Parashar: 是的,我们是。我们正在谈论在 progress 元素内部和外部生成的内容。 - BoltClock
3
我对你的观点持有不同意见。因为当我们将这个 content:attr(data-value); 改成 content: '213'; ,它就可以工作了!所以问题出在使用CSS属性中的attr函数。 - Pankaj Parashar
1
这不是与IMG标签类似的问题吗(关于:before:after)? - frozenkoi
3
进一步阅读后,进度元素不遵循空的内容模型。它使用短语内容模型,因此理论上应该可以用文本来完成这个操作。对我来说,这仍然似乎是一个奇怪的用例,但你应该向Mozilla和Chromium提交一个错误报告。 - Kerry Liu
显示剩余18条评论
3个回答

10
在我的原始评论中,我说:
我认为这是不可能的,因为进度元素内的内容如果浏览器已经绘制了进度条,则永远不会显示,类似于对象或iframe中的内容。
换句话说,这将progress归类为replaced element。就像传统的input和其他表单元素一样,它们都是替换元素,以及img一样,CSS2.1对使用生成的内容没有太多要说:
注意。本规范未完全定义:before和:after与替换元素(如HTML中的IMG)的交互。这将在将来的规范中详细定义。

众所周知,基于Gecko的浏览器选择不支持替换元素的生成内容,而基于WebKit的浏览器在某种程度上允许它,至少对于被替换的表单元素。 (有趣的是,在任何浏览器中都无法使用progress::beforeprogress::after。) 因此,如果你想知道是否可能跨浏览器实现这一点,答案是否定的,并且一直都是这样。


关于为什么WebKit浏览器可以插入字符串而不是attr()值,我不确定。CSS2.1CSS3 Units and Values都指出attr()应该从生成伪元素的实际元素的属性中获取值,因为伪元素本身无法拥有属性。这就是我困惑的地方。
也许浏览器错误地尝试从::-webkit-progress-bar::-webkit-progress-valuedata-value属性中获取值,而不是progress元素,这就是为什么使用attr()content失败但使用字符串时却成功的原因。
也许问题的根源在于您试图将生成的内容添加到其他伪元素中,这似乎在WebKit浏览器中出现了奇怪的原因。与替换元素中的生成内容上述问题不同,当前的Selectors 3规范和即将发布的Selectors 4规范都非常明确:每个复杂选择器中不应有多个伪元素。当然,WebKit在实现伪元素时一直以来都违反了各种规则,所以事后看到WebKit搞砸了并不让我感到惊讶。

无论如何,真正的结论是,CSS生成的内容的实现超出了当前CSS2.1 +选择器标准的范围,我的意思是用于替换元素(如inputprogress)的生成内容以及单个选择器中的伪元素嵌套。


1
我觉得我开始看到你不喜欢WebKit的原因的轮廓了。虽然我怀疑要完整解释这个问题可能需要写一篇相当长的博客文章。 - David Thomas
1
@David Thomas:我一直想再写博客。我真的应该尽快处理那个着陆页面。但你说得对:我通常不会写关于为什么我不喜欢WebKit的原因,我很高兴这次终于做到了。 - BoltClock
或者,你知道的那个Twitter东西...顺便说一句,宣泄情绪通常是一件好事,而且值得,即使只是某些情况下,让别人看到推理也是如此。话虽如此,虽然我喜欢Chrome,但我也开始对WebKit对标准的“解释”感到厌倦了。但还不足以让我切换回Firefox或转移到Opera(尤其是因为他们决定采用WebKit)。 - David Thomas
原始的小提琴确实可以在 Safari 6.0.5(8536.30.1)上工作。http://i.imgur.com/s2GpLk5.png,但添加内容会完全破坏[chrome](http://i.imgur.com/ZcGUmnC.png)进度元素的渲染。再想一想,你是对的。允许这种行为应该是错误的。即使进度元素被允许具有文本子元素,除非元素不受支持,否则它们的子元素不应该可见,类似于 canvas 或 iframe 元素。 - Kerry Liu
@KerryLiu,你说得对,Safari确实使用CSS生成的内容显示::before::after伪元素,但@BoltClock所提出的观点也足够有效。 - Pankaj Parashar
我接受这个答案的原因是,@BoltClock说得非常好,即data-valueprogress元素上而不是伪元素::-webkit-progress-value上,这可能是未显示内容的原因。最初我认为这是一个错误,但在您的回复后意识到我做错了! - Pankaj Parashar

2
<progress></progress>

它不接受文本,你需要调整你的CSS。

HTML:

<progress max="100" value="80" data-value="80"></progress>
<span class="percentage">80% Done</span>

CSS:

progress { margin: 0px; width:250px; border:0; }

/* CSS (Attempt 1) */

    progress:before, progress:after { content: attr(data-value); }

/* CSS (Attempt 2) */

    progress::-webkit-progress-bar:before,
    progress::-webkit-progress-bar:after { content: attr(data-value); }

    progress::-moz-progress-bar:before,
    progress::-moz-progress-bar:after { content: attr(data-value); }

/* CSS (Attempt 3) */

    progress::-webkit-progress-value:before,
    progress::-webkit-progress-value:after { content: attr(data-value); }
    progress::-moz-progress-value:before,
    progress::-moz-progress-value:after { content: attr(data-value); }

    .percentage{
        float: left;
        margin-left:100px;
        margin-top: -20px;
        position: absolute;
        display: block;
        color: #FFF;
    }

1
谢谢你的回答,但你真的没有理解我的问题!问题是关于如何使用伪元素生成CSS内容,但你的回答以嘲笑我的尝试作为结束 :) - Pankaj Parashar

0

看起来@BoltClock是正确的 - content: attr(value)正在寻找-webkit-progress-value的阴影DOM元素上的value属性,而不是实际的<progress>元素:

h4 { margin: 2em 0 0; }
progress {
  -webkit-appearance: none;
  appearance: none;
  position: relative;
}
progress::-webkit-progress-value:before {
  position: absolute;
  right: 0;
  bottom: -125%;
}
progress.show-value::-webkit-progress-value:before {
  content: attr(value);
}
progress.show-data-value::-webkit-progress-value:before {
  content: attr(data-value);
}
progress.show-style::-webkit-progress-value:before {
  content: attr(style);
}
progress.show-pseudo::-webkit-progress-value:before {
  content: attr(pseudo);
}
<h4><code>attr(value)</code>:</h4>
<progress class="show-value" max="100" value="80" data-value="5"></progress>

<h4><code>attr(data-value)</code>:</h4>
<progress class="show-data-value" max="100" value="80" data-value="5"></progress>

<h4><code>attr(style)</code>:</h4>
<progress class="show-style" max="100" value="80" data-value="5"></progress>

<h4><code>attr(pseudo)</code></h4>
<progress class="show-pseudo" max="100" value="80" data-value="5"></progress>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接