Skip to content

[css-flexbox][css-align][css-grid] abspos flex/grid item "align-self: auto behaves as start" spec-text is too vague #440

Closed

Description

@dholbert

The css-align spec (the canonical definition for align-self) is pretty unequivocal about how to handle align-self:auto. Quoting:

The auto keyword computes to the computed value of align-items on the parent or normal if the box has no parent.
https://drafts.csswg.org/css-align/#propdef-align-self

But, the flexbox & grid specs attempt to define some special-case behavior for this auto value on absolutely-positioned elements -- and IMO they're too vague about how/where that special case behavior is supposed to be triggered, and how broadly its effects spread.

The language I'm concerned about is here in the flexbox spec:

For this purpose, a value of align-self: auto is treated identically to start.
https://drafts.csswg.org/css-flexbox-1/#abspos-items

...and here in the grid spec:

For the purpose of calculating this static position, a value of auto for align-self/justify-self behaves as start.
https://drafts.csswg.org/css-grid-1/#static-position

Superficially, the phrase "a value of" is too vague. (Is that "a specified value"? "a computed value"? something in between?) And of course, "behaves as" is vague too.

I have these specific questions/concerns:

  1. Are the flex/grid specs are trying to redefine the computed value of align-self:auto for these abspos elements? Or is align-self:auto still intended to compute the way that css-align defines it (to the parent's computed align-items) and then its computed value (e.g. center if the parent has align-items:center) should somehow produce different layout behavior than it normally would?

  2. If the intent for (1) is the latter (i.e. if auto computes away but then ends up somehow producing different results in layout), how is the different behavior intended to be triggered? Layout uses computed/used values of css properties -- so if auto gets computed away, then I don't see how layout would be able to realize that it needs to apply this special-case behavior. Maybe e.g. when auto computes to center, it's expected to really compute to a special center-which-really-came-from-auto value, which is expected to behave just like center except in this special abspos case?

  3. It's not clear to me what should happen here when an align-self:auto value is inherited to an abspos element. For example: suppose an abspos element inside of a flex container has align-self:inherit, and its parent has align-self:auto, and its grandparent has align-items:center. I'm pretty sure this abspos element should end up with a computed align-self of center, BUT: is that really center, or is it the center-which-came-from-auto scenario discussed above in (2)? (This matters for layout -- if we inherit the pure center value, the static position would be center-aligned. But if we inherit some magically tainted center-which-came-from-auto value, then the static position would be start-aligned.)

Activity

  1. fantasai commented on Sep 5, 2016

    @fantasai
    Collaborator

    On 09/03/2016 01:49 PM, Daniel Holbert wrote:

    The css-align spec (the canonical definition for |align-self|)
    is pretty unequivocal about how to handle |align-self:auto|.
    Quoting:

    The |auto| keyword computes to the computed value of
    |align-items| on the parent or |normal| if the box has no parent.
    https://drafts.csswg.org/css-align/#propdef-align-self
    

    But, the flexbox & grid specs attempt to define some special-case
    behavior for this |auto| value on absolutely-positioned elements --
    and IMO they're too vague about how/where that special case behavior
    is supposed to be triggered, and how broadly its effects spread.

    The language I'm concerned about is here in the flexbox spec:

    For this purpose, a value of |align-self: auto| is treated
    identically to |start|.
    https://drafts.csswg.org/css-flexbox-1/#abspos-items
    

    ...and here in the grid spec:

    For the purpose of calculating this static position, a value
    of |auto| for |align-self|/|justify-self| behaves as |start|.
    https://drafts.csswg.org/css-grid-1/#static-position
    

    Superficially, the phrase "a value of" is too vague. (Is that
    "a /specified/ value"? "a /computed/ value"? something in
    between?) And of course, "behaves as" is vague too.

    IIRC we had backported this behavior in Flex and Grid from Align,
    but maybe we screwed up somewhere afterwards. :/

    The intention is that absolutely-positioned items never take their
    parent's align/justify-items value because they are out-of-flow
    and are positioned, often to an indirect ancestor. Honoring the
    parent's *-items value is likely to cause confusion.

    There's two ways to deal with this:
    1.) 'auto' computes to 'normal' on the root and on abspos items,
    and to the parent's *-items value on everything else
    2.) 'auto' computes to itself always and we do the logic at
    used-value time.

    I don't think we have a strong opinion on this matter. Computing
    through means getComputedStyle() returns a more accurate value;
    otherwise it probably doesn't matter much.

    ~fantasai

  2. MatsPalmgren commented on Sep 6, 2016

    @MatsPalmgren

    Regarding fantasai's suggested solutions.

    I think 1) has the same performance problems as we reported here:
    https://lists.w3.org/Archives/Public/www-style/2015Sep/0099.html
    That is, the computed value for 'align-self' would depend on
    its own computed values of 'position', 'display' etc.

    1. would change the meaning of 'inherit', e.g.:
    <A style="justify-items:left">
      <B style="justify-items:right">
        <C style="justify-self:inherit">
    
    

    Currently, this is equivalent to:

    <A style="justify-items:left">
      <B style="justify-items:right; justify-self:left">
        <C style="justify-self:left">
    
    

    With 2) we would instead get the computed values:

    <A style="justify-items:left">
      <B style="justify-items:right; justify-self:auto">
        <C style="justify-self:auto">
    
    

    B would have the used value 'left'.
    C would have the used value 'right'.

    It seems wrong that B and C ends up having different used values
    when the author explicitly specified that C should have the same
    justify-self value as B.

    I think this solution might work better:
    Store an "original-value-was-auto" flag to remember if the value
    was 'auto' before it was replaced with its parent's justify-items.

    Grid/Flexbox can then use this flag to indicate 'start' for the static
    position (and it's only used for that purpose).

    I think this would be easy to implement in Gecko (it's similar to
    how we retain the original 'display' value for the purposes of
    calculating the static position [1]).

    [1]
    https://drafts.csswg.org/css21/visudet.html#abs-non-replaced-width
    "... this hypothetical calculation might require also assuming
    a different computed value for 'display'."

  3. fantasai commented on Sep 13, 2016

    @fantasai
    Collaborator

    I have no opinion on this issue... up to the council of implementers and @dbaron . :)

  4. dholbert commented on Sep 16, 2016

    @dholbert
    MemberAuthor

    Looks like this was discussed at https://lists.w3.org/Archives/Public/www-style/2016Sep/0041.html

    It was resolved as "RESOLVED: Don't have the computed value dependency", pending any objections.

    I think I'm on-board with that, but @fantasai, could you clarify what that means? Is the plan for auto to just always compute to itself now? (and get treated in a context-specific way, depending on flex vs. grid vs. abspos etc.)

  5. fantasai commented on Sep 20, 2016

    @fantasai
    Collaborator

    Yes, I believe that is the intent. :)

  6. dholbert commented on Sep 20, 2016

    @dholbert
    MemberAuthor

    OK -- that sounds good to me, I think. Thanks!

  7. added a commit that references this issue on Sep 20, 2016
    30e67ca
  8. 26 remaining items

  9. dholbert commented on Jun 2, 2017

    @dholbert
    MemberAuthor

    Looks good to me too - thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions