mirror of
https://github.com/servo/servo
synced 2026-04-25 17:15:48 +02:00
layout: Fix which axis to consider for baseline propagation of flex items (#44281)
* When a flex item line participates in baseline alignment, the relevant baseline must be parallel to the **main axis** (affected by `flex-direction`) of the flex container. * When a flex item propagates a baseline to a parent layout (such as for `display: inline-flex`) the relevant baseline must be parallel to the **inline axis** (not affected by `flex-direction`) of the flex container. See: * https://drafts.csswg.org/css-flexbox-1/#box-model * https://drafts.csswg.org/css-flexbox-1/#flex-direction-property * https://drafts.csswg.org/css-flexbox-1/#baseline-participation * https://drafts.csswg.org/css-align-3/#baseline-export Testing: covered by existing WPT tests Fixes: https://github.com/servo/servo/issues/43687 Signed-off-by: Simon Sapin <simon@igalia.com>
This commit is contained in:
@@ -117,7 +117,7 @@ struct FlexItemLayoutResult {
|
||||
|
||||
/// Baselines from the item’s content, relative to the item’s margin box.
|
||||
/// Used only for baseline propagation to parent layout contexts.
|
||||
content_baselines_relative_to_margin_box: Baselines,
|
||||
content_baselines_for_parent_relative_to_margin_box: Baselines,
|
||||
|
||||
/// This is the single baseline this item uses for flex alignment.
|
||||
/// Either the first or the last baseline or None, depending on ‘align-self’.
|
||||
@@ -223,7 +223,9 @@ impl FlexLineItem<'_> {
|
||||
item_margin.cross_start
|
||||
};
|
||||
|
||||
let baselines = self.layout_result.content_baselines_relative_to_margin_box;
|
||||
let baselines = self
|
||||
.layout_result
|
||||
.content_baselines_for_parent_relative_to_margin_box;
|
||||
if flex_context.config.flex_direction_is_reversed {
|
||||
if let Some(last_baseline) = baselines.last {
|
||||
all_baselines
|
||||
@@ -1885,36 +1887,47 @@ impl FlexItem<'_> {
|
||||
inline_size
|
||||
};
|
||||
|
||||
let item_writing_mode_is_orthogonal_to_container_writing_mode =
|
||||
flex_context.config.writing_mode.is_horizontal() !=
|
||||
item_style.writing_mode.is_horizontal();
|
||||
let has_compatible_baseline = match flex_axis {
|
||||
FlexAxis::Row => !item_writing_mode_is_orthogonal_to_container_writing_mode,
|
||||
FlexAxis::Column => item_writing_mode_is_orthogonal_to_container_writing_mode,
|
||||
let item_inline_axis_is_horizontal = item_style.writing_mode.is_horizontal();
|
||||
let container_inline_axis_is_horizontal = flex_context.config.writing_mode.is_horizontal();
|
||||
let container_main_axis_is_horizontal = match flex_axis {
|
||||
FlexAxis::Row => container_inline_axis_is_horizontal,
|
||||
FlexAxis::Column => !container_inline_axis_is_horizontal,
|
||||
};
|
||||
let item_inline_axis_parallel_to_container_inline_axis =
|
||||
item_inline_axis_is_horizontal == container_inline_axis_is_horizontal;
|
||||
let item_inline_axis_parallel_to_container_main_axis =
|
||||
item_inline_axis_is_horizontal == container_main_axis_is_horizontal;
|
||||
|
||||
let content_baselines_relative_to_margin_box = if has_compatible_baseline {
|
||||
content_box_baselines.offset(
|
||||
self.margin.cross_start.auto_is(Au::zero) +
|
||||
self.padding.cross_start +
|
||||
self.border.cross_start,
|
||||
)
|
||||
} else {
|
||||
Baselines::default()
|
||||
};
|
||||
let content_baselines_relative_to_margin_box = content_box_baselines.offset(
|
||||
self.margin.cross_start.auto_is(Au::zero) +
|
||||
self.padding.cross_start +
|
||||
self.border.cross_start,
|
||||
);
|
||||
|
||||
let flex_alignment_baseline_relative_to_margin_box = match self.align_self.0.value() {
|
||||
// ‘baseline’ computes to ‘first baseline’.
|
||||
AlignFlags::BASELINE => content_baselines_relative_to_margin_box.first,
|
||||
AlignFlags::LAST_BASELINE => content_baselines_relative_to_margin_box.last,
|
||||
_ => None,
|
||||
};
|
||||
let content_baselines_for_parent_relative_to_margin_box =
|
||||
if item_inline_axis_parallel_to_container_inline_axis {
|
||||
content_baselines_relative_to_margin_box
|
||||
} else {
|
||||
Baselines::default()
|
||||
};
|
||||
|
||||
let flex_alignment_baseline_relative_to_margin_box =
|
||||
if item_inline_axis_parallel_to_container_main_axis {
|
||||
match self.align_self.0.value() {
|
||||
// ‘baseline’ computes to ‘first baseline’.
|
||||
AlignFlags::BASELINE => content_baselines_relative_to_margin_box.first,
|
||||
AlignFlags::LAST_BASELINE => content_baselines_relative_to_margin_box.last,
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
FlexItemLayoutResult {
|
||||
hypothetical_cross_size,
|
||||
fragments,
|
||||
positioning_context,
|
||||
content_baselines_relative_to_margin_box,
|
||||
content_baselines_for_parent_relative_to_margin_box,
|
||||
flex_alignment_baseline_relative_to_margin_box,
|
||||
content_block_size,
|
||||
containing_block_size: item_as_containing_block.size,
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
[flex-align-baseline-flex-001.html]
|
||||
[.target > * 9]
|
||||
expected: FAIL
|
||||
|
||||
[.target > * 11]
|
||||
expected: FAIL
|
||||
|
||||
@@ -32,17 +29,8 @@
|
||||
[.target > * 45]
|
||||
expected: FAIL
|
||||
|
||||
[.target > * 25]
|
||||
expected: FAIL
|
||||
|
||||
[.target > * 43]
|
||||
expected: FAIL
|
||||
|
||||
[.target > * 47]
|
||||
expected: FAIL
|
||||
|
||||
[.target > * 13]
|
||||
expected: FAIL
|
||||
|
||||
[.target > * 29]
|
||||
expected: FAIL
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
[flexbox-baseline-multi-item-vert-001a.html]
|
||||
expected: FAIL
|
||||
@@ -1,2 +0,0 @@
|
||||
[flexbox-baseline-multi-item-vert-001b.html]
|
||||
expected: FAIL
|
||||
@@ -1,2 +0,0 @@
|
||||
[flexbox-baseline-single-item-001b.html]
|
||||
expected: FAIL
|
||||
@@ -1,2 +0,0 @@
|
||||
[percentage-heights-004.html]
|
||||
expected: FAIL
|
||||
@@ -73,3 +73,6 @@
|
||||
|
||||
[.target > * 25]
|
||||
expected: FAIL
|
||||
|
||||
[.target > * 10]
|
||||
expected: FAIL
|
||||
|
||||
@@ -16,6 +16,3 @@
|
||||
|
||||
[.target > * 21]
|
||||
expected: FAIL
|
||||
|
||||
[.target > * 11]
|
||||
expected: FAIL
|
||||
|
||||
Reference in New Issue
Block a user