IE11 causing layout issues with flexbox [duplicate] - html

We have two divs with content and a third div that is a background with absolute position.
Container is a flexbox.
All works fine in Chrome and Safari, but Firefox and IE11 factors in the absolute positioned div, and distributes space between divs like there are 3 divs in a row.
I've made jsfiddle example. Is there any way to fix this bug?
https://jsfiddle.net/s18do03e/2/
div.container {
display: flex;
flex-direction: row;
width: 100%;
height: 300px;
justify-content: space-between;
width: 100%;
outline: 1px solid;
}
div.c1 {
background: #aaeecc;
width: 100px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.c2 {
background: #cceeaa;
width: 200px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.bg {
background: #ccc;
width: 100%;
height: 100%;
z-index: 0;
left: 0px;
top: 0px;
position: absolute;
display: flex;
}
<div class="container">
<div class="c1">Content 1</div>
<div class="c2">Content 2</div>
<div class="bg">Background</div>
</div>

UPDATE: This issue has been resolved in Firefox (as of v52, released March 2017). The problem still exists in IE11.
Like you wrote in the question:
Firefox calculates absolute positioned div, and distributes space between divs like there are 3 divs in a row.
Firefox is considering the third div (.bg), which is absolutely positioned, an in-flow flex item and factoring it into its space-between calculation. (IE11 does this, too; Chrome and Edge ignore it.)
Clearly, this is not in compliance with the current flexbox spec:
4.1. Absolutely-Positioned Flex Children
As it is out-of-flow, an absolutely-positioned child of a flex
container does not participate in flex layout.
Here are some workarounds:
Why not move the absolutely positioned div between the other two?
Instead of this:
<div class="container">
<div class="c1">Content 1</div>
<div class="c2">Content 2</div>
<div class="bg">Background</div>
</div>
Try this:
<div class="container">
<div class="c1">Content 1</div>
<div class="bg">Background</div>
<div class="c2">Content 2</div>
</div>
div.container {
display: flex;
flex-direction: row;
width: 100%;
height: 300px;
justify-content: space-between;
width: 100%;
outline: 1px solid;
}
div.c1 {
background: #aaeecc;
width: 100px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.c2 {
background: #cceeaa;
width: 200px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.bg {
background: #ccc;
width: 100%;
height: 100%;
z-index: 0;
left: 0px;
top: 0px;
position: absolute;
display: flex;
}
<div class="container">
<div class="c1">Content 1</div>
<div class="bg">Background</div>
<div class="c2">Content 2</div>
</div>
OR... remove .bg from the flex container:
<div class="container">
<div class="c1">Content 1</div>
<div class="c2">Content 2</div>
</div>
<div class="bg">Background</div>
div.container {
display: flex;
flex-direction: row;
width: 100%;
height: 300px;
justify-content: space-between;
width: 100%;
outline: 1px solid;
}
div.c1 {
background: #aaeecc;
width: 100px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.c2 {
background: #cceeaa;
width: 200px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.bg {
background: #ccc;
width: 100%;
height: 100%;
z-index: 0;
left: 0px;
top: 0px;
position: absolute;
display: flex;
}
<div class="container">
<div class="c1">Content 1</div>
<div class="c2">Content 2</div>
</div>
<div class="bg">Background</div>
OR... use the flex order property to re-arrange the flex items.
Add this to your code:
.c2 { order: 1; }
div.container {
display: flex;
flex-direction: row;
width: 100%;
height: 300px;
justify-content: space-between;
width: 100%;
outline: 1px solid;
}
div.c1 {
background: #aaeecc;
width: 100px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.c2 {
background: #cceeaa;
width: 200px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
order: 1;
}
div.bg {
background: #ccc;
width: 100%;
height: 100%;
z-index: 0;
left: 0px;
top: 0px;
position: absolute;
display: flex;
}
<div class="container">
<div class="c1">Content 1</div>
<div class="c2">Content 2</div>
<div class="bg">Background</div>
</div>

It is happening because justify-content: space-between; Distribute items evenly The first item at the start, the last at the end. So just putt <div class="bg">Background</div> between <div class="c1">Content 1</div> and <div class="c2">Content 2</div>
like this
<div class="container">
<div class="c1">Content 1</div>
<div class="bg">Background</div>
<div class="c2">Content 2</div>
</div>
You can see the reason on https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content

Sometimes it is not possible to re-order stuff, for example when using ::before and ::after. In those cases, you can manually order the elements.
In your case, you would need to do:
.c1 {
order: -1;
}
.c2 {
order: 10;
}
The order property is part of the flex spec and lets you re-order flex items (reference on MDN). It's very handy for multiple purposes, this included.
I used -1 because the value is ordinal, so setting it to a negative number ensures it precedes all other defaults and you don't need to specify the value for ::before. For the same reason, using 10 ensures that the second div comes last even if you add a bunch of elements to the container. You can increase that to 100 or whatever.
Still, Firefox's behaviour seems counterintuitive. position: absolute normally removes the element for the usual dom flow and I would expect that element to be removed from the flex flow as well, just like in Safari and Chrome. I am not sure whether the spec clarify this.

As an alternative you can use the flex property inside the content selector(s):
div.c1 {
background: #aaeecc;
width: 100px;
position: relative;
z-index: 50; top: 20px;
display: flex;
flex: 1; /* add this */
}
This will set the flex-grow. It might not be exactly what you need, but maybe it helps somebody else that can not reorder the content divs or take them out from the flex wrapper.
Here is the demo:
https://jsfiddle.net/s18do03e/14/

Related

CSS Display: inline-block but Stack Divs only if they overlap

I have the following divs below:
.parent {
padding: 10px;
background: grey;
}
.child {
background: green;
display: block;
position: relative;
width: 50px;
}
.stacked {
left: 0px;
}
.three {
left: 200px;
}
<div class="parent">
<div class="child stacked">div1</div>
<div class="child stacked">div2</div>
<div class="child three">div3</div>
</div>
This looks like the following:
I would like divs 1 and 2 to stack as they do, but since div3 does not collide with the divs above, I'd like it to vertically aline with div 1.
If I switch display to inline or inline-block, it pushes div 2 to the right of div one. and the left values are not accurate to the parant.
The left values of the divs will be dynamically generated so I cannot know if the divs are overlapping or not.
Is this possible?
Edit: If you really want to align the 3rd div using positioning, then you can do it like so:
.parent {
padding: 10px;
background: grey;
position: relative;
}
.child {
background: green;
display: block;
position: relative;
width: 50px;
}
.stacked {
position: relative;
left: 0px;
}
.three {
position: absolute;
left: 200px;
top: 10px;
}
<div class="parent">
<div class="child stacked">div1</div>
<div class="child stacked">div2</div>
<div class="child three">div3</div>
</div>
You can use the column-count property like so:
.parent {
padding: 10px;
background: grey;
column-count: 2;
}
.child {
background: green;
display: block;
width: 50px;
}
<div class="parent">
<div class="child">div1</div>
<div class="child">div2</div>
<div class="child">div3</div>
</div>
Or you can use flexbox to wrap vertically, like so:
.parent {
padding: 10px;
background: grey;
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 50px;
}
.child {
background: green;
display: block;
width: 50px;
}
<div class="parent">
<div class="child">div1</div>
<div class="child">div2</div>
<div class="child">div3</div>
</div>
Here's using grid:
.parent {
padding: 10px;
background: grey;
display: grid;
grid-auto-flow: column;
grid-template-rows: 1fr 1fr;
}
.child {
background: green;
display: block;
width: 50px;
}
<div class="parent">
<div class="child">div1</div>
<div class="child">div2</div>
<div class="child">div3</div>
</div>
Try this :
wrap div3 item in another div and give it a class property of flex-container.
.flex-container {
align-content: flex-start;
}
Ensure the flex direction is horizontal.

css Flex justify-content space-between not work correctly in Firefox and IE [duplicate]

We have two divs with content and a third div that is a background with absolute position.
Container is a flexbox.
All works fine in Chrome and Safari, but Firefox and IE11 factors in the absolute positioned div, and distributes space between divs like there are 3 divs in a row.
I've made jsfiddle example. Is there any way to fix this bug?
https://jsfiddle.net/s18do03e/2/
div.container {
display: flex;
flex-direction: row;
width: 100%;
height: 300px;
justify-content: space-between;
width: 100%;
outline: 1px solid;
}
div.c1 {
background: #aaeecc;
width: 100px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.c2 {
background: #cceeaa;
width: 200px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.bg {
background: #ccc;
width: 100%;
height: 100%;
z-index: 0;
left: 0px;
top: 0px;
position: absolute;
display: flex;
}
<div class="container">
<div class="c1">Content 1</div>
<div class="c2">Content 2</div>
<div class="bg">Background</div>
</div>
UPDATE: This issue has been resolved in Firefox (as of v52, released March 2017). The problem still exists in IE11.
Like you wrote in the question:
Firefox calculates absolute positioned div, and distributes space between divs like there are 3 divs in a row.
Firefox is considering the third div (.bg), which is absolutely positioned, an in-flow flex item and factoring it into its space-between calculation. (IE11 does this, too; Chrome and Edge ignore it.)
Clearly, this is not in compliance with the current flexbox spec:
4.1. Absolutely-Positioned Flex Children
As it is out-of-flow, an absolutely-positioned child of a flex
container does not participate in flex layout.
Here are some workarounds:
Why not move the absolutely positioned div between the other two?
Instead of this:
<div class="container">
<div class="c1">Content 1</div>
<div class="c2">Content 2</div>
<div class="bg">Background</div>
</div>
Try this:
<div class="container">
<div class="c1">Content 1</div>
<div class="bg">Background</div>
<div class="c2">Content 2</div>
</div>
div.container {
display: flex;
flex-direction: row;
width: 100%;
height: 300px;
justify-content: space-between;
width: 100%;
outline: 1px solid;
}
div.c1 {
background: #aaeecc;
width: 100px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.c2 {
background: #cceeaa;
width: 200px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.bg {
background: #ccc;
width: 100%;
height: 100%;
z-index: 0;
left: 0px;
top: 0px;
position: absolute;
display: flex;
}
<div class="container">
<div class="c1">Content 1</div>
<div class="bg">Background</div>
<div class="c2">Content 2</div>
</div>
OR... remove .bg from the flex container:
<div class="container">
<div class="c1">Content 1</div>
<div class="c2">Content 2</div>
</div>
<div class="bg">Background</div>
div.container {
display: flex;
flex-direction: row;
width: 100%;
height: 300px;
justify-content: space-between;
width: 100%;
outline: 1px solid;
}
div.c1 {
background: #aaeecc;
width: 100px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.c2 {
background: #cceeaa;
width: 200px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.bg {
background: #ccc;
width: 100%;
height: 100%;
z-index: 0;
left: 0px;
top: 0px;
position: absolute;
display: flex;
}
<div class="container">
<div class="c1">Content 1</div>
<div class="c2">Content 2</div>
</div>
<div class="bg">Background</div>
OR... use the flex order property to re-arrange the flex items.
Add this to your code:
.c2 { order: 1; }
div.container {
display: flex;
flex-direction: row;
width: 100%;
height: 300px;
justify-content: space-between;
width: 100%;
outline: 1px solid;
}
div.c1 {
background: #aaeecc;
width: 100px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.c2 {
background: #cceeaa;
width: 200px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
order: 1;
}
div.bg {
background: #ccc;
width: 100%;
height: 100%;
z-index: 0;
left: 0px;
top: 0px;
position: absolute;
display: flex;
}
<div class="container">
<div class="c1">Content 1</div>
<div class="c2">Content 2</div>
<div class="bg">Background</div>
</div>
It is happening because justify-content: space-between; Distribute items evenly The first item at the start, the last at the end. So just putt <div class="bg">Background</div> between <div class="c1">Content 1</div> and <div class="c2">Content 2</div>
like this
<div class="container">
<div class="c1">Content 1</div>
<div class="bg">Background</div>
<div class="c2">Content 2</div>
</div>
You can see the reason on https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content
Sometimes it is not possible to re-order stuff, for example when using ::before and ::after. In those cases, you can manually order the elements.
In your case, you would need to do:
.c1 {
order: -1;
}
.c2 {
order: 10;
}
The order property is part of the flex spec and lets you re-order flex items (reference on MDN). It's very handy for multiple purposes, this included.
I used -1 because the value is ordinal, so setting it to a negative number ensures it precedes all other defaults and you don't need to specify the value for ::before. For the same reason, using 10 ensures that the second div comes last even if you add a bunch of elements to the container. You can increase that to 100 or whatever.
Still, Firefox's behaviour seems counterintuitive. position: absolute normally removes the element for the usual dom flow and I would expect that element to be removed from the flex flow as well, just like in Safari and Chrome. I am not sure whether the spec clarify this.
As an alternative you can use the flex property inside the content selector(s):
div.c1 {
background: #aaeecc;
width: 100px;
position: relative;
z-index: 50; top: 20px;
display: flex;
flex: 1; /* add this */
}
This will set the flex-grow. It might not be exactly what you need, but maybe it helps somebody else that can not reorder the content divs or take them out from the flex wrapper.
Here is the demo:
https://jsfiddle.net/s18do03e/14/

Disable space-around for one special div [duplicate]

We have two divs with content and a third div that is a background with absolute position.
Container is a flexbox.
All works fine in Chrome and Safari, but Firefox and IE11 factors in the absolute positioned div, and distributes space between divs like there are 3 divs in a row.
I've made jsfiddle example. Is there any way to fix this bug?
https://jsfiddle.net/s18do03e/2/
div.container {
display: flex;
flex-direction: row;
width: 100%;
height: 300px;
justify-content: space-between;
width: 100%;
outline: 1px solid;
}
div.c1 {
background: #aaeecc;
width: 100px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.c2 {
background: #cceeaa;
width: 200px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.bg {
background: #ccc;
width: 100%;
height: 100%;
z-index: 0;
left: 0px;
top: 0px;
position: absolute;
display: flex;
}
<div class="container">
<div class="c1">Content 1</div>
<div class="c2">Content 2</div>
<div class="bg">Background</div>
</div>
UPDATE: This issue has been resolved in Firefox (as of v52, released March 2017). The problem still exists in IE11.
Like you wrote in the question:
Firefox calculates absolute positioned div, and distributes space between divs like there are 3 divs in a row.
Firefox is considering the third div (.bg), which is absolutely positioned, an in-flow flex item and factoring it into its space-between calculation. (IE11 does this, too; Chrome and Edge ignore it.)
Clearly, this is not in compliance with the current flexbox spec:
4.1. Absolutely-Positioned Flex Children
As it is out-of-flow, an absolutely-positioned child of a flex
container does not participate in flex layout.
Here are some workarounds:
Why not move the absolutely positioned div between the other two?
Instead of this:
<div class="container">
<div class="c1">Content 1</div>
<div class="c2">Content 2</div>
<div class="bg">Background</div>
</div>
Try this:
<div class="container">
<div class="c1">Content 1</div>
<div class="bg">Background</div>
<div class="c2">Content 2</div>
</div>
div.container {
display: flex;
flex-direction: row;
width: 100%;
height: 300px;
justify-content: space-between;
width: 100%;
outline: 1px solid;
}
div.c1 {
background: #aaeecc;
width: 100px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.c2 {
background: #cceeaa;
width: 200px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.bg {
background: #ccc;
width: 100%;
height: 100%;
z-index: 0;
left: 0px;
top: 0px;
position: absolute;
display: flex;
}
<div class="container">
<div class="c1">Content 1</div>
<div class="bg">Background</div>
<div class="c2">Content 2</div>
</div>
OR... remove .bg from the flex container:
<div class="container">
<div class="c1">Content 1</div>
<div class="c2">Content 2</div>
</div>
<div class="bg">Background</div>
div.container {
display: flex;
flex-direction: row;
width: 100%;
height: 300px;
justify-content: space-between;
width: 100%;
outline: 1px solid;
}
div.c1 {
background: #aaeecc;
width: 100px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.c2 {
background: #cceeaa;
width: 200px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.bg {
background: #ccc;
width: 100%;
height: 100%;
z-index: 0;
left: 0px;
top: 0px;
position: absolute;
display: flex;
}
<div class="container">
<div class="c1">Content 1</div>
<div class="c2">Content 2</div>
</div>
<div class="bg">Background</div>
OR... use the flex order property to re-arrange the flex items.
Add this to your code:
.c2 { order: 1; }
div.container {
display: flex;
flex-direction: row;
width: 100%;
height: 300px;
justify-content: space-between;
width: 100%;
outline: 1px solid;
}
div.c1 {
background: #aaeecc;
width: 100px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.c2 {
background: #cceeaa;
width: 200px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
order: 1;
}
div.bg {
background: #ccc;
width: 100%;
height: 100%;
z-index: 0;
left: 0px;
top: 0px;
position: absolute;
display: flex;
}
<div class="container">
<div class="c1">Content 1</div>
<div class="c2">Content 2</div>
<div class="bg">Background</div>
</div>
It is happening because justify-content: space-between; Distribute items evenly The first item at the start, the last at the end. So just putt <div class="bg">Background</div> between <div class="c1">Content 1</div> and <div class="c2">Content 2</div>
like this
<div class="container">
<div class="c1">Content 1</div>
<div class="bg">Background</div>
<div class="c2">Content 2</div>
</div>
You can see the reason on https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content
Sometimes it is not possible to re-order stuff, for example when using ::before and ::after. In those cases, you can manually order the elements.
In your case, you would need to do:
.c1 {
order: -1;
}
.c2 {
order: 10;
}
The order property is part of the flex spec and lets you re-order flex items (reference on MDN). It's very handy for multiple purposes, this included.
I used -1 because the value is ordinal, so setting it to a negative number ensures it precedes all other defaults and you don't need to specify the value for ::before. For the same reason, using 10 ensures that the second div comes last even if you add a bunch of elements to the container. You can increase that to 100 or whatever.
Still, Firefox's behaviour seems counterintuitive. position: absolute normally removes the element for the usual dom flow and I would expect that element to be removed from the flex flow as well, just like in Safari and Chrome. I am not sure whether the spec clarify this.
As an alternative you can use the flex property inside the content selector(s):
div.c1 {
background: #aaeecc;
width: 100px;
position: relative;
z-index: 50; top: 20px;
display: flex;
flex: 1; /* add this */
}
This will set the flex-grow. It might not be exactly what you need, but maybe it helps somebody else that can not reorder the content divs or take them out from the flex wrapper.
Here is the demo:
https://jsfiddle.net/s18do03e/14/

One div dynamic height one div remaining height and scroll

I have 2 divs inside a parent:
<div class="parent">
<div class="foo1"></div>
<div class="foo2"></div>
</div>
foo1 will have a dynamic height, so I can't use the style below:
height: calc(100% - foo1Height);
Now, what I want to do is make sure that the lower child foo2 never expands outside of the parent div, and to show the scrollbar if it gets too big. I would prefer CSS only solutions.
You can either use flexbox. no markup changes.
.parent {
display: flex;
flex-direction: column;
height: 100px;
}
.foo2 {
flex: 1; /*expand to fit*/
background: silver;
overflow: auto; /*scroll as needed*/
}
<div class="parent">
<div class="foo1">1</div>
<div class="foo2">2<br>2<br>2<br>2<br>2<br>2<br>2<br>2</div>
</div>
Or use CSS table, additional markup is required.
.parent {
display: table;
width: 100%;
height: 100px;
}
.foo1, .foo2 {
display: table-row;
}
.cell {
display: table-cell;
position: relative;
}
.foo2 {
height: 100%; /*expand to fit*/
background: silver;
}
.scroll {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow: auto; /*scroll as needed*/
}
<div class="parent">
<div class="foo1">
<div class="cell">1</div>
</div>
<div class="foo2">
<div class="cell">
<div class="scroll">2<br>2<br>2<br>2<br>2<br>2<br>2<br>2</div>
</div>
</div>
</div>

Absolutely positioned flex item is not removed from the normal flow in IE11

We have two divs with content and a third div that is a background with absolute position.
Container is a flexbox.
All works fine in Chrome and Safari, but Firefox and IE11 factors in the absolute positioned div, and distributes space between divs like there are 3 divs in a row.
I've made jsfiddle example. Is there any way to fix this bug?
https://jsfiddle.net/s18do03e/2/
div.container {
display: flex;
flex-direction: row;
width: 100%;
height: 300px;
justify-content: space-between;
width: 100%;
outline: 1px solid;
}
div.c1 {
background: #aaeecc;
width: 100px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.c2 {
background: #cceeaa;
width: 200px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.bg {
background: #ccc;
width: 100%;
height: 100%;
z-index: 0;
left: 0px;
top: 0px;
position: absolute;
display: flex;
}
<div class="container">
<div class="c1">Content 1</div>
<div class="c2">Content 2</div>
<div class="bg">Background</div>
</div>
UPDATE: This issue has been resolved in Firefox (as of v52, released March 2017). The problem still exists in IE11.
Like you wrote in the question:
Firefox calculates absolute positioned div, and distributes space between divs like there are 3 divs in a row.
Firefox is considering the third div (.bg), which is absolutely positioned, an in-flow flex item and factoring it into its space-between calculation. (IE11 does this, too; Chrome and Edge ignore it.)
Clearly, this is not in compliance with the current flexbox spec:
4.1. Absolutely-Positioned Flex Children
As it is out-of-flow, an absolutely-positioned child of a flex
container does not participate in flex layout.
Here are some workarounds:
Why not move the absolutely positioned div between the other two?
Instead of this:
<div class="container">
<div class="c1">Content 1</div>
<div class="c2">Content 2</div>
<div class="bg">Background</div>
</div>
Try this:
<div class="container">
<div class="c1">Content 1</div>
<div class="bg">Background</div>
<div class="c2">Content 2</div>
</div>
div.container {
display: flex;
flex-direction: row;
width: 100%;
height: 300px;
justify-content: space-between;
width: 100%;
outline: 1px solid;
}
div.c1 {
background: #aaeecc;
width: 100px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.c2 {
background: #cceeaa;
width: 200px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.bg {
background: #ccc;
width: 100%;
height: 100%;
z-index: 0;
left: 0px;
top: 0px;
position: absolute;
display: flex;
}
<div class="container">
<div class="c1">Content 1</div>
<div class="bg">Background</div>
<div class="c2">Content 2</div>
</div>
OR... remove .bg from the flex container:
<div class="container">
<div class="c1">Content 1</div>
<div class="c2">Content 2</div>
</div>
<div class="bg">Background</div>
div.container {
display: flex;
flex-direction: row;
width: 100%;
height: 300px;
justify-content: space-between;
width: 100%;
outline: 1px solid;
}
div.c1 {
background: #aaeecc;
width: 100px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.c2 {
background: #cceeaa;
width: 200px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.bg {
background: #ccc;
width: 100%;
height: 100%;
z-index: 0;
left: 0px;
top: 0px;
position: absolute;
display: flex;
}
<div class="container">
<div class="c1">Content 1</div>
<div class="c2">Content 2</div>
</div>
<div class="bg">Background</div>
OR... use the flex order property to re-arrange the flex items.
Add this to your code:
.c2 { order: 1; }
div.container {
display: flex;
flex-direction: row;
width: 100%;
height: 300px;
justify-content: space-between;
width: 100%;
outline: 1px solid;
}
div.c1 {
background: #aaeecc;
width: 100px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
}
div.c2 {
background: #cceeaa;
width: 200px;
position: relative;
z-index: 50;
top: 20px;
display: flex;
order: 1;
}
div.bg {
background: #ccc;
width: 100%;
height: 100%;
z-index: 0;
left: 0px;
top: 0px;
position: absolute;
display: flex;
}
<div class="container">
<div class="c1">Content 1</div>
<div class="c2">Content 2</div>
<div class="bg">Background</div>
</div>
It is happening because justify-content: space-between; Distribute items evenly The first item at the start, the last at the end. So just putt <div class="bg">Background</div> between <div class="c1">Content 1</div> and <div class="c2">Content 2</div>
like this
<div class="container">
<div class="c1">Content 1</div>
<div class="bg">Background</div>
<div class="c2">Content 2</div>
</div>
You can see the reason on https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content
Sometimes it is not possible to re-order stuff, for example when using ::before and ::after. In those cases, you can manually order the elements.
In your case, you would need to do:
.c1 {
order: -1;
}
.c2 {
order: 10;
}
The order property is part of the flex spec and lets you re-order flex items (reference on MDN). It's very handy for multiple purposes, this included.
I used -1 because the value is ordinal, so setting it to a negative number ensures it precedes all other defaults and you don't need to specify the value for ::before. For the same reason, using 10 ensures that the second div comes last even if you add a bunch of elements to the container. You can increase that to 100 or whatever.
Still, Firefox's behaviour seems counterintuitive. position: absolute normally removes the element for the usual dom flow and I would expect that element to be removed from the flex flow as well, just like in Safari and Chrome. I am not sure whether the spec clarify this.
As an alternative you can use the flex property inside the content selector(s):
div.c1 {
background: #aaeecc;
width: 100px;
position: relative;
z-index: 50; top: 20px;
display: flex;
flex: 1; /* add this */
}
This will set the flex-grow. It might not be exactly what you need, but maybe it helps somebody else that can not reorder the content divs or take them out from the flex wrapper.
Here is the demo:
https://jsfiddle.net/s18do03e/14/