SVG symbol not showing gradient - html

How to probably display a linear gradient in HTML from a SVG <symbol>? I tried the following but somehow this only works in FireFox (version 63). In chrome and safari it didn't load the gradient. What am I doing wrong is this a bug or is there a "work around" for this?
W3 validation shows no errors for the following code:
<!DOCTYPE html>
<html>
<head>
<title>Gradient Problem</title>
<meta charset="UTF-8" />
</head>
<body style="margin:0;overflow:hidden">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="0" height="0" style="display:block">
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#AE1C28" />
<stop offset="30%" style="stop-color:#AE1C28" />
<stop offset="40%" style="stop-color:#FFFFFF" />
<stop offset="60%" style="stop-color:#FFFFFF" />
<stop offset="70%" style="stop-color:#21468B" />
<stop offset="100%" style="stop-color:#21468B" />
</linearGradient>
</defs>
<symbol id="logo" viewbox="0 0 100 100" preserveAspectRatio="none">
<rect width="100%" height="100%" x="0" y="0" fill="url(#grad1)" />
</symbol>
</svg>
<svg style="width:100vw;height:100vh">
<use xlink:href="#logo"></use>
</svg>
</body>
</html>
Have a look at this example where I try to deal with all use cases of including a svg symbol via <use>.
Update:
Hmm weird seems like it works in chrome when the SVG is in the HTML. However when the file is in a external file (as shown in the codesandbox example) then the gradients won't show. I guess it is an issue with <use>?

Related

Cannot display linear gradient as a background image on a html page

<svg version="1.1" xmlns="http://w3.org/2000/svg">
<title> Background </title>
<text>
<LinearGradient id="g" x1="200%" x2="0%" y1="50%" y2="0%">
<stop style = "stop-color: green;" offset="0"/>
<stop style = "stop-color: white;" offset="1"/>
</LinearGradient>
</text>
<rect style = "fill: url(#g);" width = "100%" height = "100%"/>
</svg>
The output of this code is either broken image, or the Title "Background" and I do not see what's wrong with it.
You've two issues which affect standalone SVG only
the SVG namespace is incorrect so the file is not recognised as an SVG file. You're missing www from the namespace.
standalone SVG files are case sensitive so we need to write linearGradient
And this one is a bug even when you embed SVG in html.
you can't make a linearGradient the child of a <text> tag. We can use <defs> instead. In theory we could omit the <defs> tag, although I think Safari isn't keen on that.
which leaves us with this...
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<title> Background </title>
<defs>
<linearGradient id="g" x1="200%" x2="0%" y1="50%" y2="0%">
<stop style = "stop-color: green;" offset="0"/>
<stop style = "stop-color: white;" offset="1"/>
</linearGradient>
</defs>
<rect style = "fill: url(#g);" width = "100%" height = "100%"/>
</svg>
You should use defs for the gradient. You may also consider viewbox and width/height:
<svg version="1.1" xmlns="http://w3.org/2000/svg" viewBox="0 0 200 100" width="200">
<title> Background </title>
<defs>
<LinearGradient id="g" x1="200%" x2="0%" y1="50%" y2="0%">
<stop style = "stop-color: green;" offset="0"/>
<stop style = "stop-color: white;" offset="1"/>
</LinearGradient>
</defs>
<rect fill="url(#g)" x="0" y="0" width="200" height="100" />
</svg>

Can you define multiple definitions inside a single defs tag in SVG?

Is it OK to use multiple definitions inside a single def tag at the root of the document?
Example. Notice all of the gradients inside the defs tag.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<svg width="0" height="0">
<defs>
<linearGradient id="Gradient01">
<stop offset="20%" stop-color="#39F" />
<stop offset="90%" stop-color="#F3F" />
</linearGradient>
<linearGradient id="Gradient02">
<stop offset="00%" stop-color="#3F3" />
<stop offset="50%" stop-color="#39F" />
<stop offset="90%" stop-color="#F55" />
</linearGradient>
</defs>
</svg>
<svg width="800px" height="300px"
xmlns="http://www.w3.org/2000/svg">
<rect x="10" y="10" width="200" height="20"
fill="url(#Gradient01)" />
<svg width="380px" height="330px"
xmlns="http://www.w3.org/2000/svg">
<rect x="10" y="50" width="200" height="20"
fill="url(#Gradient02)" />
</svg>
</svg>
</body>
</html>
There is no def tag. There is a defs tag. This should be a hint :)
But for a formal answer, look how defs is defined:
Content model: Any number of the following elements, in any order: ...

SVG use and gradients as fill

I've been trying to externalize my SVG icons to a file and referencing them with markup like <svg><use xlink:href="file.svg#icon" /></svg>. In theory this works really nicely, but different browsers have issues with rendering. All the browsers are able to render the svg correctly when referencing the symbol with <use> inside the file and opening the svg file's url directly.
In short, is there a cross-browser way to get SVG linearGradients working as fills for elements when referencing the symbols with <svg><use/></svg> in the markup?
I set up a plunker demonstrating the problem:
http://plnkr.co/edit/feKvZ7?p=preview
Simplified, the markup is like the following:
<!DOCTYPE html>
<html>
<body>
<h1>SVG sprite test</h1>
<svg width="100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<use xlink:href="icon.svg#icon" />
</svg>
</body>
</html>
And the SVG file looks like this:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="gradient">
<stop offset="0" stop-color="black" />
<stop offset="1" stop-color="white" />
</linearGradient>
</defs>
<symbol id="icon" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" stroke="black" fill="url(#gradient)" />
</symbol>
<use id="iconuse" xlink:href="#icon" width="100" height="100" />
</svg>
This is what it looks like in the different browsers:
The symbol tag is used to hide the elements that are inside it. Elements inside the symbol are called using the <use> command by their unique indicator.
Therefore, it is better to use this method of calling individual elements rather than calling the whole symbol
In addition, elements when using <use> fall into the shadow DOM and using CSS in some cases becomes impossible
Therefore, it is better to delete all internal styles inside symbol and assign them directly to the use command
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="gradient">
<stop offset="0" stop-color="black" />
<stop offset="1" stop-color="white" />
</linearGradient>
</defs>
<symbol id="icon" viewBox="0 0 100 100">
<circle id="circle" cx="50" cy="50" r="40" />
<rect id="rect" x="100" y="10" width="100" height="100" />
</symbol>
<use class="iconuse" xlink:href="#circle" width="100" height="100" fill="url(#gradient)" stroke="black" />
<use class="iconuse" xlink:href="#rect" width="100" height="100" fill="url(#gradient)" />
</svg>
Try next one (it's how Inkscape provide implementation of gradients):
<linearGradient id="gradient">
<stop
style="stop-color:black;"
offset="0"/>
<stop
style="stop-color:white;"
offset="1" />
</linearGradient>
...
<path
style="fill:url(#gradient); ...

Applying SVG effects to HTML content

I am trying to follow this tutorial to add an SVG mask to my HTML div element:
https://developer.mozilla.org/en-US/docs/Web/SVG/Applying_SVG_effects_to_HTML_content
Here's the relevant code:
<!DOCTYPE HTML>
<html>
<body>
<svg height="0">
<mask id="mask_1">
<linearGradient id="grad_1" x1="0" x2="0" y1="0" y2="1">
<stop offset="0.0" stop-color="white" stop-opacity="0.0" />
<stop offset="1.0" stop-color="white" stop-opacity="1.0" />
</linearGradient>
<rect x="0" y="0" width="72" height="72" fill="url(#grad_1)"/>
</mask>
</svg>
<div style="left:0px;top:0px;width:68px;height:68px;background-color:#ff0000;background-size:auto;mask:url(#mask_1);">Here's some text.</div>
</body>
</html>
The mask is not working however. The div elements are being rendered properly, minus the mask that is supposed to make them fade toward the top. Am I missing something obvious? Does this method only work in XHTML versus HTML 5? Thanks.

How to Inline SVG?

I'm trying to add inline SVG to an HTML file, but it doesn't show anything, while it's fine if separate. Why?
<html>
<head></head>
<body>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16px" height="16px">
<defs>
<linearGradient id="lg1">
<stop style="stop-color:#ffffff;stop-opacity:0.50;" offset="0"/>
<stop style="stop-color:#00ff00;stop-opacity:0.75;" offset="1"/>
</linearGradient>
<linearGradient xlink:href="#lg1" id="lg2"
x1="0" y1="0" x2="16" y2="0" gradientUnits="userSpaceOnUse" />
</defs>
<g>
<rect style="fill:url(#lg2);fill-opacity:1" id="rect3001"
width="48" height="48" x="0" y="0" />
</g>
</svg>
</body>
</html>
Add <!DOCTYPE html> - looks like IE9 requires it, but FF and Chrome didn't.
Alternately, use XHTML.
<html xmlns="http://www.w3.org/1999/xhtml">