Unknown offset. (inline-flex element + clearfix) [duplicate] - css

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:
But when the inline-block is used the behaviour is different:
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

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

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.

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.

Related

::before element doesn't show up without display:flex

With below Code
.quote {
display: flex;
/*?? without this, ::before doesn't show up*/
}
.quote::before {
content: "";
min-width: 8px;
background-color: #F7DF94;
}
<div class="quote">
Hello World
</div>
I am not sure why the ::before element won't show up if I remove the display: flex.
Code snippet in JSbin here
The :before element doesn't "show up" because the default display property acts like display: inline; and you cannot set the with or height of an inline element.
Definition of width on MDN :
Applies to: all elements but non-replaced inline elements, table rows,
and row groups
[reference] (emphasis mine)
And the same goes for height, see here
When you set display: flex; on the parent, the children act like flex items that can have a width / height.
The initial value of align-items for flex items is normal (behaves like stretch in this context see here). This value makes the items take 100% height.
If you don't want to use display: flex; on the parent, you could change the default property of the pseudo element to display: inline-block; but you will need to specify a height otherwise it won't display either. Note that there will be a white-space between the pseudo element and the content.
Here is an example :
.quote::before {
display:inline-block;
content: "";
min-width: 8px;
min-height: 8px;
background-color: #F7DF94;
}
<div class="quote">
Hello World
</div>

In flexbox, why do we define the container and not the elements themselves?

I'm trying to understand the flex property.
Why do we apply float and display: inline-block to the elements that are nested inside a container, while with display: flex, we define the container itself?
How can the elements inside be display:block and still be positioned on the same row?
.flex {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
flex-direction: row;
}
#media (max-width: 600px) {
.flex {
flex-direction: column;
}
}
#aaa {
border: 3px solid black;
flex: 2;
}
#aa {
border: 3px solid black;
flex: 1;
}
#a {
border: 3px solid black;
flex: 1;
}
#bbb {
width: 300px;
}
#ccc {
float: left;
border: 5px solid yellow;
width: 200px;
}
#ddd {
clear: both;
}
.one {
background: red;
height: 50px
}
.two {
background: green;
height: 50px
}
.tree {
background: blue;
height: 50px
}
#eee {
display: inline-block;
width: 200px;
}
<div class=flex>
<div id=a class="one">flex</div>
<div id=aa class="two">flex</div>
<div id=aaa class="tree">flex</div>
</div>
<div class=block>
<div id=bbb class="one">block</div>
<div id=bbb class="two">block</div>
<div id=bbb class="tree">block</div>
</div>
<div class=float>
<div id=ccc class="one">float</div>
<div id=ccc class="two">float</div>
<div id=ccc class="tree">float</div>
</div>
<div class=block>
<div id=ddd class="one">block</div>
<div id=ddd class="two">block</div>
<div id=ddd class="tree">block</div>
</div>
<div class=block>
<div id=eee class="one">block</div>
<div id=eee class="two">block</div>
<div id=eee class="tree">block</div>
</div>
CodePen demo
In flexbox, why do we define the container and not the elements themselves?
The reason is twofold:
Flex containers are the only things flex items can appear as children of, since only flex containers generate flex layout.
Unlike anonymous block boxes and anonymous table boxes, there are no such things as anonymous flex container boxes.
So, a hypothetical display: flex-item wouldn't work unless the element's parent was a flex container, and since every child of a flex container automatically becomes a flex item anyway, this makes such a display type completely redundant.
Block-level and inline-level boxes, on the other hand, exist in many, many forms. Even flex containers can appear in block-level and inline-level forms, as display: flex and display: inline-flex respectively. Furthermore, display: block and display: inline-block actually have a lot in common, as they are both block containers. The only difference is that one is block-level and the other is inline-level (and the latter always generates a block formatting context, but that's not pertinent here).
So display: block and display: inline-block are actually very similar to display: flex and display: inline-flex respectively in that regard (see Difference between display:inline-flex and display:flex), the difference being that the former pair handles block layout or inline layout (see section 9.2 of the CSS2 spec), and the latter pair handles exclusively flex layout.
If you're asking why flexbox was designed this way, that's something only the CSSWG can answer with certainty, but I can provide an educated guess based on what I've stated above: Since block-level and inline-level boxes can exist in so many different forms for various internal layout types (block, table, flex, grid, etc), defining flex-level counterparts for every single layout type would become extremely unwieldy, even if they did introduce a concept of anonymous flex container boxes which would allow elements to exist as flex items in their own right. This is why css-display-3 redefines the display property to take the form of <display-outside> <display-inside> along with special and legacy values — to accommodate new layout types without having to redefine entire sets of keywords to go along with them.
Your flex items are display: block simply because that's their specified value of display. But they are laid out as flex items, which always obey a set of rules in flex layout, which are loosely based on a combination of various elements of block and inline layout without falling squarely within the domain of either one. This is similar to how a float or an absolutely positioned element cannot be inline even if you specify display: inline or display: inline-block — because floats and absolutely positioned elements always participate in block layout, never inline layout.
Speaking of floats, FYI, floats participate in block formatting contexts, and are therefore part of a certain subset of block layout. They follow a float model, but the float model is integrated with the rest of block layout rather than existing as a completely separate layout type.

How does float property blockify the element?

According to Cascading Style Sheets Level 2 Revision 2 (CSS 2.2) Specification,
when an element is given a float property other than none, it implicitly sets display to block, but the way i see it, its behaving like an inline-block element as it doesn't take 100% of it's parent's width.
an example:
These two blue bloxes are floated to the left so they implicitly set to display:block but they are not taking the whole width of the wrapper div (red-colored rectangle).
HTML Code
<div class="wrapper cf">
<div class="box"></div>
<div class="box"></div>
</div>
CSS Code
.wrapper {
background-color: red;
padding: 10px;
}
.box {
margin: 10px;
height: 100px;
width: 100px;
background: lightblue;
float: left;
}
.cf:after {
content: "";
display: block;
clear: both;
}
“There is a simple solution that fixes many of the IE float bugs. All floats become a block box; the standard says that the display property is to be ignored for floats, unless it’s specified as none. If we set display:inline for a floating element, some of the IE/Win bugs disappears as if by magic. IE/Win doesn’t make the element into an inline box, but many of the bugs are fixed.”
[Float Layouts]
As that suggests, the primary reason the block is added is for fixing issues that came up with floats in IE. Although the display:block is implicitly defined, display values aren't technically applied to floated elements except for if it is set to none.
If you want to learn more about floats, this is a pretty good article: CSS Float Theory: Things You Should Know

Align flex-box items to baseline of last text line in a block

I am trying to achive the last example on the following image, using flex-box.
From what I see, the align-items: baseline; property works great when the blocks only have 1 line.
The property align-items: flex-end; creates some issues mainly because the left and right items have different font-sizes and line-heights. Although the edges of the items are aligned, the white space created by the font size and line-height differences looks really bad when the item has no borders.
I'm trying to find a good all-around solution without any JS.
Thanks in advance.
You can wrap the contents of the flex items inside inline-block wrappers:
.flex {
display: flex;
align-items: baseline;
}
.inline-block {
display: inline-block;
}
.item { border: 1px solid red; }
.item:first-child { font-size: 200%; }
.flex::after { content: ''; position: absolute; left: 0; right: 0; border-top: 1px solid blue; }
<div class="flex">
<div class="item">
<div class="inline-block">Lorem<br />Ipsum<br />Dolor</div>
</div>
<div class="item">
<div class="inline-block">Foo bar</div>
</div>
</div>
That will work because, according to CSS 2.1,
The baseline of an 'inline-block' is the baseline of its last line box
in the normal flow, unless it has either no in-flow line
boxes or if its 'overflow' property has a computed value other than
'visible', in which case the baseline is the bottom margin
edge.
At the time of writing the CSS box model alignment working draft proposes a ‘first’ and ‘last’ value to be added to ‘align-items’. The would allow:
align-items: last baseline
Current it only appears to be supported by Firefox so is one for the future.
https://developer.mozilla.org/en-US/docs/Web/CSS/align-items

CSS clearfix not working

This (http://jsfiddle.net/77RRA/1/) is working, while this (http://jsfiddle.net/77RRA/) is not.
Isn't clearfix supposed to substitute the line <div style="clear: both;"></div>?
Isn't clearfix supposed to substitute the line <div style="clear: both;"></div>
Yes. The clearfix is there to avoid a non-semantic empty tag. However, for this to work you need to place it on the parent element. (Example)
In your case however, it does not address the problem that siblings will ignore the floated element. This is not the intend of clearfix, you simply add clear:right (or both as you will) on your #child sibling to restore the normal document flow.
your fixed Example
"Isn't clearfix supposed to substitute the line <div style="clear: both;"></div>?"
No
Imagine you have a container holding several items. If all of those items are floating, the container effectively loses its information of height. So margin-bottoms and background-styles are being displayed wrong. The clearfix solves this problem by adding pseudo-elements before and after the container element + setting a display: table; to stretch it back to its full height.
In your case, you will have to add a clear: both; on #child
In your case , you are trying to clear floatting element from itself (with a pseudo-element that belongs to itself).
Clear should be on elements following floatting elements.
Some other rules can achieve this too.
http://jsfiddle.net/77RRA/6/
#main {
background: lightgreen;
width: 100px;
height: 200px;
}
#one {
float: right;
display: block;
}
#child {
background: red;
width: 100%;
height: 20px;
display:inline-block
}
display:inline-block; will clear this element from floatting elements any sides.

Resources