LibWeb: Move z-index to table wrapper box

When drawing a table, some of the CSS properties must be moved from the
table grid box to an anonamyous table wrapper box. One of these
properties is `position`. `z-index` however is not. This leads to the
following behavior if a table has both `position` and `z-index`:
* The wrapper box has the `position`, but a `z-index` of `auto`.
* The grid box has the `z-index`, but `position: static`.

This effectively means that the `z-index property is ignored since it
has no effect on non-positioned elements. This behavior contradicts what
other browsers do and causes layout issues on websites.

To align Ladybird behavior with other browser this commit also moves the
`z-index` property to the wrapper box.
This commit is contained in:
InvalidUsernameException 2025-02-15 16:58:35 +01:00 committed by Alexander Kalenik
parent 91e4fb248b
commit 29d74632c7
Notes: github-actions[bot] 2025-02-16 20:07:02 +00:00
4 changed files with 82 additions and 0 deletions

View file

@ -188,6 +188,7 @@ public:
static CSS::Isolation isolation() { return CSS::Isolation::Auto; }
static CSS::Containment contain() { return {}; }
static CSS::MixBlendMode mix_blend_mode() { return CSS::MixBlendMode::Normal; }
static Optional<int> z_index() { return OptionalNone(); }
// https://www.w3.org/TR/SVG/geometry.html
static LengthPercentage cx() { return CSS::Length::make_px(0); }

View file

@ -1043,6 +1043,11 @@ void NodeWithStyle::reset_table_box_computed_values_used_by_wrapper_to_init_valu
mutable_computed_values.set_clear(CSS::InitialValues::clear());
mutable_computed_values.set_inset(CSS::InitialValues::inset());
mutable_computed_values.set_margin(CSS::InitialValues::margin());
// AD-HOC:
// To match other browsers, z-index needs to be moved to the wrapper box as well,
// even if the spec does not mention that: https://github.com/w3c/csswg-drafts/issues/11689
// Note that there may be more properties that need to be added to this list.
mutable_computed_values.set_z_index(CSS::InitialValues::z_index());
}
void NodeWithStyle::transfer_table_box_computed_values_to_wrapper_computed_values(CSS::ComputedValues& wrapper_computed_values)
@ -1060,6 +1065,12 @@ void NodeWithStyle::transfer_table_box_computed_values_to_wrapper_computed_value
mutable_wrapper_computed_values.set_float(computed_values().float_());
mutable_wrapper_computed_values.set_clear(computed_values().clear());
mutable_wrapper_computed_values.set_margin(computed_values().margin());
// AD-HOC:
// To match other browsers, z-index needs to be moved to the wrapper box as well,
// even if the spec does not mention that: https://github.com/w3c/csswg-drafts/issues/11689
// Note that there may be more properties that need to be added to this list.
mutable_wrapper_computed_values.set_z_index(computed_values().z_index());
reset_table_box_computed_values_used_by_wrapper_to_init_values();
}

View file

@ -0,0 +1,26 @@
<!DOCTYPE html>
<style>
div {
background-color: green;
position: fixed;
width: 100px;
height: 100px;
}
.offset-0 { top: 10px; }
.offset-1 { top: 120px; }
.offset-2 { top: 230px; }
.offset-3 { top: 340px; }
.offset-4 { top: 450px; }
.offset-5 { top: 560px; }
.offset-6 { top: 670px; }
.offset-7 { top: 780px; }
</style>
<div class="offset-0"></div>
<div class="offset-1"></div>
<div class="offset-2"></div>
<div class="offset-3"></div>
<div class="offset-4"></div>
<div class="offset-5"></div>
<div class="offset-6"></div>
<div class="offset-7"></div>

View file

@ -0,0 +1,44 @@
<!DOCTYPE html>
<link rel="match" value="../expected/tables-with-z-index-ref.html">
<style>
div, table { width: 100px; height: 100px; }
.table { display: table; }
.red { background-color: red; }
.green { background-color: green; }
.fixed { position: fixed; }
.absolute { position: absolute; }
.offset-0 { top: 10px; }
.offset-1 { top: 120px; }
.offset-2 { top: 230px; }
.offset-3 { top: 340px; }
.offset-4 { top: 450px; }
.offset-5 { top: 560px; }
.offset-6 { top: 670px; }
.offset-7 { top: 780px; }
.z-index-1 { z-index: 1; }
.z-index-2 { z-index: 2; }
</style>
<div class="red fixed offset-0 z-index-1"></div>
<div class="table green fixed offset-0 z-index-2"></div>
<div class="table green fixed offset-1 z-index-1"></div>
<div class="red fixed offset-1"></div>
<div class="red fixed offset-2 z-index-1"></div>
<table class="green fixed offset-2 z-index-2"></table>
<table class="green fixed offset-3 z-index-1"></table>
<div class="red fixed offset-3"></div>
<div class="red absolute offset-4 z-index-1"></div>
<div class="table green absolute offset-4 z-index-2"></div>
<div class="table green absolute offset-5 z-index-1"></div>
<div class="red absolute offset-5"></div>
<div class="red absolute offset-6 z-index-1"></div>
<table class="green absolute offset-6 z-index-2"></table>
<table class="green absolute offset-7 z-index-1"></table>
<div class="red absolute offset-7"></div>