mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
layout: Non-auto z-index
should always make stacking contexts for flex items (#32961)
Fixes #32756. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
d29e937f7e
commit
564ba5969f
9 changed files with 87 additions and 21 deletions
|
@ -315,9 +315,12 @@ pub struct StackingContext {
|
||||||
/// The clip chain id of this stacking context if it has one. Used for filter clipping.
|
/// The clip chain id of this stacking context if it has one. Used for filter clipping.
|
||||||
clip_chain_id: Option<wr::ClipChainId>,
|
clip_chain_id: Option<wr::ClipChainId>,
|
||||||
|
|
||||||
/// The fragment that established this stacking context.
|
/// The style of the fragment that established this stacking context.
|
||||||
initializing_fragment_style: Option<ServoArc<ComputedValues>>,
|
initializing_fragment_style: Option<ServoArc<ComputedValues>>,
|
||||||
|
|
||||||
|
/// The [`FragmentFlags`] of the [`Fragment`] that established this stacking context.
|
||||||
|
initializing_fragment_flags: FragmentFlags,
|
||||||
|
|
||||||
/// The type of this stacking context. Used for collecting and sorting.
|
/// The type of this stacking context. Used for collecting and sorting.
|
||||||
context_type: StackingContextType,
|
context_type: StackingContextType,
|
||||||
|
|
||||||
|
@ -376,6 +379,7 @@ impl StackingContext {
|
||||||
spatial_id: wr::SpatialId,
|
spatial_id: wr::SpatialId,
|
||||||
clip_chain_id: wr::ClipChainId,
|
clip_chain_id: wr::ClipChainId,
|
||||||
initializing_fragment_style: ServoArc<ComputedValues>,
|
initializing_fragment_style: ServoArc<ComputedValues>,
|
||||||
|
initializing_fragment_flags: FragmentFlags,
|
||||||
context_type: StackingContextType,
|
context_type: StackingContextType,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// WebRender has two different ways of expressing "no clip." ClipChainId::INVALID should be
|
// WebRender has two different ways of expressing "no clip." ClipChainId::INVALID should be
|
||||||
|
@ -390,6 +394,7 @@ impl StackingContext {
|
||||||
spatial_id,
|
spatial_id,
|
||||||
clip_chain_id,
|
clip_chain_id,
|
||||||
initializing_fragment_style: Some(initializing_fragment_style),
|
initializing_fragment_style: Some(initializing_fragment_style),
|
||||||
|
initializing_fragment_flags,
|
||||||
context_type,
|
context_type,
|
||||||
contents: vec![],
|
contents: vec![],
|
||||||
real_stacking_contexts_and_positioned_stacking_containers: vec![],
|
real_stacking_contexts_and_positioned_stacking_containers: vec![],
|
||||||
|
@ -404,6 +409,7 @@ impl StackingContext {
|
||||||
spatial_id: wr::SpaceAndClipInfo::root_scroll(wr.pipeline_id).spatial_id,
|
spatial_id: wr::SpaceAndClipInfo::root_scroll(wr.pipeline_id).spatial_id,
|
||||||
clip_chain_id: None,
|
clip_chain_id: None,
|
||||||
initializing_fragment_style: None,
|
initializing_fragment_style: None,
|
||||||
|
initializing_fragment_flags: FragmentFlags::empty(),
|
||||||
context_type: StackingContextType::RealStackingContext,
|
context_type: StackingContextType::RealStackingContext,
|
||||||
contents: vec![],
|
contents: vec![],
|
||||||
real_stacking_contexts_and_positioned_stacking_containers: vec![],
|
real_stacking_contexts_and_positioned_stacking_containers: vec![],
|
||||||
|
@ -433,7 +439,9 @@ impl StackingContext {
|
||||||
fn z_index(&self) -> i32 {
|
fn z_index(&self) -> i32 {
|
||||||
self.initializing_fragment_style
|
self.initializing_fragment_style
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(0, |style| style.effective_z_index())
|
.map_or(0, |style| {
|
||||||
|
style.effective_z_index(self.initializing_fragment_flags)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn sort(&mut self) {
|
pub(crate) fn sort(&mut self) {
|
||||||
|
@ -1055,6 +1063,7 @@ impl BoxFragment {
|
||||||
containing_block.scroll_node_id.spatial_id,
|
containing_block.scroll_node_id.spatial_id,
|
||||||
containing_block.clip_chain_id,
|
containing_block.clip_chain_id,
|
||||||
self.style.clone(),
|
self.style.clone(),
|
||||||
|
self.base.flags,
|
||||||
context_type,
|
context_type,
|
||||||
);
|
);
|
||||||
self.build_stacking_context_tree_for_children(
|
self.build_stacking_context_tree_for_children(
|
||||||
|
|
|
@ -31,7 +31,7 @@ use super::{FlexContainer, FlexItemBox, FlexLevelBox};
|
||||||
use crate::cell::ArcRefCell;
|
use crate::cell::ArcRefCell;
|
||||||
use crate::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::formatting_contexts::{Baselines, IndependentFormattingContext, IndependentLayout};
|
use crate::formatting_contexts::{Baselines, IndependentFormattingContext, IndependentLayout};
|
||||||
use crate::fragment_tree::{BoxFragment, CollapsedBlockMargins, Fragment};
|
use crate::fragment_tree::{BoxFragment, CollapsedBlockMargins, Fragment, FragmentFlags};
|
||||||
use crate::geom::{AuOrAuto, LogicalRect, LogicalSides, LogicalVec2};
|
use crate::geom::{AuOrAuto, LogicalRect, LogicalSides, LogicalVec2};
|
||||||
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, PositioningContextLength};
|
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, PositioningContextLength};
|
||||||
use crate::sizing::ContentSizes;
|
use crate::sizing::ContentSizes;
|
||||||
|
@ -1522,9 +1522,12 @@ impl InitialFlexLineLayout<'_> {
|
||||||
all_baselines.last = Some(item_baseline);
|
all_baselines.last = Some(item_baseline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut fragment_info = item.box_.base_fragment_info();
|
||||||
|
fragment_info.flags.insert(FragmentFlags::IS_FLEX_ITEM);
|
||||||
|
|
||||||
(
|
(
|
||||||
BoxFragment::new(
|
BoxFragment::new(
|
||||||
item.box_.base_fragment_info(),
|
fragment_info,
|
||||||
item.box_.style().clone(),
|
item.box_.style().clone(),
|
||||||
item_layout_result.fragments,
|
item_layout_result.fragments,
|
||||||
content_rect,
|
content_rect,
|
||||||
|
|
|
@ -88,20 +88,22 @@ bitflags! {
|
||||||
const IS_BODY_ELEMENT_OF_HTML_ELEMENT_ROOT = 1 << 0;
|
const IS_BODY_ELEMENT_OF_HTML_ELEMENT_ROOT = 1 << 0;
|
||||||
/// Whether or not the node that created this Fragment is a `<br>` element.
|
/// Whether or not the node that created this Fragment is a `<br>` element.
|
||||||
const IS_BR_ELEMENT = 1 << 1;
|
const IS_BR_ELEMENT = 1 << 1;
|
||||||
/// Whether or not the node that created was a `<table>`, `<th>` or
|
/// Whether or not this Fragment is a flex item.
|
||||||
/// `<td>` element. Note that this does *not* include elements with
|
const IS_FLEX_ITEM = 1 << 2;
|
||||||
/// `display: table` or `display: table-cell`.
|
|
||||||
const IS_TABLE_TH_OR_TD_ELEMENT = 1 << 2;
|
|
||||||
/// Whether or not this Fragment was created to contain a replaced element or is
|
/// Whether or not this Fragment was created to contain a replaced element or is
|
||||||
/// a replaced element.
|
/// a replaced element.
|
||||||
const IS_REPLACED = 1 << 3;
|
const IS_REPLACED = 1 << 3;
|
||||||
|
/// Whether or not the node that created was a `<table>`, `<th>` or
|
||||||
|
/// `<td>` element. Note that this does *not* include elements with
|
||||||
|
/// `display: table` or `display: table-cell`.
|
||||||
|
const IS_TABLE_TH_OR_TD_ELEMENT = 1 << 4;
|
||||||
/// Whether or not this Fragment was created to contain a list item marker
|
/// Whether or not this Fragment was created to contain a list item marker
|
||||||
/// with a used value of `list-style-position: outside`.
|
/// with a used value of `list-style-position: outside`.
|
||||||
const IS_OUTSIDE_LIST_ITEM_MARKER = 1 << 4;
|
const IS_OUTSIDE_LIST_ITEM_MARKER = 1 << 5;
|
||||||
/// Avoid painting the borders, backgrounds, and drop shadow for this fragment, this is used
|
/// Avoid painting the borders, backgrounds, and drop shadow for this fragment, this is used
|
||||||
/// for empty table cells when 'empty-cells' is 'hide' and also table wrappers. This flag
|
/// for empty table cells when 'empty-cells' is 'hide' and also table wrappers. This flag
|
||||||
/// doesn't avoid hit-testing nor does it prevent the painting outlines.
|
/// doesn't avoid hit-testing nor does it prevent the painting outlines.
|
||||||
const DO_NOT_PAINT = 1 << 5;
|
const DO_NOT_PAINT = 1 << 6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -244,7 +244,7 @@ pub(crate) trait ComputedValuesExt {
|
||||||
containing_block_writing_mode: WritingMode,
|
containing_block_writing_mode: WritingMode,
|
||||||
) -> LogicalSides<LengthPercentageOrAuto<'_>>;
|
) -> LogicalSides<LengthPercentageOrAuto<'_>>;
|
||||||
fn has_transform_or_perspective(&self, fragment_flags: FragmentFlags) -> bool;
|
fn has_transform_or_perspective(&self, fragment_flags: FragmentFlags) -> bool;
|
||||||
fn effective_z_index(&self) -> i32;
|
fn effective_z_index(&self, fragment_flags: FragmentFlags) -> i32;
|
||||||
fn establishes_block_formatting_context(&self) -> bool;
|
fn establishes_block_formatting_context(&self) -> bool;
|
||||||
fn establishes_stacking_context(&self, fragment_flags: FragmentFlags) -> bool;
|
fn establishes_stacking_context(&self, fragment_flags: FragmentFlags) -> bool;
|
||||||
fn establishes_scroll_container(&self) -> bool;
|
fn establishes_scroll_container(&self) -> bool;
|
||||||
|
@ -532,9 +532,14 @@ impl ComputedValuesExt for ComputedValues {
|
||||||
/// Get the effective z-index of this fragment. Z-indices only apply to positioned elements
|
/// Get the effective z-index of this fragment. Z-indices only apply to positioned elements
|
||||||
/// per CSS 2 9.9.1 (<http://www.w3.org/TR/CSS2/visuren.html#z-index>), so this value may differ
|
/// per CSS 2 9.9.1 (<http://www.w3.org/TR/CSS2/visuren.html#z-index>), so this value may differ
|
||||||
/// from the value specified in the style.
|
/// from the value specified in the style.
|
||||||
fn effective_z_index(&self) -> i32 {
|
fn effective_z_index(&self, fragment_flags: FragmentFlags) -> i32 {
|
||||||
|
// From <https://drafts.csswg.org/css-flexbox/#painting>:
|
||||||
|
// > Flex items paint exactly the same as inline blocks [CSS2], except that order-modified
|
||||||
|
// > document order is used in place of raw document order, and z-index values other than auto
|
||||||
|
// > create a stacking context even if position is static (behaving exactly as if position
|
||||||
|
// > were relative).
|
||||||
match self.get_box().position {
|
match self.get_box().position {
|
||||||
ComputedPosition::Static => 0,
|
ComputedPosition::Static if !fragment_flags.contains(FragmentFlags::IS_FLEX_ITEM) => 0,
|
||||||
_ => self.get_position().z_index.integer_or(0),
|
_ => self.get_position().z_index.integer_or(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -597,8 +602,16 @@ impl ComputedValuesExt for ComputedValues {
|
||||||
|
|
||||||
// Statically positioned fragments don't establish stacking contexts if the previous
|
// Statically positioned fragments don't establish stacking contexts if the previous
|
||||||
// conditions are not fulfilled. Furthermore, z-index doesn't apply to statically
|
// conditions are not fulfilled. Furthermore, z-index doesn't apply to statically
|
||||||
// positioned fragments.
|
// positioned fragments (except for flex items, see below).
|
||||||
if self.get_box().position == ComputedPosition::Static {
|
//
|
||||||
|
// From <https://drafts.csswg.org/css-flexbox/#painting>:
|
||||||
|
// > Flex items paint exactly the same as inline blocks [CSS2], except that order-modified
|
||||||
|
// > document order is used in place of raw document order, and z-index values other than auto
|
||||||
|
// > create a stacking context even if position is static (behaving exactly as if position
|
||||||
|
// > were relative).
|
||||||
|
if self.get_box().position == ComputedPosition::Static &&
|
||||||
|
!fragment_flags.contains(FragmentFlags::IS_FLEX_ITEM)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
tests/wpt/meta/MANIFEST.json
vendored
13
tests/wpt/meta/MANIFEST.json
vendored
|
@ -167777,6 +167777,19 @@
|
||||||
{}
|
{}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
"flex-item-z-ordering-002.html": [
|
||||||
|
"349c508e7c544ed31dc73f81e11e9058cf8febdb",
|
||||||
|
[
|
||||||
|
null,
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"/css/reference/ref-filled-green-100px-square.xht",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
],
|
||||||
"flex-lines": {
|
"flex-lines": {
|
||||||
"multi-line-wrap-reverse-column-reverse.html": [
|
"multi-line-wrap-reverse-column-reverse.html": [
|
||||||
"48c18fc5362af607854e03fc79fab9abc408fe36",
|
"48c18fc5362af607854e03fc79fab9abc408fe36",
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
[flex-item-z-ordering-001.html]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[flexbox-items-as-stacking-contexts-001.xhtml]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[flexbox-paint-ordering-002.xhtml]
|
|
||||||
expected: FAIL
|
|
32
tests/wpt/tests/css/css-flexbox/flex-item-z-ordering-002.html
vendored
Normal file
32
tests/wpt/tests/css/css-flexbox/flex-item-z-ordering-002.html
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<title>Flex painting order with z-index</title>
|
||||||
|
<link rel="author" title="Martin Robinson" href="mailto:mrobinson@igalia.com">
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/css-flexbox/#painting">
|
||||||
|
<meta name="assert"
|
||||||
|
content="z-index works on flex items even though they do not have `position: relative`" />
|
||||||
|
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#flex {
|
||||||
|
display: flex;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#flex > div {
|
||||||
|
width: 0px;
|
||||||
|
height: 0px;
|
||||||
|
}
|
||||||
|
#flex > div > div {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<p>Test passes if there is a filled green square and <strong>no red</strong>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div id="flex">
|
||||||
|
<div><div style="background: green"></div></div>
|
||||||
|
<div style="z-index: -10"><div style="background: red;"></div></div>
|
||||||
|
</div>
|
Loading…
Add table
Add a link
Reference in a new issue