nmu
nmu

Reputation: 1519

What is the correct way of <use>ing an svg?

I'm very confused about the <svg> spec as it relates to the <use> tag because everything I've read about it online seems to implement the tag with subtle differences.

On css-tricks the <svg> is added with a viewBox in the <symbol>:

<svg style="display: none;">
  <defs>
    <symbol id="basketball" viewBox="0 0 100 100">
      <title>Basketball</title>
      <path d="M28.1,3 ... "/>
    </symbol>
  </defs>
</svg> 

and then the <symbol> is plainly referenced just with the id:

<svg class="icon-basketball">
  <use xlink:href="#basketball"></use>
</svg>

The same is true for this article and even more so in this article by Chris Coyier, where he explicitly points out that <symbol> is a better tag because you don't need a viewBox when referencing it.

However, referencing a symbol with a viewBox does not work for me, and I end up with the same error as in this SO question, which concludes that you do, in fact, need the viewBox when referencing a <symbol>. This article even proposes a hack for dealing with 'intrinsic svg sizing'.

Indeed, in this short jsfiddle/snippet, you can see that with a single <symbol>, if I add the viewbox into the <svg> reference it is sized correctly, without any whitespace. Yet, with the viewbox removed, there are large 'margins' at the top and bottom.

<link href="https://unpkg.com/[email protected]/css/tachyons.min.css" rel="stylesheet"/>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><symbol viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-zap" id="zap"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" /></symbol></defs></svg>

<div class="tc">


	<!-- svg is always oversized -->
	<svg class="outline w3 bg-red">
		<use xlink:href="#zap"></use>
	</svg>
	
	<!-- svg is the correct size -->
	<svg class="outline w3 bg-green"  viewBox="0 0 24 24">
		<use class="black" xlink:href="#zap"></use>
	</svg>
	

		
</div>

So what am I getting wrong about <use> is it the way I am defining the <symbol>, which currently is being generated through svg-sprite on webpack. Or has there been a recent change in the way <svg>s are externally referenced?

Thanks!

Upvotes: 3

Views: 294

Answers (1)

Alexandr_TT
Alexandr_TT

Reputation: 14545

In the article you refer to, Chris Coyier used symbol to store icons in the sprite.

Each symbol in the sprite can have its ownviewBox, with individual parameter values, which allows you to additionally scale and position each icon individually.

<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">

  <symbol id="beaker" viewBox="214.7 0 182.6 792">
    <!-- <path>s and whatever other shapes in here -->  
  </symbol>

  <symbol id="shape-icon-2" viewBox="0 26 100 48">
    <!-- <path>s and whatever other shapes in here -->  
  </symbol>

</svg>          

In your case, when using the <use>, as Robert Longson wrote:

in one instance it has size information, in the other it does not.

In the nested svg, there is also an additional scaling.
Therefore, if you want both clones to be the same size, add a svg viewBox to the second instance with the same parameters viewBox =" 0 0 24 24 "

<link href="https://unpkg.com/[email protected]/css/tachyons.min.css" rel="stylesheet"/>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><symbol viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-zap" id="zap"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" /></symbol></defs></svg>

<div class="tc">


	<!-- svg is the correct size -->
	<svg class="outline w3 bg-red" viewBox="0 0 24 24">
		<use xlink:href="#zap"></use>
	</svg>
	
	<!-- svg is the correct size -->
	<svg class="outline w3 bg-green"  viewBox="0 0 24 24">
		<use class="black" xlink:href="#zap"></use>
	</svg>
	

		
</div>

Upvotes: 3

Related Questions