Why do Chrome and Firefox show different flex layout results?
Source of the Problem
Here is the source of the problem:
.flexContainer {
display: flex;
flex-flow: row wrap;
justify-content: center;
align-items: stretch;
align-content: flex-start; <-- problem
}
Background
The align-content
property controls the cross-axis alignment of flex lines within the flex container. Think of flex lines as the rows or columns (depending on flex-direction
) in which flex items live. Put another way, align-content
distributes the space between and around flex lines, packing them to the top, bottom, center, etc. (see the full list of values).
Because align-content
distributes space between and around flex lines, it can only work on multi-line flex containers. (A single-line extends across the full cross-axis length of the container leaving no free space for align-content
to work.)
Obviously, a multi-line container is a container with more than one line (flex items have wrapped). Technically, however, a multi-line container is simply a container with flex-wrap: wrap
or flex-wrap: wrap-reverse
(regardless of whether flex items have wrapped, or even exist).
Same concept applies to a single-line flex container, which is a container with flex-wrap: nowrap
. The align-content
property has no effect in nowrap
containers, as discussed above.
§ 8.4. Packing Flex Lines: the
align-content
propertyThe
align-content
property aligns a flex container’s lines within
the flex container when there is extra space in the cross-axis,
similar to howjustify-content
aligns individual items within the
main-axis. Note, this property has no effect on a single-line flex
container.§ 6. Flex
LinesFlex items in a flex container are laid out and aligned within flex
lines, hypothetical containers used for grouping and alignment by the
layout algorithm. A flex container can be either single-line or
multi-line, depending on theflex-wrap
property:
A single-line flex container (i.e. one with
flex-wrap: nowrap
) lays out all of its children in a single line, even if that would
cause its contents to overflow.A multi-line flex container (i.e. one with
flex-wrap: wrap
orflex-wrap: wrap-reverse
) breaks its flex items across multiple lines, similar to how text is broken onto a new line when it gets too wide to fit on the existing line.
The Discrepancy between Chrome and Firefox / Edge
Looking again at your code:
body {
background-color: teal;
}
.flexContainer {
background-color: blue;
border: 1px solid black;
height: 300px;
}
.flexItem {
background-color: red;
border: 1px solid black;
}
.flexContainer {
display: flex;
flex-flow: row wrap;
justify-content: center;
align-items: stretch;
align-content: flex-start;
}
.flexItem {
flex: 0 1 0;
}
<div class="flexContainer">
<div class="flexItem">1111111111111111111</div>
<div class="flexItem">2222<br/>2222</div>
<div class="flexItem">3333<br/>3333<br/>3333</div>
<div class="flexItem">4444444444444444444</div>
</div>
Firefox and Chrome showing different results when using flex-grow
The problem is not with flex-grow
property, but rather with the fact, that the .actual-menu
has display: table
. If you read through the answers and comments of this stackoverflow question, you'll see that, in short, using a table as a flex child directly is a bad idea.
What I can see, is that you are using the table layout just to achieve text centering of the menu items. But since you are already using flexbox for other parts of your layout, why not use it here, like so:
body {
margin: 0;
background-color: black;
}
.menu-container {
position: relative;
margin-top: 50px;
margin-right: auto;
margin-left: auto;
width: 59%;
height: 75px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
.menu-container .menu-logo {
width: 220px;
height: 100%;
background-image: url("https://via.placeholder.com/220x75.png");
-webkit-box-flex: 0;
-ms-flex: none;
flex: none;
}
.menu-container .menu-social {
position: absolute;
flex: none;
top: 0;
right: 0;
}
.menu-container .menu-social img {
padding-right: 5px;
}
.menu-container .actual-menu {
position: relative;
background-color: white;
border-radius: 24px 0 0 24px;
bottom: 0;
height: 45px;
width: auto;
display: flex;
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
top: 35%;
margin-left: 5px;
}
.menu-container ul.menu-links {
width: 100%;
margin: auto;
}
.menu-container ul.menu-links li {
display: inline;
text-transform: uppercase;
padding-right: 30px;
font-size: 16pt;
font-size: 2vh;
}
<div class="menu-container">
<div class="menu-social">
<img src="https://via.placeholder.com/27x15.png" alt="youtube">
<img src="https://via.placeholder.com/27x15.png" alt="twitter">
<img src="https://via.placeholder.com/27x15.png" alt="facebook">
<img src="https://via.placeholder.com/27x15.png" alt="discord">
</div>
<div class="menu-logo"></div>
<div class="actual-menu">
<ul class="menu-links">
<li>Test</li>
<li>Test</li>
<li>Test</li>
<li>Test</li>
<li>Test</li>
<li>Test</li>
<li>Test</li>
</ul>
</div>
</div>
Flexbox & Images — different results in Chrome and Firefox
Interesting case! I don't know why this happens with flexbox.
But, after some experimenting I figured out that it works by positioning the img
relative to its cell:
.cell {
position: relative;
}
.cell img {
position: absolute;
}
This works in both Firefox and Chrome.
Flex-box discrepancy between Chrome and Firefox
I don't see any reason why this code would work. Your height: 1px
trick is a hack. It's non-standardized code. So browser behavior can vary.
If you must keep this code structure, consider switching from height: 1px
to min-height: 1px
.
flex-shrink discrepancy between Firefox and Chrome
flex-shrink
discrepancy between Firefox and Chrome
There is a discrepancy but flex-shrink
doesn't appear to be the cause.
Is this the result of a browser bug, and if so, which is rendering per spec, and which is not?
It doesn't appear to be a bug. It looks more like an intervention, which is a deliberate deviation from the spec, and is being applied by Chrome.
flex-shrink: 1
An initial setting of a flex container is flex-shrink: 1
, as defined by the flexbox spec. This means that flex items are permitted to shrink in order to avoid overflowing the container.
Both Chrome and Firefox adhere to this guidance. You can verify this in developer tools by checking the browser's default styles for flex items. Both Chrome and Firefox render your flex items with flex-shrink: 1
.
For more details see: How does flex-shrink factor in padding and border-box?
min-height: auto
An initial setting of flex items in a column-direction container is min-height: auto
. In a row-direction container the items are set to min-width: auto
. This means that the default minimum size of a flex item is the size of its content or its specified length along the main axis.
Full more details see: Why don't flex items shrink past content size?
Your code
You have a column-direction flex container with two flex items: .navbar
and #tall
. In Chrome and Firefox, both items are set by default to flex-shrink: 1
and min-height: auto
. I verified this using dev tools. Everything looks good so far; all settings are in compliance with the spec.
Here's where the discrepancy begins: The #tall
item is set to height: 300%
. This item is much taller than the container. However, with flex-shrink: 1
there can be no overflow. All items with a non-zero flex-shrink
must reduce their size to prevent themselves and their siblings from overflowing the container (assuming the size of the content allows this). But with min-height: auto
, the items cannot reduce their size below the height of their content.
All this works in Firefox. But why not in Chrome? Why is the .navbar
item, which is being squeezed by #tall
, shrinking below the size of its content (the button) in Chrome?
Firefox
As stated above, the #tall
element, with a height: 300%
, cannot overflow the container because of flex-shrink
. Its sibling, the .navbar
item, must also shrink because of flex-shrink
. However, it cannot shrink below the size of its content because of min-height: auto
. All good. Everything complies with the spec.
Chrome
Like in Firefox, the #tall
element, with a height: 300%
, cannot overflow the container because of flex-shrink
. Its sibling, the .navbar
item, must also shrink because of flex-shrink
. However, it should not shrink below the size of its content because of min-height: auto
, but it does anyway. Why?
Interventions
An intervention is when a user agent decides to deviate slightly from a standardized behavior in order to provide a greatly enhanced user experience.
source: https://github.com/WICG/interventions
From my answer here:
Since at least 2017, it appears that Chrome is either (1) reverting back to the
min-width: 0
/min-height: 0
defaults, or (2) automatically applying the0
defaults in certain situations based on a mystery algorithm. (This could be what they call an intervention.) As a result, many people are seeing their layout (especially desired scrollbars) work as expected in Chrome, but not in Firefox / Edge.
So, as stated in the beginning of this answer, the problem you're encountering is probably not a bug, but a deliberate deviation from the spec. It would be Firefox that is in full compliance with the spec.
Important Notes
It's important to note that I have no direct knowledge of the internal workings of Chrome, Firefox or any other browsers. I only believe Chrome is applying a min-height
intervention based on my personal observations. It's a theory. More like an extrapolation. There is a possibility that I am not entirely (or even remotely?) correct. Chrome could be fiddling with min-height
, flex-shrink
and/or other properties. I don't know for sure.
It's also important to note that, because this behavior is not in accordance with the spec, it may not be reliable and can change at any time.
Flex behaves differently in chrome and Firefox
The issue is related to the use of min-width:100%
on hover creating this bad effect. You can use a fixed width instead that is big enough to fit all your texts:
:root {
--background: 255, 255, 255;
--surface: 255, 255, 255;
--color: 0, 0, 0;
--shadow: 0, 0, 0, .25;
--error-background: 211, 47, 47;
--error-color: 0, 0, 0;
--onBackground: 18, 18, 18;
--onSuface: 18, 18, 18;
--onError-background: 0, 0, 0;
--onError-color: 255, 255, 255;
}
* {
min-height: 32px;
min-width: 32px;
}
body {
margin: 0;
background-color: rgb(var(--background));
font-size: calc(12px + .625vmin);
color: rgb(var(--color));
}
div {
border-radius: 4px;
}
.fabs {
z-index: 6;
position: fixed;
bottom: 0;
right: 0;
max-height: 100%;
display: flex;
flex-direction: column-reverse;
flex-wrap: wrap-reverse;
align-content: baseline;
will-change: clip-path, opacity;
transition: clip-path .3s ease-out, opacity .3s ease;
clip-path: inset(calc(100% - 64px - 5vmin) 0 0 calc(100% - 80px - 7.5vmin));
overflow: hidden;
contain: layout style;
}
.fabs>a {
max-width: calc(48px + 2.5vmin);
max-height: calc(48px + 2.5vmin);
min-height: calc(48px + 2.5vmin);
border-radius: calc(24px + 1.25vmin);
background-color: rgb(var(--surface));
display: block;
text-decoration: none;
border: .5px solid rgb(var(--color), .2);
box-shadow: 0 0 6px rgba(var(--shadow));
margin: calc(8px + 1.25vmin) calc(16px + 2.5vmin);
transition: max-width .5s ease;
overflow: hidden;
visibility: visible;
}
.fabs:hover {
clip-path: inset(0);
}
.fabs>a~a:hover {
max-width: 300px;
}
.fabs svg {
width: calc(48px + 2.5vmin);
stroke: rgba(var(--color), .7);
}
.fabs>a~a::after {
content: attr(title);
vertical-align: top;
line-height: calc(48px + 2.5vmin);
margin-right: calc(24px + 1.25vmin);
color: rgb(var(--color));
}
<div class="fabs" id="fabs">
<a href="javascript:void(0)">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-4 -4 32 32">
<line x1="6" y1="12" x2="18" y2="12"></line>
<line x1="12" y1="6" x2="12" y2="18"></line>
</svg>
</a>
<a href="javascript:home()" title="Home">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-4 -4 32 32">
<polyline points="7 10.2,7 17,10.5 17,10.5 12,13.5 12,13.5 17,17 17,17 10.2" fill="#fff0"></polyline>
<polyline points="5 11,12 5,19 11" fill="#fff0"></polyline>
</svg>
</a>
<a href="javascript:window.scrollTo({top:0,behavior:'smooth'})" title="Top">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-4 -4 32 32">
<line x1="8" y1="7" x2="16" y2="7"></line>
<polyline points="8 13,12 9,16 13" fill="#fff0"></polyline>
<line x1="12" y1="10" x2="12" y2="18"></line>
</svg>
</a>
<a href="javascript:theme(+1)" title="Turn Theme">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-8 -8 40 40">
<path fill="#fff0" d="M22.6 11.29L20 8.69V5c0-.55-.45-1-1-1h-3.69l-2.6-2.6c-.39-.39-1.02-.39-1.41 0L8.69 4H5c-.55 0-1 .45-1 1v3.69l-2.6 2.6c-.39.39-.39 1.02 0 1.41L4 15.3V19c0 .55.45 1 1 1h3.69l2.6 2.6c.39.39 1.02.39 1.41 0l2.6-2.6H19c.55 0 1-.45 1-1v-3.69l2.6-2.6c.39-.39.39-1.03 0-1.42zm-4.68 1.69c-.34 2.12-1.85 3.94-3.88 4.66-1.21.43-2.41.45-3.5.18-.41-.1-.48-.65-.13-.9C11.98 15.84 13 14.04 13 12s-1.02-3.84-2.58-4.92c-.35-.24-.29-.79.13-.9 1.09-.27 2.29-.25 3.5.18 2.02.72 3.54 2.54 3.88 4.66.05.33.07.66.07.98-.01.32-.03.65-.08.98z"></path>
</svg>
</a>
</div>
Different implementation of Flexbox in Firefox and Chrome
The following code works as expected in Firefox
I disagree with this because for me Chrome is behaving as expected for 2 reasons:
You set the width of the image to be
100%
which means 100% of their containing block (container) that is defined by600px
. So each image will be600px
The image cannot shrink past its content size due to the default
min-width
configuration (note that usingunset
is equivalent toinitial
in this case so it's somehow useless). So the image will be kept at600px
If you add min-width:0
the image will shrink only in width:
.r {
width: 100%;
/*height: auto; useless */
min-width: 0;
max-width: 100%;
}
.container {
display: flex;
width: 600px;
}
<div class="container">
<img src="https://via.placeholder.com/1000x500" class="r" >
<img src="https://via.placeholder.com/1000x500" class="r" >
<img src="https://via.placeholder.com/1000x500" class="r" >
<img src="https://via.placeholder.com/1000x500" class="r" >
</div>
Related Topics
How to Keep Aspect Ratio of a Background-Image
Text with Image Background in Svg or CSS
Foundation 5 Build Isn't Complete
Slide Up/Down Effect with Ng-Show and Ng-Animate
Use Multiple CSS Filters at the Same Time
List of CSS Features Not Supported by IE6
CSS Animations with Spritesheets in a Grid Image (Not in a Row)
Position Absolute and Bottom 0
How to Use Font-Weight with Font-Face Fonts
What Happens When Nesting Elements with Position: Fixed Inside Each Other
Why Is the Use of '!Important' Discouraged
Continuously Adjust Element Size as Screen Size Changes
Responsive Iframe (Google Maps) and Weird Resizing
How to Use Bootstrap Modals Without Loading the Entire Library