LibWeb: Add transform-style and have it make a stacking context

This commit is contained in:
Psychpsyo 2025-11-11 17:08:51 +01:00 committed by Jelle Raaijmakers
parent c80b698589
commit e064fa19d2
Notes: github-actions[bot] 2025-11-12 14:48:50 +00:00
13 changed files with 89 additions and 3 deletions

View file

@ -756,6 +756,12 @@ TransformOrigin ComputedProperties::transform_origin() const
return { x_value, y_value, z_value };
}
TransformStyle ComputedProperties::transform_style() const
{
auto const& value = property(PropertyID::TransformStyle);
return keyword_to_transform_style(value.to_keyword()).release_value();
}
Optional<Color> ComputedProperties::accent_color(Layout::NodeWithStyle const& node) const
{
auto const& value = property(PropertyID::AccentColor);

View file

@ -207,6 +207,7 @@ public:
Vector<Transformation> transformations() const;
TransformBox transform_box() const;
TransformOrigin transform_origin() const;
TransformStyle transform_style() const;
Optional<Transformation> rotate() const;
Optional<Transformation> translate() const;
Optional<Transformation> scale() const;

View file

@ -240,6 +240,7 @@ public:
static TableLayout table_layout() { return TableLayout::Auto; }
static QuotesData quotes() { return QuotesData { .type = QuotesData::Type::Auto }; }
static TransformBox transform_box() { return TransformBox::ViewBox; }
static TransformStyle transform_style() { return TransformStyle::Flat; }
static Direction direction() { return Direction::Ltr; }
static UnicodeBidi unicode_bidi() { return UnicodeBidi::Normal; }
static WritingMode writing_mode() { return WritingMode::HorizontalTb; }
@ -634,6 +635,7 @@ public:
Vector<Transformation> const& transformations() const { return m_noninherited.transformations; }
TransformBox const& transform_box() const { return m_noninherited.transform_box; }
TransformOrigin const& transform_origin() const { return m_noninherited.transform_origin; }
TransformStyle const& transform_style() const { return m_noninherited.transform_style; }
Optional<Transformation> const& rotate() const { return m_noninherited.rotate; }
Optional<Transformation> const& translate() const { return m_noninherited.translate; }
Optional<Transformation> const& scale() const { return m_noninherited.scale; }
@ -797,6 +799,7 @@ protected:
Vector<Transformation> transformations {};
TransformBox transform_box { InitialValues::transform_box() };
TransformOrigin transform_origin {};
TransformStyle transform_style { InitialValues::transform_style() };
BoxSizing box_sizing { InitialValues::box_sizing() };
ContentData content;
Variant<VerticalAlign, LengthPercentage> vertical_align { InitialValues::vertical_align() };
@ -996,6 +999,7 @@ public:
void set_transformations(Vector<Transformation> value) { m_noninherited.transformations = move(value); }
void set_transform_box(TransformBox value) { m_noninherited.transform_box = value; }
void set_transform_origin(TransformOrigin value) { m_noninherited.transform_origin = move(value); }
void set_transform_style(TransformStyle value) { m_noninherited.transform_style = value; }
void set_translate(Transformation value) { m_noninherited.translate = move(value); }
void set_box_sizing(BoxSizing value) { m_noninherited.box_sizing = value; }
void set_vertical_align(Variant<VerticalAlign, LengthPercentage> value) { m_noninherited.vertical_align = move(value); }

View file

@ -846,6 +846,10 @@
"stroke-box",
"view-box"
],
"transform-style": [
"flat",
"preserve-3d"
],
"transition-behavior": [
"normal",
"allow-discrete"

View file

@ -216,6 +216,7 @@
"fill-box",
"fine",
"fixed",
"flat",
"flex",
"flex-end",
"flex-start",
@ -424,6 +425,7 @@
"pre-line",
"pre-wrap",
"preserve",
"preserve-3d",
"preserve-breaks",
"preserve-spaces",
"pretty",

View file

@ -3847,6 +3847,15 @@
],
"percentages-resolve-to": "length"
},
"transform-style": {
"animation-type": "discrete",
"inherited": false,
"initial": "flat",
"valid-identifiers": [
"flat",
"preserve-3d"
]
},
"transition": {
"affects-layout": false,
"inherited": false,

View file

@ -295,6 +295,13 @@ bool Node::establishes_stacking_context() const
if (computed_values.perspective().has_value() || will_change_property(CSS::PropertyID::Perspective))
return true;
// https://drafts.csswg.org/css-transforms-2/#transform-style-property
// A computed value of 'preserve-3d' for 'transform-style' on a transformable element establishes both a
// stacking context and a containing block for all descendants.
// FIXME: Check that the element is a transformable element.
if (computed_values.transform_style() == CSS::TransformStyle::Preserve3d || will_change_property(CSS::PropertyID::TransformStyle))
return true;
return computed_values.opacity() < 1.0f || will_change_property(CSS::PropertyID::Opacity);
}
@ -694,6 +701,7 @@ void NodeWithStyle::apply_style(CSS::ComputedProperties const& computed_style)
computed_values.set_transform_box(computed_style.transform_box());
computed_values.set_transform_origin(computed_style.transform_origin());
computed_values.set_perspective(computed_style.perspective());
computed_values.set_transform_style(computed_style.transform_style());
auto const& transition_delay_property = computed_style.property(CSS::PropertyID::TransitionDelay);
if (transition_delay_property.is_time()) {

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<title>CSS Reftest Reference</title>
<link rel="author" title="Aryeh Gregor" href="mailto:ayg@aryeh.name">
<style>
div {
height: 100px;
width: 100px;
background: lime;
}
</style>
</head>
<body>
<div></div>
</body>
</html>

View file

@ -0,0 +1,30 @@
<!DOCTYPE HTML>
<title>'transform-style: preserve-3d' establishes a stacking context.</title>
<link rel="author" title="Psychpsyo" href="mailto:psychpsyo@gmail.com">
<link rel="help" href="https://drafts.csswg.org/css-transforms-2/#transform-style-property">
<link rel="match" href="../../../../expected/wpt-import/css/css-transforms/transform-lime-square-ref.html">
<style>
div {
width: 100px;
height: 100px;
}
#front {
background-color: lime;
/* makes a stacking context and puts this on top */
position: absolute;
z-index: 10;
}
#back {
transform-style: preserve-3d;
}
#notOnTop {
background-color: red;
/* z-index is higher than on #front, but this should still be covered up because it is inside #back, which has 'transform-style: preserve-3d' */
position: absolute;
z-index: 1000;
}
</style>
<div id="front"></div>
<div id="back">
<div id="notOnTop"></div>
</div>

View file

@ -276,6 +276,7 @@ All properties associated with getComputedStyle(document.body):
"transform",
"transform-box",
"transform-origin",
"transform-style",
"transition-behavior",
"transition-delay",
"transition-duration",

View file

@ -773,6 +773,8 @@ All supported properties and their default values exposed from CSSStylePropertie
'transform-box': 'view-box'
'transformOrigin': '50% 50% 0px'
'transform-origin': '50% 50% 0px'
'transformStyle': 'flat'
'transform-style': 'flat'
'transition': 'all'
'transitionBehavior': 'normal'
'transition-behavior': 'normal'

View file

@ -274,6 +274,7 @@ touch-action: auto
transform: none
transform-box: view-box
transform-origin: 50% 50% 0px
transform-style: flat
transition-behavior: normal
transition-delay: 0s
transition-duration: 0s

View file

@ -1,8 +1,8 @@
Harness status: OK
Found 270 tests
Found 271 tests
264 Pass
265 Pass
6 Fail
Pass accent-color
Pass border-collapse
@ -258,6 +258,7 @@ Pass touch-action
Fail transform
Pass transform-box
Pass transform-origin
Pass transform-style
Pass transition-behavior
Pass transition-delay
Pass transition-duration