ceving
ceving

Reputation: 23824

How to reuse an embedded SVG element in the same page?

I have a simple HTML5 page with an embedded SVG icon element.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=">
  </head>
  <body>
    <h1>
      <span>ABC</span>
      <svg id="move-icon"
           width="0.7em" height="0.7em"
           viewBox="0 0 10 10"
           style="display: inline-block">
        <defs>
          <marker id="arrow-end-marker"
                  viewBox="0 0 10 10" refX="0" refY="5"
                  markerHeight="3"
                  orient="auto">
            <polygon points="0 0 10 5 0 10" />
	  </marker>
        </defs>
        <line x1="5" y1="5" x2="5" y2="7"
              stroke="black" stroke-width="0.03em"
              marker-end="url(#arrow-end-marker)" />
        <line x1="5" y1="5" x2="3" y2="5"
              stroke="black" stroke-width="0.03em"
              marker-end="url(#arrow-end-marker)" />
        <line x1="5" y1="5" x2="5" y2="3"
              stroke="black" stroke-width="0.03em"
              marker-end="url(#arrow-end-marker)" />
        <line x1="5" y1="5" x2="7" y2="5"
              stroke="black" stroke-width="0.03em"
              marker-end="url(#arrow-end-marker)" />
      </svg>
    </h1>
    <p>abc</p>
    <h2>
      <span>DEF</span>
      <!-- reuse here -->&#10067;
    </h2>
    <p>def</p>
  </body>
</html>

Now I want to reuse the embedded SVG icon in the second headline. How can this be done?

Upvotes: 22

Views: 17471

Answers (3)

milahu
milahu

Reputation: 3549

symbol + use + href="#symbol-id"

to define a symbol once, and use it in other svg documents

<!-- define symbol in hidden svg document -->
<svg style="display: none" version="2.0">
  <defs>
    <symbol id="circle-arrow-left" viewbox="0 -10 100 110">
      <path d="m 20 80 A 40 40 0 1 0 20 20"
        fill="none" stroke="#000" stroke-width="10" />
      <path d="M 10 0 v 40 h 40"
        fill="#000" />
    </symbol>
  </defs>
  <!-- to make the circle-arrow-left.svg file
       also usable as image: -->
  <use href="#circle-arrow-left"/>
</svg>

<!-- use symbol of external svg document -->
<button>
  <svg width="50" height="50" version="2.0">
    <use href="#circle-arrow-left" />
  </svg>
</button>

<!-- transform symbol with horizontal flip -->
<button>
  <svg style="transform: scale(-1, 1)" width="50" height="50" version="2.0">
    <use href="#circle-arrow-left" />
  </svg>
</button>

change style: add the new style to where the symbol is used:

<svg style="fill: red"><use href="#s1"/></svg>

<svg class="some-class"><use href="#s2"/></svg>

inkscape does not yet support <svg version="2.0"> with <use href="#some-id"/>.
for svg version 1.1 we need <svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink"> and <use xlink:href="#some-id"/>

related:

https://css-tricks.com/svg-symbol-good-choice-icons/

https://css-tricks.com/svg-use-with-external-reference-take-2/

Upvotes: 69

ceving
ceving

Reputation: 23824

I have now a solution, but I have no idea, why this is working. It is possible to define a template, which can be cloned. But cloning means duplicating id attributes. And that means they are not unique any more. But referencing them in the marker-end seems to be still possible. It is a bit strange and I am not sure, if it is wise to follow this track.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=">
  </head>
  <body>
    <h1>
      <span class="movable">ABC</span>
    </h1>
    <p>abc</p>
    <h2>
      <span class="movable">DEF</span>
    </h2>
    <p>def</p>
    <template id="move-icon">
      <svg width="0.7em" height="0.7em"
           viewBox="0 0 10 10"
           style="display: inline-block; vertical-align: baseline">
        <defs>
          <marker id="arrow-end-marker"
                  viewBox="0 0 10 10" refX="0" refY="5"
                  markerHeight="3"
                  orient="auto">
            <polygon points="0 0 10 5 0 10" />
	  </marker>
        </defs>
        <line x1="5" y1="5" x2="5" y2="7"
              stroke="black" stroke-width="0.03em"
              marker-end="url(#arrow-end-marker)" />
        <line x1="5" y1="5" x2="3" y2="5"
              stroke="black" stroke-width="0.03em"
              marker-end="url(#arrow-end-marker)" />
        <line x1="5" y1="5" x2="5" y2="3"
              stroke="black" stroke-width="0.03em"
              marker-end="url(#arrow-end-marker)" />
        <line x1="5" y1="5" x2="7" y2="5"
              stroke="black" stroke-width="0.03em"
              marker-end="url(#arrow-end-marker)" />
      </svg>
    </template>
    <script>
      (function() {
         var icon = document.querySelector('#move-icon');
         var spans = document.querySelectorAll('span.movable');
         for (var i = 0; i < spans.length; i += 1)
           spans[i].parentNode.appendChild (icon.content.cloneNode(true));
       })();
    </script>
  </body>
</html>

Upvotes: 0

aitnasser
aitnasser

Reputation: 1246

you can save the SVG to a file and use it directly in an < img > tag.like this

<img src="toto.svg" alt="toto description">

Upvotes: 1

Related Questions