Skip to content

[css-align-3][css-flexbox-1] How to determine the last baseline of a flex container with different alignment groups. #7641

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
bfgeek opened this issue Aug 23, 2022 · 15 comments

Comments

@bfgeek
Copy link

bfgeek commented Aug 23, 2022

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

<!DOCTYPE html>
<div style="display: inline-flex; align-items: last baseline;">
  <div style="background: lime; font-size: 30px;">line1<br>line2</div>
  <div style="display: flex;">
    <div style="font-size: 30px; align-self: last baseline; background: cyan;">line1<br>line2<br>line3</div> 
    <div style="font-size: 80px; align-self: baseline; background: hotpink;">line1<br>line2</div> 
  </div>
</div>

https://drafts.csswg.org/css-flexbox-1/#flex-baselines

Should the last baseline of the "lime" box be aligned with the last-baseline of the "cyan" box, or the "hotpink" box?

The rules just look at if something "participates in baseline alignment" so by that rule it should be the "hotpink" box.
But likely should be the "cyan" box.

@bfgeek bfgeek added css-align-3 Current Work css-flexbox-1 Current Work labels Aug 23, 2022
@tabatkins
Copy link
Member

Yeah, I think this is just a bit of behavior that slipped thru the edits when we upgraded from "baseline" to "first/last baseline". I suspect we should prefer taking from the last-baseline element when determining the inner flexbox's last baseline, and mutatis mutandis for the first.

This does mean that the last baseline can potentially be higher than the first baseline, tho (say, both items are single-line, and the last-baseline one has a smaller font-size). Is that ok?

@bfgeek
Copy link
Author

bfgeek commented Aug 23, 2022

Is that ok?

I think its ok - but reserve the right to complain later if it isn't. :)

@tabatkins
Copy link
Member

Okay, so suggested edits are to modify Step 1 of https://drafts.csswg.org/css-flexbox-1/#flex-baselines to first look at items with the same baseline alignment preference as the requested baseline, falling back to any baseline-aligned item if there aren't any matching.

@bfgeek
Copy link
Author

bfgeek commented Aug 24, 2022

I think I have a slight preference for look at items which match the baseline alignment preference - then fallback to any item.

Otherwise we have three(!) levels of fallback - e.g.

  1. Baseline alignment preference.
  2. Any baseline alignment.
  3. Any.
    vs.
  4. Baseline alignment preference.
  5. Any.

The two stage fallback would be web compatible with what we have today.

@fantasai
Copy link
Collaborator

@bfgeek Supposing we want to last-baseline align a table or grid, and it has first-baseline aligned content in its last row... I can see the argument going either way wrt falling back three levels or two. Consider the case of having what are, essentially, one-line items first-baseline aligned to each other but the first item is a replaced element; wouldn't we rather take the real baseline than the synthesized one from the replaced item?

@bfgeek
Copy link
Author

bfgeek commented Aug 29, 2022

Consider the case of having what are, essentially, one-line items first-baseline aligned to each other but the first item is a replaced element; wouldn't we rather take the real baseline than the synthesized one from the replaced item?

For this case it wouldn't really matter though as currently spec'd we'd take the last-baseline from the last item?

@bfgeek
Copy link
Author

bfgeek commented Aug 29, 2022

The general problem that I think you are hinting at already exists without replaced elements, e.g.

<div style="display: flex; align-items: last baseline;">
  <div>baseline</div>
  <div style="display: flex; align-items: baseline;">
    <div>line1<br>line2<br>line3</div>
    <div>baseline</div>
  </div>
</div>

(FF rendering is badly wrong here) but here "baseline" "line1" "baseline" would all be aligned.

@fantasai
Copy link
Collaborator

While it's clear we didn't think through the case of having both first- and last-baseline-aligned items in the flex line, IIRC it was pretty intentional that if only one of them existed we took that shared baseline.

i.e. in

If any of the flex items on the flex container’s startmost/endmost flex line participate in baseline alignment, the flex container’s first/last main-axis baseline set is generated from the shared alignment baseline of those flex items.

The fact that we wrote “participate in baseline alignment” and not “participate in first/last baseline alignment” was, insofar as I can remember, intentional.

This implies that, for consistency, the mixed case should be resolved with 3-way fallback (desired baseline alignment, any baseline alignment, then just grab the baselines from an arbitrary non-aligned element).

@tabatkins
Copy link
Member

(Not to say we can't dispute that and go with something simpler; this was just the intention when we wrote it originally.)

@bfgeek
Copy link
Author

bfgeek commented Aug 30, 2022

This is an advantage of how the its specified in tables - in that you end up picking the lowest vs. the "first/last" item (look at all items - pick the lowest baseline).

@css-meeting-bot
Copy link
Member

css-meeting-bot commented Sep 15, 2022

The CSS Working Group just discussed How to determine the last baseline of a flex container with different alignment groups., and agreed to the following:

  • RESOLVED: when taking the baseline of a row of item, we check a shared first baseline, then a shared last baseline, then the first baseline of the first item
  • RESOLVED: (and vice-versa for the last baseline)
The full IRC log of that discussion <Rossen_> Topic: How to determine the last baseline of a flex container with different alignment groups.
<Rossen_> github: https://github.com//issues/7660
<fremy> iank_: blink would like to implement last-baseline alignment
<fremy> iank_: (by blink I mean me)
<fremy> iank_: but how do we find out what is the last baseline is a question
<fremy> iank_: currently, anything that uses a baseline alignment should be counted in
<fremy> iank_: if none are, you fallback
<fremy> iank_: there are groups however
<fremy> iank_: some might be first-baseline aligned, some might be last-baseline aglined, etc...
<fremy> iank_: how do you choose? it's the question
<fremy> iank_: maybe TabAtkins can elaborate
<fremy> TabAtkins: I'm projecting the example on the screen
<fremy> fantasai: if we consider a flex container with multiple elements with baseline alignment
<fremy> fantasai: we want the baseline of these elements
<fremy> fantasai: but if you have last-baseline alignment only
<Rossen_> q?
<fremy> fantasai: should that count as the first baseline of that group?
<fremy> fantasai: or should we bail out?
<fremy> fantasai: and if you have both types of alignment in the first row
<fremy> fantasai: these might not align with each other
<fremy> fantasai: how do you pick in that case?
<fremy> dbaron: I would like to propose something
<dholbert> FWIW firefox's rendering changes when I inspect in devtools, so we've clearly got a bug here :)
<fremy> dbaron: maybe the solution is that if you look for a first baseline, first-baseline-aligned things should be used first
<fremy> dbaron: and vice versa for last baseline
<fremy> iank_: yes, I think most people agree with that
<Rossen_> ack dbaron
<fremy> iank_: an issue is what you do next
<fremy> fantasai: if a page has a navigation bar
<fremy> fantasai: and it's last-baseline aligned
<heycam> q+
<fremy> fantasai: if most items have one line, but one has two
<fremy> fantasai: if I align something with this, what behavior do we want?
<fremy> fantasai: we can either use the last-baseline that every item aligns to
<fremy> fantasai: or the first baseline of each of these items
<fremy> fantasai: I would posit that the shared baseline is a better guess for what the author might want
<fremy> iank_: to repeat that
<fremy> iank_: if we are trying to find the last baseline
<dbaron> I think what fantasai said seems reasonable as long as when there are *two* shared baselines, we pick the one being exported.
<chrishtr> Note: discussion not recorded to issue 7387 yet..
<fremy> iank_: we would pick the first baseline as the last baseline if that's all we got
<fremy> iank_: and if we don't even have that, then we fallback to the last baseline of the bottom item
<dholbert> q+
<fremy> fantasai: yes
<fremy> iank_: reasonable
<fremy> heycam: would not exporting a baseline be reasonaoble?
<fremy> fantasai: we will always do that
<Rossen_> ack heycam
<fremy> fantasai: but right now we synthetize one
<fremy> fantasai: that is rarely desirable
<fremy> heycam: isn't that enough?
<fremy> fantasai: it's better to use the other baseline, for the author
<fremy> iank_: the final fallback could be the first or last item
<fremy> iank_: I agree that the middle step is ok
<fremy> dholbert: I'm not sure we don't always the fallback
<dbaron> github: https://github.com//issues/7641
<fremy> dholbert: I'm worried that we could get a weird telescope effect
<heycam> s/telescope/stair-step/
<fremy> dholbert: things will be lined up
<fremy> dholbert: but in opposite directions
<fremy> dholbert: which might not look good, actually
<fremy> dholbert: the synthetic is at least "logical"
<fremy> fantasai: iank_ proposed to use the lower last baseline and the hightest first baseline etc...
<fremy> fantasai: but if you have five items that are 1, 2 or 3 lines tall; whether or not your item is at the top or the bottom, it won't look very reasonaoble
<fremy> fantasai: if you align with the shared baseline, the alignment will look reasonable I think
<fremy> dholbert: but if you are looking for a first baseline and there is none
<Rossen_> q?
<fremy> dholbert: I don't understand why the special handling is gonna make things substantially better
<fremy> fantasai: if you are aligning one line of text, it's more sensible
<Rossen_> ack dbaron
<Rossen_> ack dholbert
<fantasai> if you're asking for baseline alignment, you want to align to text, not to fall back to a box edge, if possible
<fremy> iank_: my comment is that if you are trying to find the last baseline, you could get the lowest in the first row
<fremy> iank_: this is kinda how tables work
<fremy> iank_: but the two solutions I most like
<fremy> iank_: is either use the first baseline item then use the fallback
<fremy> iank_: or fantasai's solution where there is a middle step
<fremy> iank_: both solutions look reasonable
<fremy> Rossen_: and if you had to pick?
<fremy> iank_: no strong opinion
<fremy> iank_: the first one is a bit simpler to implement because its has two levels only
<fremy> fantasai: if we are looking into multi-rows grid to align
<fremy> fantasai: if you don't have the middle step, you will get worse results
<florian> q+
<fremy> fantasai: because fewer things will align with each other
<dholbert> q+
<Rossen_> ack florian
<fremy> florian: flex items contain text
<fremy> florian: so it makes sense for them to have both
<fremy> florian: but the container only has one line
<dholbert> no, flex containers can have last-baseline as well as first-baseline aligned items
<dholbert> and can export both
<dholbert> (I think)
<fremy> florian: so I can't think of of any other relevant baseline is than the shared baseline
<fremy> iank_: you can look into it in two ways
<fremy> iank_: the question is that the fallback approach
<fremy> fantasai: in the issue, iank_ suggested also to look for the lowest or highest across all items
<fremy> fantasai: this would give even better results
<fremy> iank_: yes, this is another option I would accept
<fremy> iank_: I'm just worried a bit about the compat risk
<Rossen_> ack dholbert
<fremy> dholbert: when finding the first/last baseline, would what you described be the canonical algorithm?
<fremy> iank_: yes
<fremy> dholbert: then I would worry about compat too, I think
<fremy> dholbert: for the grid case, I agree that in most cases what fantasai proposes makes more sense
<fremy> dholbert: but when you have one flexbox with one item, which is a common case, which would be confusing I think
<fremy> dholbert: we could find the baseline of that first item
<fremy> iank_: it's an edge case
<fremy> iank_: you can get the correct behavior by doing nothing
<fremy> iank_: so, why would you do it if that's not what you want?
<fremy> iank_: I'm thus not very concerned
<Rossen_> ack dbaron
<fremy> dbaron: after listening to fantasai's explanation, I'm reasonably convinced that we want the fallback levels
<fremy> dbaron: because some things might need to be changed later in the design
<fremy> dbaron: otherwise, if you change things in one place, you have to change consistently, which might be difficult
<fremy> dbaron: the middle step enables to change only locally, and get things to work anyway
<fremy> iank_: seems like most people are aligning with fantasai's solution
<fremy> iank_: anyone would object to that?
<fremy> Rossen_: sounds like you will have to do the more complex implementation :)
<fremy> iank_: yes...
<fremy> Rossen_: ok, any objection?
<fremy> fantasai: proposed resolution: when taking the baseline of a row of item, we check a shared first baseline, then a shared last baseline, then the first baseline of the first item
<florian> +1
<fremy> fantasai: (everywhere we can get away with it without compat issues)
<dbaron> s/taking the baseline of a row of item/taking the first baseline of a row of items/
<fremy> iank_: the only additional warning is that you can have a first-baseline aligned thing in the first-baseline group, but that seems fine
<dbaron> (and vice-versa for the last baseline)
<fremy> Rossen_: ok, no objection,
<fremy> RESOLVED: when taking the baseline of a row of item, we check a shared first baseline, then a shared last baseline, then the first baseline of the first item

@fantasai
Copy link
Collaborator

The resolution got recorded as we finally take the first baseline of the first item, but we also had discussed taking the highest first baseline... is the resolution recorded correctly, or did we actually prefer @bfgeek's suggestion to take the highest one? Ian, do you happen to remember?

@bfgeek
Copy link
Author

bfgeek commented Oct 26, 2022

I believe we take the "highest" one - at least I remember we had a conversation about the "overflow:scroll;flex-direction:column-reverse;" case and thought the clamping to the top in that case was likely acceptable.

E.g. view https://www.software.hixie.ch/utilities/js/live-dom-viewer/?saved=10927 on chrome canary.

(This is also what I added as tests relatively soon after this discussion).

Ian

fantasai added a commit to fantasai/csswg-drafts that referenced this issue Jan 20, 2023
…inding algo w3c#7655 w3c#7641

* RESOLVED: When taking the baseline of a row of items,
  we check a shared first baseline, then a shared last baseline,
  then the first baseline of the first item.
  (And vice versa for last baselines.)

* RESOLVED: Rowspanning cells participate only
  in first baseline alignment of their first row,
  and last baseline alignment in the last row.

* RESOLVED: Table baselines match grid, per details above.
@fantasai
Copy link
Collaborator

@tabatkins and I have drawn up a PR for this at #8341

We'd like to get confirmation from the WG on a few points, and also wanted to ask @bfgeek for review. :)

fantasai added a commit to fantasai/csswg-drafts that referenced this issue Mar 3, 2023
…inding algo w3c#7655 w3c#7641

* RESOLVED: When taking the baseline of a row of items,
  we check a shared first baseline, then a shared last baseline,
  then the first baseline of the first item.
  (And vice versa for last baselines.)

* RESOLVED: Rowspanning cells participate only
  in first baseline alignment of their first row,
  and last baseline alignment in the last row.

* RESOLVED: Table baselines match grid, per details above.
@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-align-3][css-flexbox-1] How to determine the last baseline of a flex container with different alignment groups..

The full IRC log of that discussion <TabAtkins> Rossen_: Should we consdier this issue resolved by the PR discussion?
<TabAtkins> fantasai: yeah
<TabAtkins> iank_: clarification - are we still taking the first baseline from the topmost row and bottommost row?
<TabAtkins> fantasai: yeah?
<TabAtkins> iank_: One subtlety with last issue around reverse flex
<TabAtkins> iank_: what would be the beahvior with a reverse flex?
<iank_> https://www.software.hixie.ch/utilities/js/live-dom-viewer/?saved=11393
<TabAtkins> fantasai: Not sure, let me see if the spec handles that right now, if not we should resolve to handle it
<TabAtkins> iank_: I think I have relatively strong beahvior on this, I think our new behavior makes sense
<TabAtkins> fantasai: We took the startmost or endmost flex line
<TabAtkins> iank_: So first baseline from the visual top (basically) and last from visual bottom?
<TabAtkins> fantasai: yes
<TabAtkins> iank_: can you check chrome's beahvior in the testcase I just posted?
<TabAtkins> [people look at the example]
<TabAtkins> fantasai: Yeah this looks right
<TabAtkins> fantasai: altho... did we define alignmetn across multiline items?
<TabAtkins> [more clarification of the example]
<TabAtkins> iank_: I think in [missed case] we'll still do visual bottom/top
<iank_> https://www.software.hixie.ch/utilities/js/live-dom-viewer/?saved=11396
<TabAtkins> fantasai: If you wrap the columns, are you doing baseline alignment across the topmost items in each line? Because we could...
<TabAtkins> Rossen_: Let's open an issue for these additional wrinkles

fantasai added a commit to fantasai/csswg-drafts that referenced this issue Oct 30, 2023
…inding algo w3c#7655 w3c#7641

* RESOLVED: When taking the baseline of a row of items,
  we check a shared first baseline, then a shared last baseline,
  then the first baseline of the first item.
  (And vice versa for last baselines.)

* RESOLVED: Rowspanning cells participate only
  in first baseline alignment of their first row,
  and last baseline alignment in the last row.

* RESOLVED: Table baselines match grid, per details above.
fantasai added a commit to fantasai/csswg-drafts that referenced this issue Oct 30, 2023
…inding algo w3c#7655 w3c#7641 Part II w3c#8341

RESOLVED: first/last baseline takes from the first/last item (rather than taking highest/lowest baseline)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants