SVG:为啥外部 css 会覆盖文本的内联样式?

Posted

技术标签:

【中文标题】SVG:为啥外部 css 会覆盖文本的内联样式?【英文标题】:SVG: why does external css override inline style for text?SVG:为什么外部 css 会覆盖文本的内联样式? 【发布时间】:2014-08-09 05:46:36 【问题描述】:

我正在使用 SVG gradientFill 作为一种在 d3.js 图表中直观地“截断”长文本字符串的方法。

似乎用于填充的外部 css 样式将覆盖 SVG 中的内联渐变填充样式......总是这样吗?如何强制使用渐变填充?

在这个测试案例中,我在 svg defs 中定义了一个线性渐变,然后将渐变填充应用于两组文本。 http://jsfiddle.net/rolfsf/uX2kH/3/

var labelColWidth = 200;
var svg =  d3.select('#test').append('svg')
            .attr('width', 500)
            .attr('height', 500);

var defs = svg.append('svg:defs');

var textgradient = defs.append('svg:linearGradient')
            .attr('gradientUnits', 'userSpaceOnUse')
            .attr('x1', 0).attr('y1', 0).attr('x2', 40).attr('y2', 0)
            .attr('id', 'theGradient')
            .attr('gradientTransform',  'translate(' + (labelColWidth - 40) + ')');

    textgradient.append('svg:stop').attr('offset', '0%').attr('style', 'stop-color:rgb(0,0,0);stop-opacity:1')
    textgradient.append('svg:stop').attr('offset', '100%').attr('style', 'stop-color:rgb(0,0,0);stop-opacity:0');


var data = [[0, "xyzzy xyzzy"], [1, "xyzzy xyzzy xyzzy xyzzy xyzzy"], [2, "xyzzy xyzzy xyzzy xyzzy xyzzy xyzzy"], [3, "xyzzy xyzzy xyzzy"], [4, "xyzzy xyzzy"], [5, "xyzzy xyzzy xyzzy xyzzy xyzzy xyzzy xyzzy xyzzy xyzzy xyzzy"]];

var testGroup = svg.append('g')
    .attr('transform',  'translate(50, 100)');

var testGroup2 = svg.append('g')
    .attr('transform',  'translate(50, 250)')
    .attr('class', 'group2');

testGroup.selectAll('text').data(data)
  .enter().append('svg:text')
  .attr('fill', 'url(#theGradient)')
  .attr('x', 0)
  .attr('y', function(d, i)  return (i+1) * 20; )
  .text(function(d, i)  return d[1]; );

testGroup2.selectAll('text').data(data)
  .enter().append('svg:text')
  .attr('fill', 'url(#theGradient)')
  .attr('x', 0)
  .attr('y', function(d, i)  return (i+1) * 20; )
  .text(function(d, i)  return d[1]; );

然后在 CSS 中,我为 .group2 文本定义填充

.group2 text 
    fill: #000;

第一组有渐变填充,第二组没有。

内联样式不应该优先吗?

谢谢!

【问题讨论】:

【参考方案1】:

因为在 SVG 中,就像之前的 html 一样,样式胜过属性样式。

fill="red" 下面不是“内联样式”,style="fill:green"内联样式。

<svg  >
  <text x="50" y="50" fill="red" style="fill:green">This will be green</text>
</svg>

同样,如果您在外部定义了样式,它将获胜。

<style>
  text  fill: lime; 
</style>

<svg  >
  <text x="50" y="40" fill="red">This will be lime</text>
</svg>

【讨论】:

嗯...那么如何应用覆盖任何预定义文本填充的渐变填充? “这将是石灰”是红色的。 @user3624702 这是因为有人编辑了这个并搞砸了“运行代码 sn-p”,所以它没有包含 【参考方案2】:

来自SVG specification

对于支持 CSS 的用户代理,表示属性必须根据非 CSS 表示提示的优先级([CSS2],第 6.4.4 节)中描述的规则转换为相应的 CSS 样式规则,并额外说明表示属性在概念上被插入到新的作者样式表中,该样式表是作者样式表集合中的第一个。因此,表示属性将参与 CSS2 级联,就好像它们被放置在作者样式表开头的相应 CSS 样式规则所取代,特异性为零。一般来说,这意味着 表示属性的优先级低于作者样式表或“样式”属性中指定的其他 CSS 样式规则。

所以你可以使用内联样式而不是表示属性,例如

.attr('style', 'fill : url(#theGradient)')

【讨论】:

【参考方案3】:

在我的例子中,就像在 d3 链中用 style 替换 attr 一样简单:

.style('stroke', 'url(#gradient--min)')

【讨论】:

以上是关于SVG:为啥外部 css 会覆盖文本的内联样式?的主要内容,如果未能解决你的问题,请参考以下文章

CSS 的优先级机制[总结]

Webpack 从我的样式表中的内联 SVG 中去除标签,我不知道为啥

如何将带有css样式的内联SVG从浏览器保存/导出到图像文件

您如何使用 CSS 设置外部 svg 的样式

外部样式表中带有 fill:url(#id) 样式的 Firefox SVG,内联样式很好

对外部 SVG 文件使用 CSS 悬停?