8

I have a weird behaviour of an inline-flex element when applying a clearfix to it. When I set a clearfix to an element which has an inline-flex display property the strange white space appears before it:

inline-flex

But when the inline-block is used the behaviour is different:

inline-block

I don't understand why inline-flex has a different behaviour than inline-block.. and why it has that weird space.

.a,
.b {
  border: 1px solid red;
}
.a {
  text-align: center;
}
.b {
  display: inline-flex;
  height: 20px;
  width: 20px;
}
.cf:before,
.cf:after {
  content: " ";
  display: table;
}
.cf:after {
  clear: both;
}
<div class="a">
  <div class="b cf"></div>
</div>

JSFiddle Demo

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
starikovs
  • 3,240
  • 4
  • 28
  • 33
  • 2
    Why would you do that in the first place? Clear fix is a horrible hack to deal with hacking layouts using floats … and flexbox is a replacement for hacking layouts using floats. – Quentin Aug 10 '16 at 12:57
  • @Quentin, heh, good question! I found it not in my code.. – starikovs Aug 10 '16 at 13:22
  • 2
    @Quentin: The kind of people who use the clearfix hack with abandon are the kind of people who lack a fundamental understanding of what it does in the first place, and often even of floats in general. – BoltClock Aug 10 '16 at 15:25

3 Answers3

11

Try set a vertical-align: top to your inline-flex | inline-block element to fix this offset.

https://jsfiddle.net/jeca65my/2/

Thank's to @NenadVracar on this solution

Mikepote
  • 6,042
  • 3
  • 34
  • 38
Alvego
  • 336
  • 3
  • 7
8

display: inline-flex

When you use display: inline-flex, you establish a flex container.

An initial setting of a flex container is flex-direction: row.

This means that all in-flow child elements of the container (including in-flow pseudo-elements) will line up in a row. The display value of these children (table, in this case) is overridden/ignored, in accordance with the rules of a flex formatting context.

Your flex container has two flex items (the pseudo-elements) in one line:

.a,
.b {
  border: 1px solid red;
}
.a {
  text-align: center;
}
.b {
  display: inline-flex;
  height: 20px;
  width: 20px;
}
.cf:before,
.cf:after {
  content: "x";
  display: table;
}
.cf:after {
  clear: both;
}
<div class="a">
  <div class="b cf"></div>
</div>

display: inline-block

When you use display: inline-block, you establish a block formatting context.

The display property of child elements is respected.

Your pseudo-elements with display: table are block elements which, by default, occupy the full available width. Hence, the pseudos are creating two rows:

.a,
.b {
  border: 1px solid red;
}
.a {
  text-align: center;
}
.b {
  display: inline-block;
  height: 20px;
  width: 20px;
}
.cf:before,
.cf:after {
  content: "x";
  display: table;
}
.cf:after {
  clear: both;
}
<div class="a">
  <div class="b cf"></div>
</div>

vertical-align: baseline

Because both versions of your code use inline-level display values, this calls into play the vertical-align property, who's initial value is baseline.

The white space you are seeing below div.b when set to display: inline-flex is due to baseline alignment.

The white space you are seeing below div.b when set to display: inline-block is due to baseline alignment in combination with the effects of two block element children.

Here is a more detailed explanation:: https://stackoverflow.com/a/36975280/3597276


The clear property

.cf:after {
    clear: both;
}

Your clearfix method is not the source of any of the white space. In fact, it's having no effect on your layout and can be safely removed.

You use the clear property only when dealing with floats.

From the spec:

9.5.2 Controlling flow next to floats: the clear property

This property indicates which sides of an element's box(es) may not be adjacent to an earlier floating box.

Not only are there no floated elements in your layout, but if there were, the float and clear properties are nonetheless ignored in a flex formatting context.

3. Flex Containers: the flex and inline-flex display values

  • float and clear do not create floating or clearance of flex item, and do not take it out-of-flow.
Community
  • 1
  • 1
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
1

You have to imagine your page as a flow. Every element of your page is in the flow (DOM). You are using the position property to change the position in the flow.

block

A block element will Always start a new line. (ie: div)

inline-block

Inline blocks elements are blocks like div but with inline properties in it. (ie: span)

inline-flex

This is used the same way as inline-block in the flow. It makes a container that is inline but with the flex layout.

For your example, an interesting thing to do in order to focus on the difference between inline-block and inline-flex is to add text in your child div. You'll see that the comportment of your child div will once again change because it has text in it. JSFiddle example

EDIT : I found a sentence on SO that resumes well the situation. thank's to @BoltClock on This post :

display: inline-flex does not make flex items display inline. It makes the flex container display inline.

Community
  • 1
  • 1
Relisora
  • 1,163
  • 1
  • 15
  • 33