w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.52k stars 673 forks source link

[css-align-3][css-tables] vertical-align in orthogonal table cells #4033

Open frivoal opened 5 years ago

frivoal commented 5 years ago

vertical-align on things other than table cells behaves differently than on table cells. I am only talking about table cells here.

Does "vertical" actually mean vertical, or does it mean block axis? if it means block axis, is that based on the writing mode of the table, or of the table cell?

I think it should be the block axis of the table cell (otherwise there is no way adjust alignment of the table cell content in that direction), but as far as I can tell, there's no spec that says that.

FremyCompany commented 5 years ago

I should test in browsers just to be sure, but as far as I know, vertical-align works on the cells at the table row level, as in: cells get aligned in the first row layout based on that, so vertical-align does not apply in the table cell block axis but the table row block axis, just like it does for inlines in a block.

My understanding is that the thing that is special about tables is not how vertical-align works, it is that after the alignment, all cells are stretched to the full line height, where in a block>inline situation, there is empty space above/below the aligned inlines.

At this point, cell boxes that are smaller than the height of the rows they span receive extra top and/or bottom padding such that their content does not move vertically but their top and bottom edges meet the ones of the rows they span.

I guess I should clarify that vertically in the above spec text refers to the verticality of the table row, but there is a figure just above that kinda does clarify it a bit.

frivoal commented 5 years ago

Working from the row rather than the cell seems confusing to me, but maybe, that just shows I don't understand how rows and cells and vertical-align works :)

If it is working from the row's writing mode, what does it do if a cell has it's writing-mode orthogonal to the row? Say, a horizontal-tb table with horizontal-tb rows, with a vertical-rl cell, and vertical-align:middle. Assume that the table has other rows and other columns, such that this orthogonal cell ends up being bigger than it needs to in both axises. My guess was that it would be "centering" the text in the block axis of the cell, i.e. horizontally. If not:

  1. What does it do?
  2. Is there a way to "center" the content of the cell in the block axis?
FremyCompany commented 5 years ago

Vertical-align works the same way for table cells in a table row as if you took all the cells of the row,

Here is an example: https://jsfiddle.net/3jp2nwoy/

The only difference is that with table rows, you add padding to the cells so that their top and bottom sides meet the full row height (without shifting their content box) while for a normal flow line, you just leave blank space on either side of the line block.

If you have boxes without background and border, are nothing positioned relatively to them, there is no difference between a table-cell row and an inline-block flow regarding how vertical-align works. Otherwise, the added padding has some impact.

Here is the same example but with support for proper background/border/etc (addition of padding-top/padding-bottom to meet the row height after alignment, assuming things have roughly the same height as on my machine):

https://jsfiddle.net/3jp2nwoy/1/


Now, you are correct that there is no way to visually center the content of an inline-block or block in its block axis if that block axis does not happen to match the parent one. That's a limitation of flows in general, not of table cells (which are more or less a block).

My impression is that what you are trying to achieve is to add a align-content / justify-content on the table cell. The only problem is that those properties do not apply to regular blocks as far as I can recall, only to flex and grid. But maybe they should?

That would be an issue against another spec however. The internal layout of a table-cell is just the layout of a block, so you would want to modify css-align to interact with blocks.

cc @fantasai since she's the expert wrt css-align

FremyCompany commented 5 years ago

I should add to the previous explanation that if some cells have height, or if the row has an height, or if there are spanning cells forcing some rows to grow, things are still a bit different wrt a flow of inline-block in the sense that there is this additional constraints that may apply. If we had to think in terms of flow, I think the impact is roughly the same as if every line started with an anonymous inline-block of width 0px and of height being the height of the imposed height, with a vertical-align of top (because cells will lower their bottom to accommodate that constraint, if I recall correctly)

Hopefully this comparison of vertical-align between block flows and table-rows has cleared up why it does not affect the cells in their own axis and rather affect cells in the axis of the row,

fantasai commented 5 years ago

This is currently defined in https://www.w3.org/TR/css-align-3/#distribution-block There's an interesting question if this is how it should work, but it is how it does per spec.

css-meeting-bot commented 4 years ago

The CSS Working Group just discussed vertical-align on orthogonal table cells, and agreed to the following:

The full IRC log of that discussion <TabAtkins> Topic: vertical-align on orthogonal table cells
<astearns> github: https://github.com/w3c/csswg-drafts/issues/4033
<TabAtkins> florian: If we have a table-cell which is orthogonal to the table, and you verticla-align it, what does that mean?
<TabAtkins> florian: "vertical" isn't a great word in the first place, but is it "vertical" in the table, or in the cell?
<TabAtkins> florian: Related, how does that interact with the justify/align properties that are also trying to shift the table cell contents?
<TabAtkins> fantasai: There are two types of properties here. *-self, which apply to the box itself in its context, and *-content, wich apply to the contents of the box relative to the box.
<TabAtkins> fantasai: vertical-align is like the *-content properties
<TabAtkins> fantasai: When we drafted up the Align spec, we said that "align-content: normal" looks up vertical-align and does what it says.
<TabAtkins> fantasai: (for table cells)
<TabAtkins> fantasai: That works as expected for non-orthogonal cells. But for orthogonal ones, which writing mode is it using?
<TabAtkins> fantasai: The *-content properties work in the container's writing mode (the table cell). But vertical-align probably applies in the table's writing mode.
<TabAtkins> fantasai: So we could say that vertical-align doesn't apply to orthogonal cells.
<TabAtkins> fantasai: Second is vertical-align applies when align-content is "normal" in the appropraite (table's) axis
<TabAtkins> fantasai: Third is that both align/justify-content is potentially affected by vertical-align: use the writing mode of the table to figure out which property on the table cell cares about vertical-align.
<TabAtkins> fremy: Third was the behavior of EdgeHTML.
<TabAtkins> fremy: vertical-align worked the same whether you had table cells or inline blocks.
<TabAtkins> fremy: In both cases it cared about the line's direction, not the items.
<TabAtkins> fremy: Complication with tables is just that, at the end, you have to alter the size of the cell to make them all the same height. But before that, the algorithm is identical to inline-blocks in a text line.
<TabAtkins> fremy: So based on that, I think it makes the most sense for v-a to work the same in both, applying in the axis of the line.
<TabAtkins> fremy: Downside is that you lose some control here; you can't necessarily apply the place-* keywords because vertical-align has already added magic padding to align things.
<TabAtkins> fremy: Possibility is that if you say "*-content: normal", you do the normal vertical-align stuff, but if you say any other keyword, vertical-align has no effect.
<TabAtkins> florian: Initially I thought this was counter-intuitive, as v-a on table-cells doesn't *seem* to do the same as alignment; because of the extra padding added, it felt like it wasn't shifting boxes, it was shifting the content of the box.
<TabAtkins> florian: So if that's your model, you might think that it should align in the cell's writing mode, rotated relative ot the table.
<TabAtkins> florian: So it's a little counter-intuitive to me, but v-a is anyway, and the underlying model is sensible. So as long as we get *-content to actually work on table cells, you can achieve whatever result you wanted.
<TabAtkins> florian: If v-a was the only property we could use, we might want something different, but as the spec stands it seems okay.
<TabAtkins> dbaron: A lot of legacy table stuff maps into verticla-align or text-align depending on writing-mode. Does this cause them to ever act on the same axis?
<TabAtkins> fremy: I think so, yes, for any orthogonal cell.
<TabAtkins> florian: I think it's a problem that previously you used text-align and vertical-align to control everything, and having them always be perpendicular was good, but now we have the *-content properties which definitely are perpendicular.
<TabAtkins> dbaron: I think that's not *great*.
<TabAtkins> florian: v-a and t-a are already parallel for orthogonal inline-blocks
<TabAtkins> dbaron: They're a bit different because table-cells have a special behavior for vertical-align.
<TabAtkins> fremy: Using the *-content properties you get full control. The old properties didn't always give you full control anyway.
<TabAtkins> fantasai: I think dbaron's issue is valid. The model of vertical-align requires that the content is smaller than the table cell and you add padding.
<TabAtkins> fantasai: In text-align, you rely on the fact that the linebox fills the table cell.
<TabAtkins> fantasai: verticla-align doesn't have stretch, it aligns you to some spot, and only applies if the item is smaller than the container.
<TabAtkins> fantasai: So basically orthogonal cells won't be affected by vertical-aign at all, since the linebox will fill the full height.
<TabAtkins> TabAtkins: Yeah, I think that's what we expect actually.
<TabAtkins> florian: Another possible model is that the vertical-align applies first, then you vertical-align the tight bounding box of the text.
<TabAtkins> dbaron: Too many fundamental model changes for an edge case.
<TabAtkins> florian: So we're saying that text-align applies in the only axis it can possibly make sense, and vertical-align applies in the table's writing mode.
<TabAtkins> (parallel directions)
<TabAtkins> TabAtkins: So what happens today?
<TabAtkins> fremy: Orthogonal cells don't work at all in Chrome or Safari, EdgeHTML used the behavior we're discussing, and Firefox has broken sizing behavior.
<AmeliaBR> If anyone else wants to look at current browser behavior, I made a test: https://codepen.io/AmeliaBR/pen/afcd79a788685ccee7892f733cc8251f Chromium currently ignores `writing-mode` on a `td`. Firefox supports them, though it's weird. It uses the table's definition of top/bottom for `vertical-align`
<TabAtkins> dbaron: So my preferred suggestion is that both v-a and t-a work on the cell's writing mode.
<TabAtkins> fremy: Either case is potentially weird. I think it's weird to not follow the same model as inline-block.
<TabAtkins> fremy: Maybe come up with a lot of examples and see what looks most reasonable?
<TabAtkins> florian: I think from an author point of view what dbaron proposed makes more sense.
<TabAtkins> florian: You've still got the two properties, they jsut rotate
<TabAtkins> fremy: Still a difference - you'd have to redo row layout here, where in the "just stretch it" model you don't.
<TabAtkins> dbaron: You need to redo layout once you discover the final row height anyway, for %s.
<TabAtkins> florian: Every time I've used orthogonal table cells I've tripped over this, and wanted dbaron's behavior.
<TabAtkins> fremy: So if I do make that change, would anyone want to implement it?
<TabAtkins> dbaron: Which change?
<TabAtkins> fremy: That v-a and t-a both work in the cell's w-m, so you have to do a second layout pass.
<TabAtkins> dbaron: You do a second pass, and it can only increase the height.
<TabAtkins> fremy: yes
<TabAtkins> dbaron: In principle this seems reasonable, we have a bunch orthogonal cell bugs that haven't been a priority.
<TabAtkins> TabAtkins: I can volunteer Aleks to look at this, yeah
<TabAtkins> fantasai: the inline axis of an ortho cell is sized *after* the baseline alignment of the non-ortho cells in that row.
<fantasai> RESOLVED: vertical-align operates in the block-axis of the table cell
<fantasai> RESOLVED: the inline axis of an orthogonal table cell is sized *after* the baseline alignment of the non-orthogonal cells in that row
atotic commented 4 years ago

Need clarification for implementation:

the inline axis of an orthogonal table cell is sized after the baseline alignment of the non-orthogonal cells in that row

What happens when all cells are orthogonal? Is row height defined by minimum or maximum inline size?

What are %ge inline/block sizes resolved against?

vertical-align operates in the block-axis of the table cell

vertical-align: baseline is interesting. There is no "row baseline", what does baseline alignment means here?

FremyCompany commented 4 years ago

Need clarification for implementation:

the inline axis of an orthogonal table cell is sized after the baseline alignment of the non-orthogonal cells in that row

What happens when all cells are orthogonal? Is row height defined by minimum or maximum inline size?

Good question. I would assume the minimum height.

What are %ge inline/block sizes resolved against?

During the first pass, auto? During the second pass, which will be required anyway, I suspect we can resolve them, and just like we do with other cells, if there's an overflow, we let the content overflow.

Does that make sense to you?

vertical-align operates in the block-axis of the table cell

vertical-align: baseline is interesting. There is no "row baseline", what does baseline alignment means here?

I would assume it's simply being ignored in this case.

fantasai commented 4 years ago

vertical-align: baseline is interesting. There is no "row baseline", what does baseline alignment means here?

On an orthogonal cell, it means the cell doesn't participate in baseline alignment across cells in the same row, but it could participate in alignment across cells in the same column. I don't know how awful that would be implementation-wise given the state of table algorithms, but it's how things are defined for grids IIRC. :)

atotic commented 4 years ago

On an orthogonal cell, it means the cell doesn't participate in baseline alignment across cells in the same row, but it could participate in alignment across cells in the same column.

I think that column baseline alignment for tables should not be supported unless someone demonstrates clear need for it. Implementing it is non-trivial, and has a corner case that cannot be implemented: descendants with percentage block sizes.

Baseline computation for rows algorithm: 1) in measuring phase, each row computes an intrinsic baseline. This baseline is used to compute row's height. Block percentages resolution size is 0. 2) Layout phase requires up to 2 passes. 3) Layout pass 1 is optional. If baseline aligned TDs have a descendant with percentage block size, an optional baseline resolution layout is needed to compute new baseline. Baseline is recomputed by doing layout where block percentage resolution size is row height. 4) Layout pass 2 is required. TDs are laid out, and their content vertically positioned based on vertical alignment.

atotic commented 4 years ago

What happens when all cells are orthogonal? Is row height defined by minimum or maximum inline size?

Good question. I would assume the minimum height.

Agree,

What are %ge inline/block sizes resolved against?

During the first pass, auto? During the second pass, which will be required anyway, I suspect we can resolve them, and just like we do with other cells, if there's an overflow, we let the content overflow.

Agree.

FremyCompany commented 4 years ago

Great, I'll be adding this into the spec, then.