Vertical margins/paddings and Flexbox, a quirky combination
Vertical margins/paddings and Flexbox, a quirky combination ź“ė Ø
tl;dr
In CSS, percentage-based paddings are ā as per spec ā calculated with respect to the width of an element. However, for flex items (e.g. items whose parent have display: flex; applied) thatās not always the case.
Depending on which browser you are using the percentage-based padding of a flex item will be resolved against its height instead of its width ⦠and the spec is totally fine with that.
Until browser vendors agree on one behavior, be advised to not use vertical margins/paddings on flex items ⦠and know that the CSS Aspect Ratio Hack wonāt work on them.
UPDATE 2018-01-24
Microsoft has announced (w3c/csswg-drafts#2085) that they are going to implement the Blink/Webkit behavior for compat reasons and ship it in the next version of Edge.
As a result Firefox ā the only browser left with the āoddā behavior, once the change in Edge ships ā also decided to follow the same path (w3c/csswg-drafts). Work to implement this has already started.
Soon, this quirk will be resolved and all (modern) browsers will have the same behavior.
UPDATE 2018-01-31
The relating Firefox bug has been closed and got marked as resolved. The changes are planned to ship with the release of Firefox 60. š
As detailed in āAspect Ratios in CSS are a Hackā we can use percentage-based padding to force a box to have a fixed aspect ratio.
However, In a recent project I was working on I noticed that my aspect ratio boxes werenāt working as expected in Firefox. Where other browsers would nicely render boxes with their set aspect ratio, Firefox would do render the box with a fixed height, independent of the boxās defined width.
Digging deeper into the problem ā in order to flesh out what exactly triggers this rendering quirk ā I knocked up a testcase in which it became clear to me that the CSS Aspect Ratio Hack didnāt seem to work on flex items (e.g. elements that are contained inside a parent element that has display: flex; applied) ā Uh oh!
Interpreting the results


In Chrome/Edge/Safari the green box acts as expected, and has a 16:9 aspect ratio thanks to a 56.25% vertical padding. Firefox however renders the box with a height of 281.25px, independent of its width. Running some numbers this 281.25px turns out to be exactly 56.25% of 500px, which is the height of its parent.
This must be a bug, right?
Filing a bug
So I set out to file a bug report for Firefox. To my surprise the issue got closed, concluding that Firefox renders things correctly ⦠as do all the other browsers.
Huh? How can two different results both be correct? Turns out thereās some wiggle room in the spec:
"CSS Flexible Box Layout Module Level 1 - 4.2. Flex Item Margins and Paddings" From CSS Working Group Editor Drafts (drafts.csswg.org)
Percentage margins and paddings on flex items can be resolved against either:
- their own axis (left/right percentages resolve against
width, top/bottom resolve againstheight)- the inline axis (left/right/top/bottom percentages all resolve against
width)A User Agent must choose one of these two behaviors.
Now letting browsers choose which behavior they want to implement of course isnāt ideal, and thatās also what spec writer Tab Atkins has added as a note:
Note
This behavior sucks, but it accurately captures the current state of the world. It is the CSSWGās intention that browsers will converge on one of the behaviors, at which time the spec will be amended to require that.
Down the Rabbit Hole: How come Firefox behaves differently?
The āculpritā for this quirk is that an older version of the spec read this on margin/padding behavior for flex items:
From CSS Working Group Wiki (wiki.csswg.org)
Percentage margins and paddings on flex items are always resolved against their own axis: left and right margins resolve against the containing blockās width, and top and bottom margins resolve against the containing blockās height. Unlike blocks, block-axis margins do not resolve against the inline dimension of their containing block.
One might wonder why this initially specced behavior behaves different from what we are used to. As Tab Atkins put it:
"Issue#41005888" From Chromium (issues.chromium.org)
The logic is that the behavior of percentage vertical padding in existing layout modes is document-focused, where width is *always* the dominant measurement; height is nearly never an input to anything. The newer layout modes (Flexbox and Grid) are different ā in them, height and width are on a more equal playing field, and code written that uses percentage padding in the main axis of a flexbox should work equally well for row and column flexboxes. Similar arguments apply for Grid.
So Firefox had implemented this behavior from the start on, and kept in place as a change in the spec still accepted it.
Sidenote
In an archived mailing list message ā again by Tab Atkins, the man truly is/was the thriving force behind this spec ā I also found this note on the fact that speccing it in this way would nullify the existing aspect ratio hacks:
We recognize that there are some drawbacks, notably the inconsistency with existing document-focused display modes, and the loss of the ability to employ the common āaspect-ratioā hack involving vertical padding. We believe that the first is not too relevant [ā¦]. The second is unfortunate, but we plan to address aspect ratios directly in the future, and so consider the loss of this hack for now to be not significant enough to sway our opinion.
⦠but we plan to address aspect ratios directly in the future ⦠ā More on that in a later post š
Feeling Curious
But why was the original spec changed in the first place? Looking at one of the responses in my initial bug report the adjustment was made because Chrome refused to implement the spec-mandated behavior.
I can follow Chrom(e/ium)ās decision here, as us developers are already used to a vertical padding being calculated with respect to the width:
"Issue#41005888" From Chromiume (issues.chromium.org)
Part of the reason weāre arguing to change the spec is that all the developers weāve heard from want the Blink/WebKit behavior because they want to do the aspect ratio hack. Weāve had no developers asking for the specced behavior.
On the other hand, one must admit that the behavior weāre used to is an acquired taste. The first time I ever set a vertical padding I thought itād be resolved against the height and not the width.
The easy fix would be for Firefox to adjust its behavior to what other browsers do, right? In the long run however ā given the history laid out here ā I personally thing it might be better to follow the initially specced behavior. Why cling on to an acquired taste, and possibly limit our future possibilities?
That might explain why the spec authors didnāt just switch from one behavior to the other, but added a second behavior instead. By adding a second behavior, they left the door open for future decisions on the matter. For example: the day native aspect ratio methods arrive in browsers, this part of the spec can be reevaluated (and hopefully one of both behaviors can be chosen).
What now?
For now, be advised to not use percentage-based values paddings/margins when it comes to flex items as thereās still some ongoing discussion going on about this. This is also noted in the spec:
Advisement
Authors should avoid using percentages in paddings or margins on flex items entirely, as they will get different behavior in different browsers.
The fact that the bug reports on this are still open for both Chromium and Firefox tell me that thereās more to come concerning this. The longer they remain open though, the more sites that might break though once a consensus has been reached.
In case you do want to use any of the current hacks to creating aspect ratios with CSS in combination with flex items, donāt apply the styles on one and the same element but use separate elements for them.
Itās things like this that make the simple thing called CSS not easy š
UPDATE 2017-07-31
Today I came to discover that thereās an open issue on Flexbugs about this (philipwalton/flexbugs#87). Iāve appended my findings to said issue.