Skip to content

[css-position-3] Absolute positioning - Is the new inset & auto-size behaviour web-compatible? #11195

Closed

Description

@dshin-moz

Implementing justify-self & align-self for abs-positioned elements, we ran into:

Which has something to the effect of:

<!DOCTYPE html>
<style>
.abs {
  position: absolute;
  align-self: stretch;
  height: auto;
  top: auto;
  bottom: auto;
  background: lime;
}
</style>
<div class="abs">Test</div>

align-self: stretch should be a no-op (At least for absolute elements not within flex/grid context) in the old behaviour, but seems to be used by websites in the wild anyway in the linked bugs:

  • Virustotal: <uno-navbar>'s shadow-root child
  • SAP: opblock-summary-method

As per the new absolute-positioning steps:

  1. Calculate inset-modified containing block:
  2. Resolving sizes: Definite available size is viewport, no min/max height is given, and since self-alignment is stretch, auto size is stretch size.
  3. Auto margins: N/A
  4. Alignment: Fits exactly in the available space

As per the old steps

  1. Everything is auto, margins zeroed out, top takes its static position value, which is zero
  2. Height is Auto heights for block formatting context roots - Distance between top of the topmost line box and bottom of the bottommost line box, so auto size is basically a shrink-fit size.
  3. Solve for bottom, taking up whatever empty space

Activity

  1. emilio commented on Nov 13, 2024

    @emilio
    Collaborator

    @dshin-moz you're probably missing a position: absolute in your test-case as well, right?

    cc @fantasai @tabatkins

  2. dshin-moz commented on Nov 13, 2024

    @dshin-moz
    ContributorAuthor

    Fixed. Thanks!

  3. Loirooriol commented on Nov 13, 2024

    @Loirooriol
    Contributor

    Better add some background to the testcase to be able to see the size.
    2 broken sites found in 6 days is not looking very good... Why are they using stretch if they don't want to stretch 🤦

  4. Loirooriol commented on Nov 14, 2024

    @Loirooriol
    Contributor

    Actually, the default is align-self: auto, which behaves as normal, which behaves as stretch.

    So this means that you should get this behavior even without align-self: stretch, which is obviously wrong.

  5. dshin-moz commented on Nov 14, 2024

    @dshin-moz
    ContributorAuthor

    You're right that align-self: auto -> normal, but then:

    Or if it is normal [...] has no auto inset in the relevant axis
    Its automatic size is its stretch-fit size.

    So given that the testcase has auto insets, it ends up being content-fit size, I think

    EDIT: Ah, I see you've filed #11215 regarding that.

  6. moved this to FTF agenda items in CSSWG January 2025 meetingon Jan 22, 2025
  7. moved this from FTF agenda items to Regular agenda items in CSSWG January 2025 meetingon Jan 22, 2025
  8. bfgeek commented on Apr 3, 2025

    @bfgeek

    So FWIW chrome didn't change static-pos'd abspos for this reason. We had a look at it, and determined that it wasn't web-compatible (sorry we should have filed an issue at that time).

  9. Loirooriol commented on Apr 15, 2025

    @Loirooriol
    Contributor

    Yeah, in Servo we tried a few testcases on major browsers, and came to the conclusion that the automatic size of an abspos needs to be fit-content when one or both insets are auto, even if the self-alignment property is stretch.
    https://github.com/servo/servo/blob/da4ea0f0965414733f0352e76ff416b1ded75a08/components/layout_2020/positioned.rs#L821,L829

    Authors can still use height: stretch if they really want to stretch.

  10. Loirooriol commented on Apr 15, 2025

    @Loirooriol
    Contributor

    Actually, it has already been fixed in the spec (#11902): https://drafts.csswg.org/css-position-3/#abspos-auto-size

    The automatic size of an absolutely positioned box is resolved against its inset-modified containing block as follows:

    If its self-alignment property in the relevant axis is stretch and neither of its inset properties nor margins in that axis are auto

    Or if it is normal and the box is non-replaced, not a table wrapper box, and has no auto inset in the relevant axis

    Its automatic size is its stretch-fit size.

    Otherwise

    Its automatic size is its fit-content size.

    Well, the "nor margins in that axis are auto" is wrong: browsers still allow stretching.

  11. 15 remaining items

  12. fantasai commented on May 14, 2025

    @fantasai
    Collaborator

    If neither stretch alignment nor auto margins force a fit-content size, then neither alignment effect will be observable.

    This is not true. The box may have a non-stretch-fit size, in which case alignment is observable.

  13. css-meeting-bot commented on May 14, 2025

    @css-meeting-bot
    Member

    The CSS Working Group just discussed [css-position-3] Absolute positioning - Is the new inset & auto-size behaviour web-compatible?, and agreed to the following:

    • RESOLVED: change stretch alignment case to allow the size to stretch when the normal alignment case allows stretching
    The full IRC log of that discussion <emilio> oriol: this was discussed a few weeks ago and I couldn't attend
    <emilio> ... not sure if the consequences of the resolution were fully understood
    <miriam> present
    <emilio> ... the implication is that you can have an abspos with auto margins that if it has normal alignment it'd stretch, but if you change self-alignment to be stretch, then it will stop stretching
    <emilio> ... I think that doesn't really make sense and would just cause confusion
    <emilio> ... in flex and grid auto margins don't stretch even if they have stretch alignment
    <emilio> ... but this happens both for stretch and normal alignment
    <emilio> ... so I think it's better to have abspos be consistent
    <emilio> ... and avoid having the align-self: stretch align with flex / grid
    <emilio> ... also the argument for making consistent with flex/grid feels weak
    <emilio> ... in block layout auto margins don't prevent block level items
    <emilio> ... from stretching
    <emilio> ... so I'd like to change the previous resolution
    <emilio> ... so that if they stretch with normal alignment they also stretch with stretch alignment
    <emilio> fantasai: whichever way we go we are going to introduce inconsistencies
    <emilio> ... in terms of alignment I think being consistent with flex/grid is more important because that's what authors are used to
    <emilio> ... in block layout only blink has implemented and it's very recent so we can probably change it
    <emilio> ... for normal we're stuck with css2, but for the other keywords it'd introduce inconsistencies
    <emilio> ... are you proposing that auto margins are stronger than centering in flex/grid but not abspos? That seems like a bad idea
    <emilio> ... I think maybe changing stretch only is better than the current situation, I admit it's quite weird that stretch is less stretchy than normal
    <fantasai> s/I think//
    <emilio> oriol: not sure the right way to look at this is props winning over other
    <emilio> ... the way i see it is both margin and alignment have some effect simultaneously
    <emilio> ... e.g. both may affect the auto size to be fit-content
    <emilio> ... also auto-margins work by changing the margin box and alignment works in terms of that box
    <emilio> ... so if you have auto margins that fills the whole container alignment won't do anything, but it's not like it is disabled
    <emilio> ... it's more like it doesn't matter which value you use
    <emilio> ... whether we decide that self-alignment forces auto size to be fit-content or auto margins do that I think it's independent decisions
    <emilio> ... and it's not like some values win and they don't
    <emilio> s/they/don't
    <emilio> s/they/some
    <emilio> ... e.g. even tho in flex and grid auto margins prevent stretching
    <emilio> ... then center alignment could prevent stretching even with a 0 margin
    <emilio> ... so we could say that center alignment is "winning" over the 0 margin
    <emilio> ... so what wins and loses can be subjective
    <emilio> ... I prefer seeing it as different things applying simultaneously
    <emilio> fantasai: so iiuc, if you have auto margins and stretch, the first thing you do is stretch
    <emilio> ... then auto margins end up having no effect (unless max-size is involved)
    <emilio> oriol: exactly
    <emilio> ... so in this case for abspos neither auto margins nor stretch alignment force fit-content size (so it can stretch)
    <emilio> ... typically alignments won't matter because auto margins will resolve to 0 and then alignment would do nothing
    <emilio> ... but if you have a max-size then you can align stuff using the alignment properties
    <emilio> fantasai: I think that makes sense. There's a weird clause about negative and auto in this case, need to go back and check, but should be fine
    <emilio> astearns: so prev resolution is no change to the spec, what should the spec say
    <emilio> oriol: a way to word could be "change stretch alignment case to allow the size to stretch when the normal alignment case allows stretching"
    <emilio> astearns: makes sense, wdyt fantasai?
    <emilio> fantasai: yeah
    <emilio> +1
    <emilio> RESOLVED: change stretch alignment case to allow the size to stretch when the normal alignment case allows stretching
  14. bfgeek commented on May 14, 2025

    @bfgeek

    @fantasai @Loirooriol - Is it correct under the above resolution, tables should have the old behaviour? E.g.

    https://www.software.hixie.ch/utilities/js/live-dom-viewer/?saved=13785

    <!DOCTYPE html>
    <style>
    .cb {
      width: 100px;
      height: 100px;
      display: inline-block;
      position: relative;
      border: solid 3px;
    }
    table {
      position: absolute;
      min-width: 20px;
      min-height: 20px;
      background: lime;
      margin: auto;
      inset: 0;
    }
    </style>
    <div class="cb">
      <table style="align-self: normal; justify-self: normal;"></table>
    </div>
    <div class="cb">
      <table style="align-self: stretch; justify-self: stretch;"></table>
    </div>
    
  15. Loirooriol commented on May 14, 2025

    @Loirooriol
    Contributor

    Oh, yeah, I failed to consider tables and replaced elements when summarizing the proposed resolution, but I guess they should be covered too.

    So basically https://drafts.csswg.org/css-position/#abspos-auto-size should be changed as follows:

    The automatic size of an absolutely positioned box is resolved against its inset-modified containing block as follows:

    If its self-alignment property in the relevant axis is stretch and neither of its inset properties nor margins in that axis are auto

    Or if it is normal and the box is non-replaced, not a table wrapper box, and has no auto inset in the relevant axis

    Its automatic size is its stretch-fit size.

    Otherwise

    Its automatic size is its fit-content size.

  16. bfgeek commented on May 14, 2025

    @bfgeek

    Sounds good. Tables stretching is this case is more consistent IMO.

  17. tabatkins commented on Jan 30, 2026

    @tabatkins
    Member

    Thanks, updated the draft.

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions