Search code examples
htmlcsssvgalignment

Why does svg alignment change when parent div is < 14px in size?


I want the svg to be the same width/height as the parent div.

I've created a reduced test case below of a simple svg inside a div:

<div class="box">
  <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
       viewBox="0 0 50 50">
    <rect width="50" height="50"/>
  </svg>
</div>

Changing the parent width/height will change the size of the svg:

.box {
  width: 20px;
  height: 20px;
  background-color: red;
}

When the parent div width/height is less than 14px, the svg is no longer aligned inside the div. Why is this the case?


Solution

  • To understand the issue add some text inside and use different font-sizes:

    .box {
      height: 30px;
      display:inline-block;
      vertical-align:top;
      background-color: red;
      margin:5px;
    }
    svg {
      width:20px;
    }
    <div class="box">
      A
      <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
           viewBox="0 0 50 50">
        <rect width="50" height="50"/>
      </svg>
    </div>
    
    <div class="box" style="font-size:30px;">
      A
      <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
           viewBox="0 0 50 50">
        <rect width="50" height="50"/>
      </svg>
    </div>
    
    <div class="box" style="font-size:40px;">
      A
      <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
           viewBox="0 0 50 50">
        <rect width="50" height="50"/>
      </svg>
    </div>

    You can clearly see that the SVG is aligned with the baseline of the text and if the font-size is growing you will have an overflow. Same logic if we keep the same font-size and we decrease the height:

    .box {
      height: 40px;
      display:inline-block;
      vertical-align:top;
      background-color: red;
      margin:5px;
    }
    svg {
      width:40px;
    }
    <div class="box">
      A
      <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
           viewBox="0 0 50 50">
        <rect width="50" height="50"/>
      </svg>
    </div>
    
    <div class="box" style="height:20px;">
      A
      <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
           viewBox="0 0 50 50" style="width:20px;">
        <rect width="50" height="50"/>
      </svg>
    </div>
    
    <div class="box" style="height:10px;">
      A
      <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
           viewBox="0 0 50 50" style="width:10px;">
        <rect width="50" height="50"/>
      </svg>
    </div>

    And if you remove the text, the behavior will be kept the same since the baseline won't change:

    .box {
      height: 40px;
      width:40px;
      display:inline-block;
      background-color: red;
      margin:5px;
      padding:2px;
    }
    <div class="box">
      <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
           viewBox="0 0 50 50">
        <rect width="50" height="50"/>
      </svg>
    </div>
    
    <div class="box" style="height:20px;width:20px;">
      <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
           viewBox="0 0 50 50">
        <rect width="50" height="50"/>
      </svg>
    </div>
    
    <div class="box" style="height:10px;width:10px;">
      <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
           viewBox="0 0 50 50">
        <rect width="50" height="50"/>
      </svg>
    </div>
    
    <div class="box" style="height:5px;width:5px;">
      <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
           viewBox="0 0 50 50">
        <rect width="50" height="50"/>
      </svg>
    </div>

    To avoid this, simply adjust the alignment and make it different from baseline:

    .box {
      height: 20px;
      width:20px;
      display:inline-block;
      background-color: red;
      margin:5px;
      padding:2px;
    }
    
    svg {
     vertical-align:top;
    }
    <div class="box">
      <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
           viewBox="0 0 50 50">
        <rect width="50" height="50"/>
      </svg>
    </div>
    
    <div class="box" style="height:10px;width:10px;">
      <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
           viewBox="0 0 50 50">
        <rect width="50" height="50"/>
      </svg>
    </div>
    
    <div class="box" style="height:5px;width:5px;">
      <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
           viewBox="0 0 50 50">
        <rect width="50" height="50"/>
      </svg>
    </div>

    Or reset the font-size to 0:

    .box {
      height: 20px;
      width:20px;
      display:inline-block;
      background-color: red;
      margin:5px;
      padding:2px;
      font-size:0;
    }
    <div class="box">
      <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
           viewBox="0 0 50 50">
        <rect width="50" height="50"/>
      </svg>
    </div>
    
    <div class="box" style="height:10px;width:10px;">
      <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
           viewBox="0 0 50 50">
        <rect width="50" height="50"/>
      </svg>
    </div>
    
    <div class="box" style="height:5px;width:5px;">
      <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
           viewBox="0 0 50 50">
        <rect width="50" height="50"/>
      </svg>
    </div>