如何在SVG精灵符号中引用内部渐变定义?

时间:2014-07-17 14:54:24

标签: css svg gradient

摘要: SVG精灵包含五个图标<symbol>块,其中一个块通过ID引用自己的渐变定义。它不再能够找到这个渐变并正确渲染。

JSFIDDLE: http://jsfiddle.net/Qtq24/1/


我正在将一些图形转换为SVG,并且它们是图标(在这种情况下是社交网络配置文件)我希望将它们保存在精灵中(就像之前我使用过PNG一样)。

我已关注this guide to SVG sprites on CSS-tricks.com(以及this follow-up which advises using <symbol> instead of <g>)。

我现在有一个SVG精灵文件, social-sprite.svg ,您可以完整查看here

这是一个完整的<svg>块,其中包含五个不同的<symbol>块,每个块都带有idviewBox属性。在每种情况下,我都通过在Adobe Illustrator中准备官方图标并保留已处理代码的相关部分来获取每个符号的SVG代码。

只要<body>标记打开,就会通过PHP包含.svg文件(这就是为什么其中的主<svg>容器标有style="display: none;")以便引用每个符号都来自HTML。

四个图标完美运行,我唯一遇到问题的是YouTube图标,因为它使用内部定义的渐变。以下是SVG代码的YouTube部分:

<symbol id="youtube" viewBox="0 0 400 281.641">
    <path id="Triangle" fill="#FFFFFF" d="M159.845,191.73l106.152-54.999L159.845,81.348V191.73z"/>
    <path id="The_Sharpness" opacity="0.12" fill-rule="evenodd" clip-rule="evenodd" fill="#420000" d="M159.845,81.348l93.091,62.162
    l13.061-6.778L159.845,81.348z"/>
    <g id="Lozenge">
        <g>
            <linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="200.4204" y1="2.6162" x2="200.4204" y2="278.9292">
                <stop  offset="0" style="stop-color:#E52D27"/>
                <stop  offset="1" style="stop-color:#BF171D"/>
            </linearGradient>
            <path fill="url(#SVGID_1_)" d="M392.928,62.226c0,0-3.839-27.073-15.617-38.995C362.371,7.583,345.626,7.506,337.947,6.59
            c-54.975-3.974-137.441-3.974-137.441-3.974h-0.171c0,0-82.464,0-137.44,3.974c-7.68,0.916-24.419,0.993-39.364,16.641
            C11.753,35.153,7.92,62.226,7.92,62.226s-3.929,31.792-3.929,63.583v29.805c0,31.791,3.929,63.582,3.929,63.582
            s3.833,27.073,15.611,38.995c14.945,15.646,34.575,15.152,43.318,16.792c31.43,3.015,133.571,3.946,133.571,3.946
            s82.552-0.124,137.526-4.099c7.679-0.915,24.424-0.993,39.363-16.64c11.778-11.922,15.617-38.995,15.617-38.995
            s3.923-31.791,3.923-63.582v-29.805C396.851,94.017,392.928,62.226,392.928,62.226z M159.863,191.73l-0.018-110.383
            l106.152,55.384L159.863,191.73z"/>
        </g>
    </g>
</symbol>

这在HTML中调用:

<svg width="30" height="21">
    <use xlink:href="#youtube" src="fallback.png" width="30" height="21" />
</svg>

开放的两条路径运行正常,问题是在这个新的组合精灵SVG文件中,每个图标分隔为<symbol>&#34; Lozenge&#34; <path>无法找到<linearGradient>#SVGID_1 _ 引用。

在Firefox中,这会导致菱形显示为白色(我想,也许它根本没有显示 - 没有真正调查过它):

firefox fills as white

虽然Chrome将其呈现为黑色:

chrome fills as black

显然两者都不可接受。我目前唯一可以做的就是删除路径上的fill="url(#SVGID_1_)",然后填充适合YouTube徽标的平面红色。这不是一个合适的解决方案,甚至可以忽略这样一个事实,即以这种方式滥用YouTube徽标不会被他们的品牌指导所接受。

我尝试过的事情(并且没有运气):

  • 删除围绕渐变和路径的两个<g>包装器,因此整个符号只是<path>-<path>-<linearGradient>-<path>
  • 将渐变定义包装在<defs>容器
  • 将其包装在<defs>中并将其移至SVG文件的顶部,即在YouTube特定的<symbol>
  • 范围之外
  • 更改ID名称(你永远不知道!)
  • 使用百分比而不是像素值重新定义渐变

那么如何让内部<symbol>引用内部<linearGradient>定义?


编辑:当整个<svg>块标有style="display: none;"时,结果显示渐变失败。如果删除此样式,则渐变呈现正确。但作为提醒,添加了这种样式,以便在导入SVG精灵时,它不会立即在页面上呈现,只允许您根据需要引用id定义的符号。

visibility: hiddenopacity: 0都允许渐变正确渲染,显然它们不提供正确的解决方案,因为它们仍然划分了SVG在可见时占用的空间。 / p>

在发现所有这些之后,我非常确定完全可见<svg>没有添加任何样式 INSIDE 隐藏的容器<div>是没有问题的。但是,即使这样也会导致渐变不呈现。我没有更接近解决这个问题。

2 个答案:

答案 0 :(得分:28)

首先请注意我的问题的编辑 - 然后我发现使用display: none隐藏SVG符号直到我们需要它是问题。

我一直在摆弄这个&#34;回答&#34;,这远非完美,但对任何这种情况仍应可靠。

您需要做的就是将整个<svg>代码包装在<div>容器中,必须显示但不会影响布局,所以我只是通过大型过度杀戮CSS完成此操作,例如:

height: 0; width: 0; position: absolute; visibility: hidden;

这很有效。看到最后的小提琴:http://jsfiddle.net/Qtq24/5/

如果有人有更好的解决方案,我很乐意听到它,因为这感觉有点像一种hacky方式,但我想不管怎么说都不要使用display: none;。< / p>

答案 1 :(得分:5)

你有两个问题:

不要使用style =“display:none;”在SVG。您在根<svg>元素上拥有它。可见性:隐藏,高度/宽度=“0”或<defs>是更好的选择。

Firefox中存在一个错误,如果渐变元素位于符号内部,则它们不起作用。解决方法非常简单,只需将linearGradient移动到符号之外,使其看起来像这样......

<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="200.4204" y1="2.6162" x2="200.4204" y2="278.9292">
    <stop  offset="0" style="stop-color:#E52D27"/>
    <stop  offset="1" style="stop-color:#BF171D"/>
</linearGradient>
<symbol id="youtube" viewBox="0 0 400 281.641">
    <path id="Triangle" fill="#FFFFFF" d="M159.845,191.73l106.152-54.999L159.845,81.348V191.73z"/>
    <path id="The_Sharpness" opacity="0.12" fill-rule="evenodd" clip-rule="evenodd" fill="#420000" d="M159.845,81.348l93.091,62.162
    l13.061-6.778L159.845,81.348z"/>
    <g id="Lozenge">
        <g>
            <path fill="url(#SVGID_1_)" d="M392.928,62.226c0,0-3.839-27.073-15.617-38.995C362.371,7.583,345.626,7.506,337.947,6.59
            c-54.975-3.974-137.441-3.974-137.441-3.974h-0.171c0,0-82.464,0-137.44,3.974c-7.68,0.916-24.419,0.993-39.364,16.641
            C11.753,35.153,7.92,62.226,7.92,62.226s-3.929,31.792-3.929,63.583v29.805c0,31.791,3.929,63.582,3.929,63.582
            s3.833,27.073,15.611,38.995c14.945,15.646,34.575,15.152,43.318,16.792c31.43,3.015,133.571,3.946,133.571,3.946
            s82.552-0.124,137.526-4.099c7.679-0.915,24.424-0.993,39.363-16.64c11.778-11.922,15.617-38.995,15.617-38.995
            s3.923-31.791,3.923-63.582v-29.805C396.851,94.017,392.928,62.226,392.928,62.226z M159.863,191.73l-0.018-110.383
            l106.152,55.384L159.863,191.73z"/>
        </g>
    </g>
</symbol>