Skip to content

Commit

Permalink
web/core: Respect CSS "clear" property during layout
Browse files Browse the repository at this point in the history
  • Loading branch information
simonwuelker committed Dec 7, 2023
1 parent 6976edb commit 9850d70
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 0 deletions.
22 changes: 22 additions & 0 deletions crates/web/core/src/css/layout/flow/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,9 +295,29 @@ impl<'box_tree, 'formatting_context> BlockFlowState<'box_tree, 'formatting_conte
}
}

fn respect_clearance(&mut self, clear: &values::Clear) {
let clear_to = match clear {
values::Clear::Left => self.block_formatting_context.float_context.clear_left(),
values::Clear::Right => self.block_formatting_context.float_context.clear_right(),
values::Clear::Both => self.block_formatting_context.float_context.clear_both(),
_ => return,
};

log::info!("cursor {:?}, clear to {:?}", self.cursor.y, clear_to);
if self.cursor.y < clear_to {
// Introduce "clearance".
// This prevents margin collapse
self.block_formatting_context.prevent_margin_collapse();

self.cursor.y = clear_to;
}
}

pub fn visit_block_box(&mut self, block_box: &'box_tree BlockLevelBox) {
match block_box {
BlockLevelBox::Floating(float_box) => {
self.respect_clearance(float_box.style.clear());

// Floats are placed at or below the flow position
self.block_formatting_context
.float_context
Expand All @@ -312,6 +332,8 @@ impl<'box_tree, 'formatting_context> BlockFlowState<'box_tree, 'formatting_conte
self.fragments_so_far.push(box_fragment.into())
},
BlockLevelBox::InFlow(in_flow_box) => {
self.respect_clearance(in_flow_box.style.clear());

// Every block box creates exactly one box fragment
let box_fragment = in_flow_box.fragment(
self.cursor,
Expand Down
29 changes: 29 additions & 0 deletions crates/web/core/src/css/layout/flow/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ pub struct FloatContext {

/// Describes how the available space is reduced by floating elements
content_bands: Vec<ContentBand>,

lowest_float_left: Pixels,
lowest_float_right: Pixels,
}

impl FloatContext {
Expand All @@ -193,9 +196,26 @@ impl FloatContext {
float_ceiling: Pixels::ZERO,
containing_block,
content_bands: vec![content_band],
lowest_float_left: Pixels::ZERO,
lowest_float_right: Pixels::ZERO,
}
}

#[must_use]
pub fn clear_left(&self) -> Pixels {
self.lowest_float_left
}

#[must_use]
pub fn clear_right(&self) -> Pixels {
self.lowest_float_right
}

#[must_use]
pub fn clear_both(&self) -> Pixels {
self.lowest_float_left.max(self.lowest_float_right)
}

pub fn lower_float_ceiling(&mut self, new_ceiling: Pixels) {
self.float_ceiling = new_ceiling;
}
Expand Down Expand Up @@ -250,6 +270,15 @@ impl FloatContext {

// Lower the float ceiling: New floats may not appear above this box
self.lower_float_ceiling(placement.position.y);

match side {
Side::Left => {
self.lowest_float_left = placement.position.y + margin_area.height;
},
Side::Right => {
self.lowest_float_right = placement.position.y + margin_area.height;
},
}
}

fn find_position_for_float(&self, float_width: Pixels, side: Side) -> Placement {
Expand Down

0 comments on commit 9850d70

Please sign in to comment.