Home > Software engineering >  CSS - inline SVG interferes with line-height?
CSS - inline SVG interferes with line-height?

Time:11-11

I'm struggling to understand the the following css behavior. Maybe I'm missing something important because this actually seems like a simple scenario to me. Consider the following example:

.container {
  background-color: lime;
  font-size: 20px;
  line-height: 20px;
}
<div class="container">
  <svg width="1em" height="1em" viewBox="0 0 24 24" >
      <circle cx="12" cy="12" r="10"/>
  </svg>
  Text
</div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Because container has line-height: 20px set, I'd expect it to be 20px high. At least this is the case if it only contains text. With the svg however it is suddenly 24px high, even though the svg is 20px high, as expected because of height=1em. Also the "Text" has a height of 23px, even though I'd expect it to be 20px.

Interestingly, if I set container's line-height to something like 30px, it behaves as expected: container is now 30px high.

Can you help me understand why container is not 20px high? Or is line-height simply not easily predictable once the container contains other elements than just plain text? Thank you!

CodePudding user response:

There are two things going on in your demo that are affecting the height of div.container. First, line-height isn't an explicit, fixed height: it specifies the minimum height of line boxes within div.container in your case. Since line-height is a minimum, it can grow if something inside it causes it to grow.

That leads to the SVG: it has a default vertical-align of baseline, which aligns it to the baseline of div.container, and, due to its height, causes the height of div.container to grow to accommodate it. By changing vertical-align of the SVG to something else so it fits within your 20px line-height, you can make it fit.

I've added a few different vertical-align props to your demo so you can see how alignment affects height. In general, bottom and top align the svg to the bottom and top of the line, respectively, which, given the SVG's 20px height, keep it within the line-height. However, if you really, really need div.container to be 20px height, height or max-height are probably better bets.

.container {
  background-color: lime;
  font-size: 20px;
  line-height: 20px;
    margin-bottom: 1em;
}
<div class="container">
  <svg width="1em" height="1em" viewBox="0 0 24 24" >
      <circle cx="12" cy="12" r="10"/>
  </svg>
  Default: vertical-align: baseline (24px)
</div>

<div class="container">
  <svg width="1em" height="1em" viewBox="0 0 24 24" style="vertical-align:middle">
      <circle cx="12" cy="12" r="10"/>
  </svg>
  Default: vertical-align: middle (~22px)
</div>

<div class="container">
  <svg width="1em" height="1em" viewBox="0 0 24 24" style="vertical-align:bottom">
      <circle cx="12" cy="12" r="10"/>
  </svg>
  Default: vertical-align: bottom (20px)
</div>

<div class="container">
  <svg width="1em" height="1em" viewBox="0 0 24 24" style="vertical-align:top">
      <circle cx="12" cy="12" r="10"/>
  </svg>
  Default: vertical-align: top (20px)
</div>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

This gets all heights to 20px using flex, align-items: center; and line-height: 1rem;:

.container {
  background-color: lime;
    font-size: 20px;
    line-height: 1rem;
    display: flex;
    align-items: center;
}
<div class="container">
  <svg width="1em" height="1em" viewBox="0 0 24 24" >
      <circle cx="12" cy="12" r="10"/>
  </svg>
  Text
</div>
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related