Skip to content

Commit

Permalink
layout: Place absolutes in IFCs at their hypothetical static position (
Browse files Browse the repository at this point in the history
…#31418)

Absolutes need to be placed at their hypothetical position as if the
position value was static. This position differs based on the value they
had before blockification. The code for placing absolutes was taking
into account the original display for the inline value, but not for the
block value. A static `display: block` box would placed at a new block
position past the end of the linebox.
  • Loading branch information
mrobinson committed Feb 23, 2024
1 parent 41a41b3 commit 0d4e474
Show file tree
Hide file tree
Showing 9 changed files with 32 additions and 40 deletions.
2 changes: 2 additions & 0 deletions components/layout_2020/dom_traversal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ where
}
}

#[derive(Debug)]
pub(super) enum Contents {
/// Refers to a DOM subtree, plus `::before` and `::after` pseudo-elements.
OfElement,
Expand All @@ -107,6 +108,7 @@ pub(super) enum NonReplacedContents {
OfPseudoElement(Vec<PseudoElementContentItem>),
}

#[derive(Debug)]
pub(super) enum PseudoElementContentItem {
Text(String),
Replaced(ReplacedContent),
Expand Down
52 changes: 27 additions & 25 deletions components/layout_2020/flow/line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use style::properties::ComputedValues;
use style::values::computed::{Length, LengthPercentage};
use style::values::generics::box_::{GenericVerticalAlign, VerticalAlignKeyword};
use style::values::generics::text::LineHeight;
use style::values::specified::box_::DisplayOutside;
use style::values::specified::text::TextDecorationLine;
use style::Zero;
use webrender_api::FontInstanceKey;
Expand All @@ -27,9 +28,7 @@ use crate::geom::{LogicalRect, LogicalVec2};
use crate::positioned::{
relative_adjustement, AbsolutelyPositionedBox, PositioningContext, PositioningContextLength,
};
use crate::style_ext::{
ComputedValuesExt, Display, DisplayGeneratingBox, DisplayOutside, PaddingBorderMargin,
};
use crate::style_ext::{ComputedValuesExt, PaddingBorderMargin};
use crate::ContainingBlock;

pub(super) struct LineMetrics {
Expand Down Expand Up @@ -523,31 +522,34 @@ impl AbsolutelyPositionedLineItem {
fn layout(self, state: &mut LineItemLayoutState) -> ArcRefCell<HoistedSharedFragment> {
let box_ = self.absolutely_positioned_box;
let style = AtomicRef::map(box_.borrow(), |box_| box_.context.style());
let initial_start_corner = match Display::from(style.get_box().original_display) {
Display::GeneratingBox(DisplayGeneratingBox::OutsideInside { outside, inside: _ }) => {

// From https://drafts.csswg.org/css2/#abs-non-replaced-width
// > The static-position containing block is the containing block of a
// > hypothetical box that would have been the first box of the element if its
// > specified position value had been static and its specified float had been
// > none. (Note that due to the rules in section 9.7 this hypothetical
// > calculation might require also assuming a different computed value for
// > display.)
//
// This box is different based on the original `display` value of the
// absolutely positioned element. If it's `inline` it would be placed inline
// at the top of the line, but if it's block it would be placed in a new
// block position after the linebox established by this line.
let initial_start_corner =
if style.get_box().original_display.outside() == DisplayOutside::Inline {
// Top of the line at the current inline position.
LogicalVec2 {
inline: match outside {
DisplayOutside::Inline => {
state.inline_position - state.parent_offset.inline
},
DisplayOutside::Block => Length::zero(),
},
// The blocks start position of the absolute should be at the top of the line.
inline: state.inline_position - state.parent_offset.inline,
block: -state.parent_offset.block,
}
},
Display::GeneratingBox(DisplayGeneratingBox::LayoutInternal(_)) => {
unreachable!(
"The result of blockification should never be a layout-internal value."
);
},
Display::Contents => {
panic!("display:contents does not generate an abspos box")
},
Display::None => {
panic!("display:none does not generate an abspos box")
},
};
} else {
// After the bottom of the line at the start of the inline formatting context.
LogicalVec2 {
inline: Length::zero(),
block: state.line_metrics.block_size - state.parent_offset.block,
}
};

let hoisted_box = AbsolutelyPositionedBox::to_hoisted(
box_.clone(),
initial_start_corner,
Expand Down
6 changes: 3 additions & 3 deletions components/layout_2020/style_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub(crate) enum Display {
GeneratingBox(DisplayGeneratingBox),
}

#[derive(Clone, Copy, Eq, PartialEq)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) enum DisplayGeneratingBox {
OutsideInside {
outside: DisplayOutside,
Expand Down Expand Up @@ -72,13 +72,13 @@ impl DisplayGeneratingBox {
}
}

#[derive(Clone, Copy, Eq, PartialEq)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) enum DisplayOutside {
Block,
Inline,
}

#[derive(Clone, Copy, Eq, PartialEq)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) enum DisplayInside {
// “list-items are limited to the Flow Layout display types”
// <https://drafts.csswg.org/css-display/#list-items>
Expand Down

This file was deleted.

2 changes: 0 additions & 2 deletions tests/wpt/meta/css/CSS2/positioning/abspos-007.xht.ini

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

0 comments on commit 0d4e474

Please sign in to comment.