admin管理员组

文章数量:1404350

I am having a very hard time trying to vertically center SVG icons with text:

.text {
  display: inline;
  vertical-align: middle;
  font-size: 42px;
  line-height: 42px;
  font-family: "Montserrat";
  font-weight: 900;
}

.icon {
  display: inline;
  vertical-align: middle;
  line-height: 42px;
}

svg {
  width: 16px;
  height: 16px;
  display: inline;
  vertical-align: middle;
}
<link href=":ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<div class="text">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit
  <div class="icon">
    <svg xmlns="" viewBox="212 -791.77 536 627.77"><path d="M264-216h109.85v-237.69h212.3V-216H696v-348L480-726.77 264-564v348Zm-52 52v-426l268-201.77L748-590v426H534.15v-237.69h-108.3V-164H212Zm268-307.38Z"></path></svg>
  </div>
</div>

I am having a very hard time trying to vertically center SVG icons with text:

.text {
  display: inline;
  vertical-align: middle;
  font-size: 42px;
  line-height: 42px;
  font-family: "Montserrat";
  font-weight: 900;
}

.icon {
  display: inline;
  vertical-align: middle;
  line-height: 42px;
}

svg {
  width: 16px;
  height: 16px;
  display: inline;
  vertical-align: middle;
}
<link href="https://fonts.googleapis/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<div class="text">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit
  <div class="icon">
    <svg xmlns="http://www.w3./2000/svg" viewBox="212 -791.77 536 627.77"><path d="M264-216h109.85v-237.69h212.3V-216H696v-348L480-726.77 264-564v348Zm-52 52v-426l268-201.77L748-590v426H534.15v-237.69h-108.3V-164H212Zm268-307.38Z"></path></svg>
  </div>
</div>

See the result here: https://codepen.io/orobert91/pen/raNGmjW

The icon is completely off. What am I missing with vertical-align? Is this CSS attribute just broken with SVGs?

Note that the SVG icon MUST be wrapped and using display: flex is not an option.

Share Improve this question edited Mar 11 at 13:52 j08691 208k32 gold badges269 silver badges280 bronze badges asked Mar 11 at 13:42 olivierr91olivierr91 1,4373 gold badges14 silver badges36 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 2

You have a lot of useless styles. All you need is the below.

Note that middle may not have the effect your are looking for. It will slightly move the icon.

.text {
  font-size: 42px;
  line-height: 1;
  font-family: "Montserrat";
  font-weight: 900;
}

.icon {
  display: inline;
}

svg {
  width: 16px;
  aspect-ratio: 1;
  vertical-align: middle;
}
<link href="https://fonts.googleapis/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<div class="text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit
<div class="icon">
<svg xmlns="http://www.w3./2000/svg" viewBox="212 -791.77 536 627.77"><path d="M264-216h109.85v-237.69h212.3V-216H696v-348L480-726.77 264-564v348Zm-52 52v-426l268-201.77L748-590v426H534.15v-237.69h-108.3V-164H212Zm268-307.38Z"></path></svg>
</div>
</div>

If you want a perfect alignment inside the line

.text {
  font-size: 42px;
  line-height: 1;
  font-family: "Montserrat";
  font-weight: 900;
}

.icon {
  display: inline;
}

svg {
  width: 16px;
  aspect-ratio: 1;
  vertical-align: bottom;
  translate: 0 calc(50% - .5lh)
}
<link href="https://fonts.googleapis/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<div class="text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit
<div class="icon">
<svg xmlns="http://www.w3./2000/svg" viewBox="212 -791.77 536 627.77"><path d="M264-216h109.85v-237.69h212.3V-216H696v-348L480-726.77 264-564v348Zm-52 52v-426l268-201.77L748-590v426H534.15v-237.69h-108.3V-164H212Zm268-307.38Z"></path></svg>
</div>
</div>

Use display: contents; on .icon to bypass it when aligning. Set vertical-align: middle; on the svg:

.text {
  display: inline;
  font-size: 42px;
  line-height: 42px;
  font-family: "Montserrat";
  font-weight: 900;
}

.icon {
  display: contents;
}

svg {
  width: 16px;
  vertical-align: middle;
}
<link href="https://fonts.googleapis/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">

<div class="text">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit

  <div class="icon">
    <svg xmlns="http://www.w3./2000/svg" viewBox="212 -791.77 536 627.77"><path d="M264-216h109.85v-237.69h212.3V-216H696v-348L480-726.77 264-564v348Zm-52 52v-426l268-201.77L748-590v426H534.15v-237.69h-108.3V-164H212Zm268-307.38Z"></path></svg>
  </div>
</div>

vertical-align is not well suited for inline baseline adjustments

You may better avoid vertical-align completely and instead rely on transforms like translate.

A huge disadvantage of vertical-align is that it can introduce undesired line height changes - where transforms won't affect any line-heights or margins. Sure you could also adjust these margins e.g. by tweaking the icons line-height but transforms should be the safer way.

body{
    font-family: "Montserrat";
}

.text {
  font-size: 5vw;
  line-height: 1em;
  font-weight: 900;
  outline: 1px solid #ccc;
}

.svg-icon {
  /* rely on SVG intrinsic aspect-ratio defined by viewBox */
  width: auto;
  /* define relative size */
  height:0.45em;
  /* manual baseline shift */
  transform: translateY(-0.1em);
}

.svg-icon-va {
  width: auto;
  height:0.45em;
  vertical-align: 48px;
}
<link href="https://fonts.googleapis/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">


<p class="text">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit
    <svg class="svg-icon" viewBox="0 0 536 628"><path d="M 52 575 h 109.8 v -237.7 h 212.3 v 237.7 h 109.8 v -348 l -216 -162.8 l -216 162.8 v 348 z m -52 52 v -426 l 268 -201.8 l 268 201.8 v 426 h -213.9 v -237.7 h -108.3 v 237.7 h -213.8 z m 268 -307.4 z" /></svg>
  After icon<br>
  2nd line
</p>


<h3>Line shifts with vertical align</h3>
<p class="text">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit
    <svg class="svg-icon-va" viewBox="0 0 536 628"><path d="M 52 575 h 109.8 v -237.7 h 212.3 v 237.7 h 109.8 v -348 l -216 -162.8 l -216 162.8 v 348 z m -52 52 v -426 l 268 -201.8 l 268 201.8 v 426 h -213.9 v -237.7 h -108.3 v 237.7 h -213.8 z m 268 -307.4 z" /></svg>
  After icon<br>
  2nd line
</p>

Also, you may not need a wrapping div and use the svg directly as its default display property is already inline.
Since your SVG has a correct viewBox you can rely on its intrinsic aspect-ratio and just change the height or width relative to the parents font-size.

You may also use a font relative unit like ex to define a baseline shift.

  transform: translateY(-0.2ex);

Vertically centered?

All in all, you need to find the best value yourself as there is no "automagic" way to get the visually most appealing vertically centered position. For instance you may prefer something like the half capital height when using uppercase text.

body{
    font-family: "Montserrat";
}

.text {
  font-size: 4.5vw;
  line-height: 1em;
  font-weight: 900;
  outline: 1px solid #ccc;
}

.uc{
  text-transform:uppercase;
}

.lc{
  text-transform:lowercase;
}

.svg-icon {
  width: auto;
  /* define relative size */
  height:0.45em;
  transform: translateY(-0.1em);
}

.lc
.svg-icon {
  transform: translateY(-0.15ex);
}

.uc
.svg-icon {
  transform: translateY(-0.125cap);
}
<link href="https://fonts.googleapis/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">

<!--
<svg class="--icon" viewBox="212 -791.77 536 627.77"><path d="M264-216h109.85v-237.69h212.3V-216H696v-348L480-726.77 264-564v348Zm-52 52v-426l268-201.77L748-590v426H534.15v-237.69h-108.3V-164H212Zm268-307.38Z" /></svg>
    <svg viewBox="0 0 537 628"><path d="M 52 575 h 109.8 v -237.7 h 212.3 v 237.7 h 109.8 v -348 l -216 -162.8 l -216 162.8 v 348 z m -52 52 v -426 l 268 -201.8 l 268 201.8 v 426 h -213.9 v -237.7 h -108.3 v 237.7 h -213.8 z m 268 -307.4 z" /></svg>
-->


<p class="text uc">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit
    <svg class="svg-icon" viewBox="0 0 536 628"><path d="M 52 575 h 109.8 v -237.7 h 212.3 v 237.7 h 109.8 v -348 l -216 -162.8 l -216 162.8 v 348 z m -52 52 v -426 l 268 -201.8 l 268 201.8 v 426 h -213.9 v -237.7 h -108.3 v 237.7 h -213.8 z m 268 -307.4 z" /></svg>
  After icon<br>
  2nd line
</p>


<p class="text lc">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit
    <svg class="svg-icon" viewBox="0 0 536 628"><path d="M 52 575 h 109.8 v -237.7 h 212.3 v 237.7 h 109.8 v -348 l -216 -162.8 l -216 162.8 v 348 z m -52 52 v -426 l 268 -201.8 l 268 201.8 v 426 h -213.9 v -237.7 h -108.3 v 237.7 h -213.8 z m 268 -307.4 z" /></svg>
  After icon<br>
  2nd line
</p>

本文标签: htmlVerticalalign middle is completely off with inline SVG iconStack Overflow