mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
layout: Make transform-style: preserve-3d
establish a containing block for all descendants (#35808)
* layout: Fix behavior of `transform-style: preserve-3d` This makes `transform-style: preserve-3d` establish a containing block for all descendants, as specified here: <https://drafts.csswg.org/css-transforms-2/#transform-style-property> Signed-off-by: Daniel Hast <hast.daniel@protonmail.com> * layout: Check for transformable elements Adds a new `is_transformable` helper method and use this in several other methods, including the methods for whether the fragment establishes a new stacking context or a containing block for all descendants. Signed-off-by: Daniel Hast <hast.daniel@protonmail.com> * Use generic green square reference for reftest. Signed-off-by: Daniel Hast <hast.daniel@protonmail.com> * layout: Fix stacking context & containing block checks. Only the computed value of `transform-style` should be used to determine whether the element establishes a stacking context and/or a containing block, not the used value. Signed-off-by: Daniel Hast <hast.daniel@protonmail.com> * Update clip-no-stacking-context test expectation to pass. Signed-off-by: Daniel Hast <hast.daniel@protonmail.com> --------- Signed-off-by: Daniel Hast <hast.daniel@protonmail.com>
This commit is contained in:
parent
991635eefb
commit
34b000c86e
4 changed files with 50 additions and 14 deletions
|
@ -283,6 +283,7 @@ pub(crate) trait ComputedValuesExt {
|
|||
&self,
|
||||
containing_block_writing_mode: WritingMode,
|
||||
) -> LogicalSides<LengthPercentageOrAuto<'_>>;
|
||||
fn is_transformable(&self, fragment_flags: FragmentFlags) -> bool;
|
||||
fn has_transform_or_perspective(&self, fragment_flags: FragmentFlags) -> bool;
|
||||
fn effective_z_index(&self, fragment_flags: FragmentFlags) -> i32;
|
||||
fn effective_overflow(&self, fragment_flags: FragmentFlags) -> AxesOverflow;
|
||||
|
@ -463,9 +464,8 @@ impl ComputedValuesExt for ComputedValues {
|
|||
LogicalSides::from_physical(&self.physical_margin(), containing_block_writing_mode)
|
||||
}
|
||||
|
||||
/// Returns true if this style has a transform, or perspective property set and
|
||||
/// it applies to this element.
|
||||
fn has_transform_or_perspective(&self, fragment_flags: FragmentFlags) -> bool {
|
||||
/// Returns true if this is a transformable element.
|
||||
fn is_transformable(&self, fragment_flags: FragmentFlags) -> bool {
|
||||
// "A transformable element is an element in one of these categories:
|
||||
// * all elements whose layout is governed by the CSS box model except for
|
||||
// non-replaced inline boxes, table-column boxes, and table-column-group
|
||||
|
@ -473,14 +473,18 @@ impl ComputedValuesExt for ComputedValues {
|
|||
// * all SVG paint server elements, the clipPath element and SVG renderable
|
||||
// elements with the exception of any descendant element of text content
|
||||
// elements."
|
||||
// https://drafts.csswg.org/css-transforms/#transformable-element
|
||||
if self.get_box().display.is_inline_flow() &&
|
||||
!fragment_flags.contains(FragmentFlags::IS_REPLACED)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// <https://drafts.csswg.org/css-transforms/#transformable-element>
|
||||
// TODO: check for all cases listed in the above spec.
|
||||
!self.get_box().display.is_inline_flow() ||
|
||||
fragment_flags.contains(FragmentFlags::IS_REPLACED)
|
||||
}
|
||||
|
||||
!self.get_box().transform.0.is_empty() || self.get_box().perspective != Perspective::None
|
||||
/// Returns true if this style has a transform, or perspective property set and
|
||||
/// it applies to this element.
|
||||
fn has_transform_or_perspective(&self, fragment_flags: FragmentFlags) -> bool {
|
||||
self.is_transformable(fragment_flags) &&
|
||||
(!self.get_box().transform.0.is_empty() ||
|
||||
self.get_box().perspective != Perspective::None)
|
||||
}
|
||||
|
||||
/// Get the effective z-index of this fragment. Z-indices only apply to positioned elements
|
||||
|
@ -614,8 +618,9 @@ impl ComputedValuesExt for ComputedValues {
|
|||
return true;
|
||||
}
|
||||
|
||||
if self.get_box().transform_style == ComputedTransformStyle::Preserve3d ||
|
||||
self.overrides_transform_style()
|
||||
// See <https://drafts.csswg.org/css-transforms-2/#transform-style-property>.
|
||||
if self.is_transformable(fragment_flags) &&
|
||||
self.get_box().transform_style == ComputedTransformStyle::Preserve3d
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -688,6 +693,13 @@ impl ComputedValuesExt for ComputedValues {
|
|||
return true;
|
||||
}
|
||||
|
||||
// See <https://drafts.csswg.org/css-transforms-2/#transform-style-property>.
|
||||
if self.is_transformable(fragment_flags) &&
|
||||
self.get_box().transform_style == ComputedTransformStyle::Preserve3d
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: We need to handle CSS Contain here.
|
||||
false
|
||||
}
|
||||
|
|
13
tests/wpt/meta/MANIFEST.json
vendored
13
tests/wpt/meta/MANIFEST.json
vendored
|
@ -276759,6 +276759,19 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"preserve3d-containing-block.html": [
|
||||
"fc74e3874c67a2965b549036dd6699d593eeb3ef",
|
||||
[
|
||||
null,
|
||||
[
|
||||
[
|
||||
"/css/reference/ref-filled-green-100px-square.xht",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
],
|
||||
"preserve3d-nested-perspective.html": [
|
||||
"368784c74f51c774cf8ea1b6f55127e72fd5854e",
|
||||
[
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
[clip-no-stacking-context.html]
|
||||
expected: FAIL
|
13
tests/wpt/tests/css/css-transforms/preserve3d-containing-block.html
vendored
Normal file
13
tests/wpt/tests/css/css-transforms/preserve3d-containing-block.html
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS test: "transform-style: preserve-3d" should establish a containing block for all descendants</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-transforms-2/#transform-style-property">
|
||||
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
|
||||
<meta name="assert" content="The box should be green (not red) because the div establishes a containing block for all descendants.">
|
||||
<style>
|
||||
body { transform: scale(1); height: 0 }
|
||||
div { background: red; width: 100px; height: 100px; }
|
||||
div::before { content: ""; position: fixed; width: 100%; height: 100%; background: green; }
|
||||
</style>
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
<div style="transform-style: preserve-3d"></div>
|
Loading…
Add table
Add a link
Reference in a new issue