Search code examples
htmlcsssvgscaling

How to scale/squish triangle symbol in SVG using `use`


I have the following system:

<html>
  <head>
    <style>
      html, body {
        margin: 0;
        padding: 0;
        overflow: hidden;
      }
    </style>
  </head>
  <body>
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3000 3000">
      <defs>
        <symbol id="triangle" viewBox="0 0 100 100">
          <polygon points="0,100 50,0 100,100" class="triangle" />
        </symbol>

        <symbol id="tree" viewBox="0 0 100 100">
          <use href="#triangle" width="100" height="100" />
        </symbol>
      </defs>

      <use href="#tree" width="200" height="400" x="1000" />
      <use href="#tree" width="100" height="100" x="1100" />
    </svg>
  </body>
</html>

For the following:

<use href="#tree" width="200" height="400" x="1000" />

I would expect it to be a triangle that's twice the height as the width (200x400). But it just ends up being a random size that is proportional to the original 100x100 triangle.

Wondering how to get this to scale/squish the image so I can use use in multiple times and have it show different height trees all with the same width.

Same with making a #rect symbol that you can size with any width/height and it creates an appropriately shaped rectangle. If I try the following it just shows a square.

    <symbol id="rect" viewBox="0 0 100 100">
      <rect width='100' height='100' />
    </symbol>

    <use href="#rect" width="400" height="300" x="1300" y="1000" />

Solution

  • Add preserveAspectRatio="none" to your symbol elements.

    <html>
      <head>
        <style>
          html, body {
            margin: 0;
            padding: 0;
            overflow: hidden;
          }
        </style>
      </head>
      <body>
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3000 3000">
          <defs>
            <symbol id="triangle" viewBox="0 0 100 100" preserveAspectRatio="none">
              <polygon points="0,100 50,0 100,100" class="triangle" />
            </symbol>
    
            <symbol id="tree" viewBox="0 0 100 100" preserveAspectRatio="none">
              <use href="#triangle" width="100" height="100" />
            </symbol>
            
            <symbol id="rect" viewBox="0 0 100 100" preserveAspectRatio="none">
              <rect width='100' height='100' />
            </symbol>
          </defs>
    
          <use href="#tree" width="200" height="400" x="1000" />
          <use href="#tree" width="100" height="100" x="1100" />
          <use href="#rect" width="400" height="300" x="1300" y="1000" />
        </svg>
      </body>
    </html>