Reputation: 57
I'm trying to position a fixed child div inside of a flexbox container, but running into browser compatibility issues between Firefox and Chrome. Using VW units to adjust margins on the child div results in different measurements in each browser. Can anyone tell me which browser has the correct interpretation and if there's any workaround to get both displaying consistently?
I've worked on a CodePen here: https://codepen.io/japongnet/pen/YbgZww
.parent {
background-color: #333333;
border: 1px solid black;
color: white;
width: 90vw;
height: 50vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.child {
background-color: #aaabbb;
width: 200px;
height: 200px;
margin-left: 50vw;
position: fixed;
}
<div class="parent">
<div class="child">
Child
</div>
</div>
Here's the output in Firefox:
And in Chrome:
Upvotes: 2
Views: 394
Reputation: 273031
I would say firefox is the correct one here but Chrome isn't violating any specfication and can also be correct.
The issue is related to the fact that you are not setting left
or right
value and the browser is considering the static position to identify the position of the element.
From the specification
For the purposes of this section and the next, the term "static position" (of an element) refers, roughly, to the position an element would have had in the normal flow. More precisely:
- The static-position containing block is the containing block of a hypothetical box that would have been the first box of the element if its specified 'position' value had been 'static' and its specified 'float' had been 'none'. (Note that due to the rules in section 9.7 this hypothetical calculation might require also assuming a different computed value for 'display'.)
- The static position for 'left' is the distance from the left edge of the containing block to the left margin edge of a hypothetical box that would have been the first box of the element if its 'position' property had been 'static' and 'float' had been 'none'. The value is negative if the hypothetical box is to the left of the containing block.
- The static position for 'right' is the distance from the right edge of the containing block to the right margin edge of the same hypothetical box as above. The value is positive if the hypothetical box is to the left of the containing block's edge.
Then later:
- 'left' and 'right' are 'auto' and 'width' is not 'auto', then if the 'direction' property of the element establishing the static-position containing block is 'ltr' set 'left' to the static position, otherwise set 'right' to the static position. Then solve for 'left' (if 'direction is 'rtl') or 'right' (if 'direction' is 'ltr').
Basically, we didn't set any left value to our element so the browser will use the left value of the element if it was set to position:static
Before setting position:fixed
we have the following which is the same in all the browsers:
.parent {
background-color: #333333;
border: 1px solid black;
color: white;
width: 90vw;
height: 50vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.child {
background-color: #aaabbb;
width: 200px;
height: 200px;
margin-left: 50vw;
}
<div class="parent">
<div class="child">
Child
</div>
</div>
If we add position:fixed
the element should not move and the same position should be kept which is the case in Firefox only:
.parent {
background-color: #333333;
border: 1px solid black;
color: white;
width: 90vw;
height: 50vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.child {
background-color: #aaabbb;
width: 200px;
height: 200px;
margin-left: 50vw;
position:fixed;
}
<div class="parent">
<div class="child">
Child
</div>
</div>
From the same specification we can also read:
But rather than actually calculating the dimensions of that hypothetical box, user agents are free to make a guess at its probable position.
Considering this we cannot say chrome is doing wrong. Chrome is considering the static position of the element without margin-left
specified like below:
.parent {
background-color: #333333;
border: 1px solid black;
color: white;
width: 90vw;
height: 50vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.child {
background-color: #aaabbb;
width: 200px;
height: 200px;
}
<div class="parent">
<div class="child">
Child
</div>
</div>
Then the position:fixed
is added:
.parent {
background-color: #333333;
border: 1px solid black;
color: white;
width: 90vw;
height: 50vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.child {
background-color: #aaabbb;
width: 200px;
height: 200px;
position:fixed;
}
<div class="parent">
<div class="child">
Child
</div>
</div>
Then margin-left is added:
.parent {
background-color: #333333;
border: 1px solid black;
color: white;
width: 90vw;
height: 50vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.child {
background-color: #aaabbb;
width: 200px;
height: 200px;
margin-left: 50vw;
position:fixed;
}
<div class="parent">
<div class="child">
Child
</div>
</div>
To make sure you will have the same behavior you need to either specify left
or right
:
.parent {
background-color: #333333;
border: 1px solid black;
color: white;
width: 90vw;
height: 50vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.child {
background-color: #aaabbb;
width: 200px;
height: 200px;
left: 50vw;
position:fixed;
}
<div class="parent">
<div class="child">
Child
</div>
</div>
Upvotes: 2