Flex items treat percentage padding & margin values in vertical axis as 0, if the flex container lacks an explicit height (allowed by current spec, but perhaps not interoperable?)

REOPENED
Assigned to

Status

()

Core
Layout
REOPENED
3 years ago
a month ago

People

(Reporter: Kevin Weeks, Assigned: dholbert)

Tracking

(Blocks: 1 bug)

Trunk
x86_64
Windows 8
Points:
---
Dependency tree / graph
Bug Flags:
webcompat ?

Firefox Tracking Flags

(Not tracked)

Details

(Whiteboard: [webcompat])

Attachments

(4 attachments, 1 obsolete attachment)

(Reporter)

Description

3 years ago
User Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36

Steps to reproduce:

http://codepen.io/thetallweeks/pen/kEqwp

I created 1 flex container with 2 divs that have padding-bottom: 25%;

Then I created another flex container with 2 divs that have padding-bottom: 200px;

Lastly is an example of what should occur (using floats instead of flexbox).

I have tested this in Firefox 26, 28, and 29.


Actual results:

The % padding is ignored, while the pixel-value padding is used.


Expected results:

The divs should use a padding-bottom value equal to 25% of the width of their containers. This allows the divs to scale up or down as the window resizes while maintaining a specific aspect ratio.
Component: Untriaged → Layout
Product: Firefox → Core
Version: 29 Branch → Trunk
Created attachment 8358760 [details]
reporter's testcase
Created attachment 8358762 [details]
reduced testcase 1
Assignee: nobody → dholbert
Status: UNCONFIRMED → NEW
Ever confirmed: true
Comment on attachment 8358762 [details]
reduced testcase 1

Sorry, my "reduced testcase 1" is actually incorrect (though Chrome "passes" it).

For blocks in CSS, % padding values are always resolved against the containing block width -- but in flexbox, they're resolved against the length of the containing block's corresponding dimension (width or height).  Spec reference:
  http://dev.w3.org/csswg/css-flexbox/#item-margins

(I implemented this change in bug 851379.)

Given that the reporter's original testcase has no specified height on the flex container, it makes sense that the % vertical padding would resolve to 0 there.
Attachment #8358762 - Attachment is obsolete: true
Created attachment 8358771 [details]
testcase demonstrating this working

Here's a testcase that demonstrates how this actually works.
Created attachment 8358772 [details]
reporter's testcase, tweaked to allow the percent padding to meaningfully resolve

Here's the reporter's original testcase again, tweaked in the following ways:
 - Removed all but the top flex container (the actual thing being tested), for simplicity
 - Gave a height to the flex container, so that the percent height has something to resolve against. (which it needs for it to be meaningful, per spec link in comment 3)
 - Made the flex container "align-items: flex-start", because otherwise the flex item just stretches up to the container's height regardless of its padding.

With these tweaks, you can see the 25% padding taking effect, in Firefox. The gray "test" regions are the height of the text, plus 25% of the height of the flex container.  (In Chrome, they're much taller, because Chrome apparently doesn't honor the spec chunk quoted in comment 3.)
Resolving as INVALID because our behavior matches the spec.
Status: NEW → RESOLVED
Last Resolved: 3 years ago
Resolution: --- → INVALID
Comment on attachment 8358771 [details]
testcase demonstrating this working

>    .child {
>      padding-bottom: 50%; /* Applies to width of containing block */

(Sorry, disregard that -------^ incorrect comment in the testcase's source. That was left over from my original version of the testcase, before I remembered that percent padding in flexboxes is special.)
Created attachment 8358774 [details]
testcase showing correct expected behavior (no red should be visible)
I filed http://code.google.com/p/chromium/issues/detail?id=333533 on this, to poke the Chrome folks to fix this.
Depends on: 851379
I also filed a WebKit bug, for good measure, since this affects them, too:
 https://bugs.webkit.org/show_bug.cgi?id=126809
Duplicate of this bug: 964703
Duplicate of this bug: 977263
Duplicate of this bug: 1029463
Summary: Flexbox items do not accept percentage padding values → Flexbox items treat percentage padding values in vertical axis as 0, if the container lacks an explicit height
Duplicate of this bug: 1048933

Comment 15

3 years ago
FWIW - the chrome (bug/feature) is actually useful.  this is not.
If you're frustrated with the currently-specced behavior (as implemented by Firefox), please take it up with the W3C / CSSWG -- not by making comments on Firefox bugs.

Though your case has been made on the www-style mailing list; see:
 http://lists.w3.org/Archives/Public/www-style/2014Apr/0193.html
and other messages in that thread.

The response from spec editor is here:
 http://lists.w3.org/Archives/Public/www-style/2014May/0015.html
...which I think makes it pretty clear that the spec isn't going to change on this.
Summary: Flexbox items treat percentage padding values in vertical axis as 0, if the container lacks an explicit height → Flex items treat percentage padding & margin values in vertical axis as 0, if the flex container lacks an explicit height
Duplicate of this bug: 1091326

Comment 18

3 years ago
While Firefox does seem to implement the correct behavior, somewhat, vertical margins/paddings on flex items with explicit height still computes to zero in the latest nightly.

Also, as long as an element has any height (because of content, stretch, etc.), percentage padding/margin should be computed from that height, no? The spec doesn't say "always zero"...

Cheers!
(In reply to Bogdan Gribincea from comment #18)
> While Firefox does seem to implement the correct behavior, somewhat,
> vertical margins/paddings on flex items with explicit height still computes
> to zero in the latest nightly.

Not in e.g. this testcase:
data:text/html,<div%20style="display:flex;height:100px"><div%20style="margin-top:50%">hi

If you're really seeing this behavior, could you file a new bug (with a testcase demonstrating the problem) and CC me?
(Note that a flex item's percent margin/padding is supposed to resolve against the *flex container's* explicit size, not against the *item's* size. Maybe that's the source of confusion?)

Comment 21

3 years ago
Thank you for your reply.

I didn't find anything in the spec that mentions if the width/height taken into account is the container or the item so yes that did confuse me. Indeed it works fine with explicit height set on the container.

Another thing that confuses me about this is the following:
- a container with flex-direction: row with no explicit width set will respect horizontal percentage margins on the flex items and set it to that percentage of the container width.
- a container with flex-direction: column with no explicit height set will treat vertical percentage margins as zero on it's flex items.

Is this intentional and per spec?

Example: http://jsfiddle.net/npLzhgty/1/

Cheers,
Bogdan
In your jsfiddle, the flex container's width is effectively explicit, because it's a block-level element with "width:auto", and its parent (the body) is a block.  Its parent's block layout gives it the full available width. (That's how "width:auto" block-level elements behave in block layout.)

But you're onto something, & here's a more interesting example, where the flex container's width depends on the children (via "inline-flex"):
http://jsfiddle.net/npLzhgty/3/

In that case, we do seem to be inconsistent. With the horizontal container, we size the container based on the children's intrinsic sizes, and then we resolve the items' percent margins as a percent of the container's now-resolved width. This means the children have not-quite-enough-space and are forced to wrap. Whereas with the vertical container, we resolve the percent vertical margins to 0.

While this is inconsistent, I don't think it violates the spec -- CSS2.1 says about percent margins: "If the containing block's width depends on this element [the element with a percent margin], then the resulting layout is undefined in CSS 2.1."
 http://www.w3.org/TR/CSS2/box.html#margin-properties
We've apparently chosen (presumably for historical reasons) to define that layout such that these horizontal percent margin values do resolve against the container's computed width (after the container has been sized to its contents) -- both in block layout and in flexbox layout.

In contrast, CSS is more explicit about vertical percent-values (e.g. "height") being explicitly invalid when resolved against a container whose height depends on its children -- e.g. the "height" property says percent values are treated as "auto" if the container's height depends on this element:
 http://www.w3.org/TR/CSS2/visudet.html#propdef-height
I filed bug 1110305 on the inconsistency described in comment 22. Let's take any subsequent discussion on that topic over there.
See Also: → bug 1110305
Duplicate of this bug: 1163119
Duplicate of this bug: 1234533
For the record, the situation here with the spec has changed slightly -- the spec now allows either behavior (instead of explicitly requiring Edge & Firefox's current behavior).

That spec change was here: https://hg.csswg.org/drafts/rev/86681ff9c4e9
Link to this section in current spec draft: https://drafts.csswg.org/css-flexbox/#item-margins

(I don't think this changes the status of this bug, though, for the time being.)

Comment 27

a year ago
Hey Daniel,
thanks a lot for your feedback on this issue.
Considering the spec update, could you please elaborate on how the status of this issue still invalid?

Thank you in advance.
Flags: needinfo?(dholbert)
I suppose I'll reopen and clarify the summary.

(I'm not sure we'd take a patch to change this behavior -- our current behavior does still match the spec.  We should probably come to an agreement with other implementors and the CSSWG before / around when this behavior changes, if it changes.)
Flags: needinfo?(dholbert)
Summary: Flex items treat percentage padding & margin values in vertical axis as 0, if the flex container lacks an explicit height → Flex items treat percentage padding & margin values in vertical axis as 0, if the flex container lacks an explicit height (allowed by current spec, but perhaps not interoperable?)
Status: RESOLVED → REOPENED
Resolution: INVALID → ---

Comment 29

a year ago
Thanks Daniel, that's appreciated. So just to make sure I understand, the spec now has changed to accommodate both cases, adding:

1. their own axis (left/right percentages resolve against width, top/bottom resolve against height);
2. the inline axis (left/right/top/bottom percentages all resolve against width);

So in opposition to mislabelling as a bug, since the behaviour on Firefox clearly follows (1), wouldn't the possibility (2) then be lacking implementation in this case? — possibly adapting to the behaviour found in some other vendors?

Please forgive me if I am missing something.

Thanks again.
> wouldn't the possibility (2) then be lacking implementation in this case?

I'm not sure what you mean. Are you saying we should implement *both* behaviors? That's not what the spec is saying -- it currently allows browsers to implement *either* behavior.
> possibly adapting to the behaviour found in some other vendors?

(If this was the crux of your question: we might do that at some point, though I'm not sure, per my parenthesized comments at the end of comment 28.)

Comment 32

a year ago
Thanks Daniel,
I didn't realise it was either one of the alternative, but now that you've mentioned, it makes sense since one would nullify the other.
It's interesting how two alternatives that would result in different behaviours can be accepted isn't it?
Anyway, hopefully we will all get to an agreement in this regard soon.

Thanks for your support and all the best.

Comment 33

8 months ago
It's my first time playing around with flex and I also stumbled into this browser inconsistency.
Using padding to assume a certain aspect ratio has worked well for me for years, till I tried using it within a flexbox. FF's current implementation throws that behavior - I am and probably others are familiar with - out of the window. At this point, it also differs from both chrome's and IE's implementation, making it harder to make it work properly crossbrowser.

I hope we can see a switch from 1 to 2 mentioned in comment 29.
Blocks: 1308517

Comment 34

7 months ago
Just run into this issue and wanted to add my perspective, even if it isn't novel to this thread.  To cut to the chase, I also believe FF should implement the 2nd option in comment 29.  

My particular use case is a grid of flex items with percent-based widths, and percent-based vertical and horizontal margins to ensure that a) the rows take up the full container width and b) the vertical and horizontal gutters are the same size.  Intuitively, based on float and inline-block behavior, I believed this strategy would work for flex-items.  The margins were calculated as I expected on Chrome and IE11, but I was surprised (and ended up on this thread) when the vertical margin mysteriously collapsed in FF.  

Many thanks!
Duplicate of this bug: 1315669

Updated

a month ago

Updated

a month ago
Flags: webcompat?
Whiteboard: [webcompat]
You need to log in before you can comment on or make changes to this bug.