Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Element with "display: inline-flex" has a strange top margin

Tags:

html

css

flexbox

I have two div elements, both with the CSS property display: inline-flex, as I would like to position them beside each other. At first, the div's appear to be positioned properly.

.userImg{
  height: 3em;
  width: 3em;
  background: red;
  display: inline-flex;
}

.nameOfUser{
  display: inline-flex;
  height: 3em; 
  width: 10em; 
  background: blue;
}
<div class = "userImg"></div>
                    
<div class = "nameOfUser"></div>

However, once I place some text inside of the nameOfUser div, it seems to create some strange top margin which makes the two div elements un-aligned from each other.

.userImg{
  height: 3em;
  width: 3em;
  background: red;
  display: inline-flex;
}

.nameOfUser{
  display: inline-flex;
  height: 3em; 
  width: 10em; 
  background: blue;
}
<div class = "userImg"></div>

<div class = "nameOfUser">
  <h3>Jaxon Crosmas</h3>
</div>

Can someone please explain why this is happening and a possible solution?

like image 523
Jaxon Crosmas Avatar asked Jan 05 '18 15:01

Jaxon Crosmas


People also ask

Does Flex work on inline elements?

The display:inline-flex does not make flex items display inline. It makes the flex container display inline. The main difference between display: flex and display: inline-flex is that display: inline-flex will make the flex container an inline element while its content maintains its flexbox properties.

Do inline elements respect margins?

Top and bottom margins do not affect inline elements because inline elements flow with content on the page. You can set left and right margins/padding on an inline element but not top or bottom because it would disrupt the flow of content.

Why display inline Flex is used?

Display:inline-flex apply flex layout to the flex items or children as well as to the container itself. As a result the container behaves as an inline flex element just like the children do and thus takes up the width required by its items/children only and not the entire width of the screen.

Why is display inline-block not working?

Because you are using inline-block, any newline character or whitespace you have after the element and before another inline element, will be counted as a space. If you want the blocks to stack side by side like in your picture, your HTML would need to be like this.


1 Answers

With display: inline-flex you are dealing with inline-level elements.

This activates the vertical-align property, which applies only to inline-level and table-cell elements (source).

The initial value of vertical-align is baseline. This means that inline-level elements position themselves vertically to achieve baseline (text) alignment.

baseline

The baseline is the line upon which most letters sit and below which descenders extend.

enter image description here

Source: Wikipedia.org

This is your current code structure, with the text you added:

.userImg {
  display: inline-flex;
  height: 3em;
  width: 3em;
  background: red;
}

.nameOfUser {
  display: inline-flex;
  height: 3em;
  width: 10em;
  background: aqua;
}
<div class="userImg"></div>
<div class="nameOfUser">
  <h3>Jaxon Crosmas</h3>
</div>

The second element shifts down so that it aligns with the current baseline of the first element.

Now add some text to the first element:

.userImg {
  display: inline-flex;
  height: 3em;
  width: 3em;
  background: red;
}

.nameOfUser {
  display: inline-flex;
  height: 3em;
  width: 10em;
  background: aqua;
}
<div class = "userImg">text</div>
<div class = "nameOfUser">
  <h3>Jaxon Crosmas</h3>
</div>

Notice how the baselines shift to align.

The elements still aren't squarely aligned because the h3 has default vertical margins. If you remove the margins:

.userImg {
  display: inline-flex;
  height: 3em;
  width: 3em;
  background: red;
}

.nameOfUser {
  display: inline-flex;
  height: 3em;
  width: 10em;
  background: aqua;
}

h3 { margin: 0; }
<div class = "userImg">text</div>
<div class = "nameOfUser">
  <h3>Jaxon Crosmas</h3>
</div>

Here are two quick solutions:

1. Override the default value of vertical-align, with any other value.

.userImg {
  display: inline-flex;
  height: 3em;
  width: 3em;
  background: red;
}

.nameOfUser {
  display: inline-flex;
  height: 3em;
  width: 10em;
  background: aqua;
}

div { vertical-align: top; }
<div class = "userImg"></div>
<div class = "nameOfUser">
  <h3>Jaxon Crosmas</h3>
</div>

2. Make the parent a flex container.

This makes your elements flex items, which de-activates vertical-align since flex items are block-level elements.

This method also lines up your elements in a row, because an initial setting of a flex container is flex-direction: row.

.userImg {
  height: 3em;
  width: 3em;
  background: red;
}

.nameOfUser {
  height: 3em;
  width: 10em;
  background: aqua;
}

body { display: flex; }
<div class = "userImg"></div>
<div class = "nameOfUser">
  <h3>Jaxon Crosmas</h3>
</div>
like image 158
Michael Benjamin Avatar answered Oct 03 '22 02:10

Michael Benjamin