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

Mat*_*son 23 css svg gradient

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

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


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

在CSS-tricks.com上遵循了本指南中的SVG sprites(以及后续建议使用<symbol>而不是使用<g>).

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

这是一个<svg>包含五个不同<symbol>块的完整块,每个块都id带有一个viewBox属性.在每种情况下,我通过在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>
Run Code Online (Sandbox Code Playgroud)

这在HTML中调用:

<svg width="30" height="21">
    <use xlink:href="#youtube" src="fallback.png" width="30" height="21" />
</svg>
Run Code Online (Sandbox Code Playgroud)

开放的两个路径工作正常,问题是在这个新的组合精灵SVG文件中,每个图标分隔为a <symbol>,"Lozenge" <path>无法找到#SVGID_1_的引用<linearGradient>.

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

firefox填充为白色

而Chrome则呈现黑色:

铬填充为黑色

显然两者都不可接受.我现在唯一可以做的就是删除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: hidden或者opacity: 0两者都允许梯度正确渲染,显然它们没有提供适当的解决方案,因为它们仍然划分了SVG在可见时占用的空间.

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

Mat*_*son 29

首先请注意我的问题的编辑 - 我发现在display: none我们需要之前隐藏SVG符号是一个问题.

我一直在摆弄并解决这个"答案",这个答案远非完美,但对任何这种情况都应该是可靠的.

您需要做的就是将整个<svg>代码包装在一个必须显示但永远不会影响布局<div>容器中,所以我只是通过巨大的overkill CSS来完成这个,例如:

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

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

如果有人有一个更好的解决方案,我很乐意听到它,因为这感觉有点像一种hacky方式,但我想没有比display: none;不管怎么说都没有hacky .

  • 我真的很挣扎,谢谢你花时间回答你的问题! (2认同)
  • 先生,您是救世主 (2认同)

Rob*_*son 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>
Run Code Online (Sandbox Code Playgroud)