UPDATE: This has been addressed and updated in the latest WC3 Editor’s Draft, which you can read here.
I came across a strange issue regarding a seemingly rare use-case, while dealing with specific aspect ratios for child elements combined with new-and-shiny Flexbox support in major browsers.
Here’s the idea: we have a “grid” of list items that flow inline, are flexible, and maintain their aspect-ratio along the way. These squares should always remain squares.
Rather than simply adding and dropping columns between breakpoints, the items would flex to fit the space allocated to them while maintaining their “grid” layout as well as their proportions.
See the Pen Flexbox items with padding by John Kreitlow (@kreitlow) on CodePen.15401
Depending onÂ what browser you’re using to readÂ this, and theÂ amount of timeÂ passed since this was published, you’ll either see a nice collection of gray boxes or a blob of #debugpink in the CodePen above.
The W3C has recently been discussing the issue of percentage-based margins and paddings on flex items. TheÂ meat of the issue is that the W3C would prefer to keep Grid and Flexbox algorithms as similar as possible, to reduce confusion and make developers’ lives easier I guess.
The initial reason for the change was that Grid, as drafted and implemented by Microsoft, was the other way around. If they refuse to change Grid, and Blink refuses to change Flexbox, then we have a problem.
I’ve gone this far not explaining what the actual problem is. It’s a narrow one, and mayÂ not seem like such a smallÂ detail in the grand scheme of the Internet. The change referred to above is this line in the current Flexbox spec draft:
Percentage margins and paddings on flex items are always resolved against their respective dimensions; unlike blocks, they do not always resolve against the inline dimension of their containing block.
CSS Flexible Box Layout Module 1 [W3C Working Draft] (http://www.w3.org/TR/css-flexbox-1/#item-margins)
So if you use
padding-bottom, with a percentage value, the containing block decides whether thatÂ value resolves against the main dimensionÂ or the cross dimension.
The animation below is intended to show the relationship between containers and child elements. On Chrome 43, both left and right animations appear the same. InÂ FirefoxÂ 38.0.1, the Flexbox implementation appears to be broken, which will only display a red line on the right.
See the Pen Block vs. Flex margin and padding animation by John Kreitlow (@kreitlow) on CodePen.15401
According to the W3C and @CodingExon, Firefox is right, and Chrome is wrong:
@johnkreitlow @firefox Your 25% padding-top (1st val in “padding”) is resolving to 0, which is correct per spec. See https://t.co/LMCwib1Rp5
â€” Daniel Holbert (@CodingExon) March 19, 2014
Fantasai proposes two resolutions for this problemÂ on the blog CSS3.Info. ThoseÂ both boil down to eitherÂ resolveÂ p/m-t/b against the height or width of the containing block (i.e., pick one). There have been suggestions from others in the mailing list, proposing an
aspect-ratio property or similar, which I think would be weird (merely because it seems too ambiguous).
So, why not add a new flexbox-specific property to solve thisÂ problem?
flex-relation: main-axis | cross-axis | width | height | auto
flex-relation property allows for changingÂ theÂ dimension that percentage margins and paddings are resolved against for flex items. The property applies to the flex container and affects all flex items.
- Flex items willÂ always resolve their padding or margin size against the main dimension. For `row` and `row-reverse` flex containers, flex items resolve allÂ percentage margins and paddings against the widthÂ of the flex container. For `column` and `column-reverse` flex containers, flex items resolve allÂ percentage margins and paddings against the heightÂ of the flex container.
- Flex items willÂ always resolve their padding or margin size against the cross dimension. For `row` and `row-reverse` flex containers, flex items resolve allÂ percentage margins and paddings against the heightÂ of the flex container. For `column` and `column-reverse` flex containers, flex items resolve allÂ percentage margins and paddings against the widthÂ of the flex container.
- Flex items will resolve all percentage margins and paddings against the width of the flex container, regardless of the flex container’s direction.
- Flex items will resolve percentageÂ margins andÂ paddings against the height of the flex container, regardless of the flex container’s direction.
- auto (default)
- Flex items will resolve percentage margins and paddings against their respectiveÂ dimensions.
I feel like margins and paddings are justÂ a few potentialÂ uses of this property, and it could be expanded on for some interesting use cases.
I don’t know what the level of effort is to implement something like this, but I’d like to hear what others say about adding a new property. With
flex-relation, Browser developersÂ would be able to have different defaults for grid and flexbox if they want. Developers wouldn’t have to agree with those defaults and would have the power to adjust things to how they prefer. And my divsÂ would be nice and square.