Closed Bug 874718 Opened 11 years ago Closed 8 years ago

Adapt to updated spec language for calculating static position of absolutely positioned children of a flex container (& don't let them interfere with non-abspos flex items' positioning)

Categories

(Core :: Layout, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED

People

(Reporter: dholbert, Assigned: dholbert)

References

(Blocks 1 open bug, )

Details

As implied by bug 874713, we don't have the correct logic for calculating the static position of flex items in some cases.

I believe our current logic is from an older version of the spec, which stated that placeholders get wrapped in anonymous flex items (like raw text).

The current spec-behavior is defined as follows:
##########
An absolutely-positioned child element of a flex container does not participate in flex layout beyond the reordering step. However, if both ‘left’ and ‘right’ or both ‘top’ and ‘bottom’ are ‘auto’, then the used value of those properties are computed from its static position, as follows:

If both ‘left’ and ‘right’ are ‘auto’, the absolutely-positioned child must be positioned so that its main-start or cross-start edge (whichever is in the horizontal axis) is aligned with the static position. If both ‘top’ and ‘bottom’ are ‘auto’, the absolutely-positioned child must be positioned so that its main-start or cross-start edge (whichever is in the vertical axis) is aligned with the static position.

In the main axis,

  1.    If the flex container does not contain any flex items, the static position is determined by the value of ‘justify-content’ on the flex container as if the static position were represented by a single zero-sized flex item.
  2.    If there is no preceding flex item or the preceding flex item and the subsequent flex item are on the same flex line, the static position is the outer main-start edge of that flex item.
  3.    Otherwise, if there is a preceding flex item, the static position is the outer main-end edge of that flex item. 

In the cross axis,

  1.    If there is a preceding flex item, the static position is the cross-start edge of the flex-line that item is in.
  2.    Otherwise, the static position is the cross-start edge of the first flex line. 
##########
http://dev.w3.org/csswg/css-flexbox/#abspos-items
Note that the spec currently says in the "Status of this Document" section:
>  The following features are at-risk:
>    Calculation of the static position of absolutely-positioned flex items.
  http://www.w3.org/TR/css3-flexbox/#status
  http://dev.w3.org/csswg/css-flexbox/#status

(I'm not sure, but I seem to recall that being the reason why I initially held off on implementing this change, when the spec switched to its current behavior.  And then I must've just forgotten about it.)

I'll email www-style to double-check whether this chunk of the spec is still at-risk or not.
Blocks: 874713
My email to www-style: http://lists.w3.org/Archives/Public/www-style/2013May/0512.html
fantasai's response: http://lists.w3.org/Archives/Public/www-style/2013May/0514.html

She suggests holding off on this (or at least, prioritizing other bugs higher), since the spec might end up changing.
The spec (ED-130911) now says: 

#####
4.1 Absolutely-Positioned Flex Children

An absolutely-positioned child element of a flex container does not participate in flex layout beyond the reordering step.

Its static position is calculated by first doing full flex layout without the absolutely-positioned elements, then positioning each absolutely-positioned child as if it were the sole flex item in the flex container, assuming it was a fixed size box of its used size.

For example, by default, the static position of absolutely positioned elements is in the main-start/column-start corner, corresponding to the default values of justify-self and align-self. Setting justify-self:center, however, would center it in the main axis. 
#####

TR has not been updated.
(In reply to Daniel Holbert [:dholbert] from comment #0)
> I believe our current logic is from an older version of the spec, which
> stated that placeholders get wrapped in anonymous flex items (like raw text).

For the record, the old spec-text that our implementation matches on this is:
 http://www.w3.org/TR/2012/WD-css3-flexbox-20120612/#abspos-flex-items
(I'm unclear on a few things in the new spec text. Awaiting clarification; re-posted here:
 http://lists.w3.org/Archives/Public/www-style/2014Jan/0025.html )
(Tab replied:
 http://lists.w3.org/Archives/Public/www-style/2014Jan/0146.html
Hoping to fix this soon.)
Assignee: nobody → dholbert
Status: NEW → ASSIGNED
Summary: static position of abspos flex items are calculated incorrectly in some cases → Adapt to updated spec language for calculating static position of absolutely positioned children of a flex container
Blocks: 1009214
See Also: → 619476
I notice equivalent issues with position:fixed
See Also: 619476
Blocks: 1097184
Blocks: 1124772
I think the CSSWG is considering changing the specced behavior here again, though I'm not yet sure what the new behavior would be.
References:
 Greg's post: https://lists.w3.org/Archives/Public/www-style/2015Feb/0411.html
 CSSWG minutes 2/25: https://lists.w3.org/Archives/Public/www-style/2015Feb/0504.html (2nd section)
Actually, it sounds like the upshot there is that they're hoping to stick with the currently-specced (only-implemented-in-IE-so-far) behavior.
Depends on: 1174406
Blocks: 1224421
No longer blocks: 1224421
No longer blocks: 1009214
This bug's fix will layer on top of mats' work to implement similar abspos behavior for grid items, in bug 1151243. Adding dependency.
Depends on: 1151243
Summary: Adapt to updated spec language for calculating static position of absolutely positioned children of a flex container → Adapt to updated spec language for calculating static position of absolutely positioned children of a flex container (& don't let them interfere with non-abspos flex items' positioning)
Blocks: 1248402
Depends on: 1269045
Depends on: 1269046
I spun off two helper bugs, to fix this bug in two parts. Basically:
 - bug 1269045 covers safely removing the old special-case code for abspos flex children (and leaving us in a consistent state with abspos children no longer spawning anonymous flex items).
 - bug 1269046 covers adding new code for computing the static position of abspos flex children, based on the css alignment properties that flexbox respects.

See the bugs for more details.  I intend to land their patches at the same time, so that we'll atomically go from old-spec-behavior to current-spec-behavior -- but from a review/testing/implementation perspective, it's useful for me to separate the two steps logically. (Hence the two bugs.)
I've come across a discrepancy in how absolutely positioned elements within flex containers are handled. 

There's a reduced test case in this codepen: http://codepen.io/jodi/pen/oLvZea

The correct (or at least, desired) behaviour is observed in Chrome and IE11. The absolutely positioned elements have top and bottom implicitly set to auto.

I sit next to :kingstonTime and he recommended filing it here.
Yup, that's a version of this bug. Our behavior on that bug is from the older spec text (i.e. we're vertically centering a 0-sized placeholder, basically); and you'll get the desired behavior (purple thing actually centered) when the helper-bugs mentioned in comment 23 are fixed.
It seems chrome will be releasing this for Chrome 52.
https://medium.com/dev-channel/flexbox-gets-new-behavior-for-absolute-positioned-children-ca73b59f2063

> The latest version of the spec takes them 
> fully out of flow and sets the static position 
> based on align and justify properties. 
> At the time of this writing, Edge and Opera 39 
> for desktop and Android already support this.


http://codepen.io/webcompat/full/LkAxok/
Firefox on left, Opera Blink on right.
http://imgur.com/a/QAFCm
This is now FIXED by bug 1269045 & bug 1269046, per comment 23.

SIDE NOTE: some of the testcases mentioned here (comment 25, and the medium post in comment 27) assume that "align-items: center" on a flex container will influence the positioning of its abspos children. This is what happens in Chrome & Edge, but the latest spec text says that it should *not* influence that positioning. See https://github.com/w3c/csswg-drafts/issues/440#issuecomment-244791183 ("The intention is that absolutely-positioned items never take their parent's align/justify-items value").

I've filed bugs on Chrome & Edge for non-compliance with the spec on this point:
 https://bugs.chromium.org/p/chromium/issues/detail?id=661662
 https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/9637906/

If it turns out that web compatibility requires us to implement their behavior & the spec to change, then we can do that in a followup bug.
Status: ASSIGNED → RESOLVED
Closed: 8 years ago
Resolution: --- → FIXED
No longer blocks: 1097184
No longer blocks: 874713
Closing the loop on one thing here:

(In reply to Daniel Holbert [:dholbert] from comment #29)
> SIDE NOTE: some of the testcases mentioned here (comment 25, and the medium
> post in comment 27) assume that "align-items: center" on a flex container
> will influence the positioning of its abspos children. This is what happens
> in Chrome & Edge, but the latest spec text says that it should *not*
> influence that positioning. [...]
> 
> I've filed bugs on Chrome & Edge for non-compliance with the spec on this
> point

The spec ended up changing to align with what Chrome and Edge were doing here, and I updated our implementation in bug 1340309 for that spec change.
One more "close the loop" item here -- I just noticed we've still got a reftest marked as "fails" due to this bug:
https://dxr.mozilla.org/mozilla-central/source/layout/reftests/flexbox/reftest.list#75

This reftest was from bug 877890 comment 5, and it was verifying that abspos flex children get painted in order of their "order" property (as the spec used to require).  (And at that point in time, we failed to reorder them because their placeholders were getting wrapped in anonymous flex items, and those anonymous flex items didn't have "order" set.)

Anyway -- the spec has changed since then, and now we're *not* supposed to care about "order" on these elements anymore (and indeed we don't).  So the test is requiring the wrong behavior (which is why it still "fails"), and we should just remove it. I'll push a late-breaking followup to do that.
Blocks: 1431856
(In reply to Daniel Holbert [:dholbert] from comment #32)
> So the
> test is requiring the wrong behavior (which is why it still "fails"), and we
> should just remove it. I'll push a late-breaking followup to do that.

Nah, I changed my mind... probably better to morph the test into something with correct expectations (that "order" is ignored for abspos flex children).  That's not trivial enough to do in a followup at this point, so I spun it off as bug 1431856.
You need to log in before you can comment on or make changes to this bug.