Search code examples
csssvgbuttonflexbox

SVG positioning using flexbox within a button creates unexpected effect on other buttons in a row


I would like to make a responsive SVG icon placed near the text within a Button and aligned vertically in the center. While tried many various solutions I found using flexbox gives the best results.

Unfortunately I noticed a strange result when a such a button is placed in the same line with the identical button without an SVG icon inside. Those BUTTONS got positioned differently within a line, and I'm confused to understand why, and what can I do about it.

<!-- A benchmark button -->
<span>
  <button>
    Button (no SVG)
  </button>
</span>

<!-- A benchmark button with flex (no difference) -->
<span>
  <button class="flex-alignment">
    Button (flex, no SVG)
  </button>
</span>

<!-- A button with SVG -->
<span>
  <button>
    <svg viewBox="0 0 100 100"><rect width="100" height="100" fill="white" /></svg>
    Button (with SVG)
  </button>
</span>

<!-- A button with SVG (Flex positioned) Best result -->
<span>
  <button class="flex-alignment">
    <svg viewBox="0 0 100 100"><rect width="100" height="100" fill="white" /></svg>
    Button (flex, with SVG)
  </button>
</span>
span{
  display: inline-block
}

button{
  width: 200px;
  height: 50px;
  background: black;
  color: white;
  border: none;
}

.flex-alignment{
  display: flex;
  gap: 6px;
  justify-content: center;
  align-items: center;
}

svg{
  /* Make SVG inside the button proportional   */
  height: 60%;
}

The result

The example

The problem:

  1. If the button is not flexbox'ed the vertical positioning of the icon is a mess when button height is not fixed.
  2. If the button is flexbox'ed and is placed in the same line with a button containing no icon, buttons are not aligned vertically (???)

The codepen: https://codepen.io/tomastan/pen/OPJReqP

Any ideas?


Solution

  • The class .flex-alignment should be assigned to a "flex container" which is an element that contains the "flex items" which are all of the elements you want to have lined up and positioned with each other (eg. the <button>s). Moreover, those <span>s are pointless, they're not necessary.

    <section class="flex-alignment">
      <button>NO FLEX STYLES NEEDED</button>
      <button>NO FLEX STYLES NEEDED</button>
      <button>NO FLEX STYLES NEEDED</button>
      <button>NO FLEX STYLES NEEDED</button>
      <button>ALSO, NO SPANS NEEDED</button>
    </section>
    

    .flex-alignment {
      display: flex;
      justify-content: center;
      align-items: center;
      gap: 6px;
    }
    
    button {
      width: 200px;
      height: 50px;
      border: none;
      color: white;
      background: black;
    }
    
    svg {
      height: 60%;
    }
    <section class="flex-alignment">
      <button>
        Button (no SVG)
      </button>
    
      <button>
        Button (no SVG)
      </button>
    
      <button>
        <svg viewBox="0 0 100 100">
          <rect width="100" height="100" fill="white" />
        </svg>
        Button (with SVG)
      </button>
    
      <button>
        <svg viewBox="0 0 100 100">
          <rect width="100" height="100" fill="white" />
        </svg>
        Button (with SVG)
      </button>
    </section>