Once we have what we are calling our “defs block” of SVG – that chunk of SVG that defines all the things we want to draw later – where do we put it? So far we’ve been putting it directly into the HTML, and that absolutely works. If we leave it at the top of the page, say just after the opening <body>
tag:
</head>
<body>
<!-- include svg defs here -->
That will work great in all browsers that support SVG.
It might be tempting to move this down. Perhaps the icons aren’t super vital to to page, not as vital as the real content that they page is meant to deliver, so we move the icons to the bottom of the page instead, deferring their loading like we often do with JavaScript. We try this in the video, but has problems with Safari rendering the icons we later tried to <use>
at all. To be honest, I’ve seen inconsistent behavior or various types in other browsers as well doing it this way, and it seems the landscape is shifting a bit in this regard. So I’ve heard: <use>
is a difficult thing to implement. Safest to put the block at the top if you end up keeping the defs right in your documents.
In this video we look at some basic testing of all this, and then look at some real-world websites that are using this system and how/where they insert the svg defs block.
See the Pen 954e71cb5d5e79fb61d3c89bb3f21b8a by Chris Coyier (@chriscoyier) on CodePen.
Note
I like the term “SVG defs block” – just so we can call it something that has a specific purpose but doesn’t really have an official name. But, you don’t always need to actually use a <defs>
tag. When you use <symbol>
s, those don’t render on their own anyway, and indeed I don’t think are supposed to be within <defs>
. I’ve heard definitions of gradients in SVG are the same, and won’t even work if they are in the <defs>
. Regardless, it’s still a “block of SVG code we’re just defining to use later” so I’ll likely keep calling it a “SVG defs block.”
Thanks a heap for these! It’s been super useful.
I’m hoping someone can point out where my bug is with this little problem I have.
I can’t resize one
<symbol>
from an external svg with CSS, but I can another<symbol>
from the same external svg.In the CSS I’m changing the
width
andheight
. Which#pluss
handles fine, whereas#heart
completely ignores it. It just wants to stay at 24px * 24px regardless of CSS sizing.I can’t tell what I’m doing differently. Headscratchingly confusing!
The external icons-defs.svg file:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="pluss" viewBox="0 0 24 24" aria-labeledby="title">
<title>Add</title>
<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</symbol>
<symbol id="heart" viewbox="0 0 24 24" aria-labeledby="title">
<title>Favourite</title>
<path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/>
</symbol>
</svg>
And in HTML:
<button>
<svg class="icon-heart" role="presentation">
<use xlink:href="icons-defs.svg#heart"></use>
</svg>
Like
</button>
<button>
<svg class="icon-pluss" role="presentation">
<use xlink:href="icons-defs.svg#pluss"></use>
</svg>
Add Goal
</button>
When having the same svg with symbols inline at top of the HTML document it works fine.
Any pointers would be much appreciated :)
Problem solved.
I’d written
viewbox
on#heart
. Which HTML5 accepts, but XML doesn’t. It has to beviewBox
(capital B).