mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 11:27:35 +00:00
LibWeb: Narrow width of boxes that create BFC to avoid overlap of float
https://www.w3.org/TR/CSS22/visuren.html#floats says that when a box establishes BFC it should not overlap with floats. The way to avoid overlaps is up to implementor. This change implements avoiding overlap by narrowing width of a box because it seems like what other engines do (in the scenarios I tested).
This commit is contained in:
parent
bf41af6b9d
commit
853ecb8d8e
3 changed files with 71 additions and 10 deletions
|
@ -0,0 +1,22 @@
|
|||
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||
BlockContainer <html> at (0,0) content-size 800x1008 [BFC] children: not-inline
|
||||
BlockContainer <body> at (8,8) content-size 784x108.21875 children: not-inline
|
||||
BlockContainer <div.wrapper> at (8,8) content-size 784x108.21875 children: not-inline
|
||||
BlockContainer <div.float> at (592,8) content-size 200x1000 floating [BFC] children: not-inline
|
||||
BlockContainer <div.bfc> at (18,18) content-size 564x88.21875 [BFC] children: inline
|
||||
line 0 width: 458.125, height: 17.46875, bottom: 17.46875, baseline: 13.53125
|
||||
frag 0 from TextNode start: 0, length: 56, rect: [18,18 458.125x17.46875]
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||
line 1 width: 511.796875, height: 17.9375, bottom: 35.40625, baseline: 13.53125
|
||||
frag 0 from TextNode start: 57, length: 60, rect: [18,35 511.796875x17.46875]
|
||||
"Pellentesque vitae neque nunc. Nam fermentum libero a lectus"
|
||||
line 2 width: 537.078125, height: 18.40625, bottom: 53.34375, baseline: 13.53125
|
||||
frag 0 from TextNode start: 118, length: 67, rect: [18,52 537.078125x17.46875]
|
||||
"vulputate eleifend. Nam sagittis tristique augue, id sodales mauris"
|
||||
line 3 width: 537.34375, height: 17.875, bottom: 70.28125, baseline: 13.53125
|
||||
frag 0 from TextNode start: 186, length: 65, rect: [18,70 537.34375x17.46875]
|
||||
"suscipit at. Vivamus eget placerat ex. Suspendisse potenti. Morbi"
|
||||
line 4 width: 455.375, height: 18.34375, bottom: 88.21875, baseline: 13.53125
|
||||
frag 0 from TextNode start: 252, length: 57, rect: [18,87 455.375x17.46875]
|
||||
"pulvinar ipsum eget nulla dapibus, ac varius mi eleifend."
|
||||
TextNode <#text>
|
|
@ -0,0 +1,23 @@
|
|||
<style>
|
||||
* {
|
||||
font-family: 'SerenitySans';
|
||||
}
|
||||
|
||||
.float {
|
||||
width: 200px;
|
||||
height: 1000px;
|
||||
background-color: royalblue;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.bfc {
|
||||
background-color: mediumseagreen;
|
||||
border: 10px solid skyblue;
|
||||
display: flow-root;
|
||||
}
|
||||
</style>
|
||||
<div class="wrapper"><div class="float"></div><div class="bfc">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque vitae
|
||||
neque nunc. Nam fermentum libero a lectus vulputate eleifend. Nam sagittis
|
||||
tristique augue, id sodales mauris suscipit at. Vivamus eget placerat ex.
|
||||
Suspendisse potenti. Morbi pulvinar ipsum eget nulla dapibus, ac varius mi
|
||||
eleifend.
|
|
@ -115,12 +115,28 @@ void BlockFormattingContext::compute_width(Box const& box, AvailableSpace const&
|
|||
return;
|
||||
}
|
||||
|
||||
auto remaining_available_space = available_space;
|
||||
if (available_space.width.is_definite() && creates_block_formatting_context(box)) {
|
||||
// 9.5 Floats
|
||||
// The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a
|
||||
// new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap the margin
|
||||
// box of any floats in the same block formatting context as the element itself. If necessary, implementations should
|
||||
// clear the said element by placing it below any preceding floats, but may place it adjacent to such floats if there is
|
||||
// sufficient space. They may even make the border box of said element narrower than defined by section 10.3.3.
|
||||
// CSS2 does not define when a UA may put said element next to the float or by how much said element may
|
||||
// become narrower.
|
||||
auto box_in_root_rect = content_box_rect_in_ancestor_coordinate_space(box, root(), m_state);
|
||||
auto space = space_used_by_floats(box_in_root_rect.y());
|
||||
auto remaining_width = available_space.width.to_px() - space.left - space.right;
|
||||
remaining_available_space.width = AvailableSize::make_definite(remaining_width);
|
||||
}
|
||||
|
||||
if (is<ReplacedBox>(box)) {
|
||||
// FIXME: This should not be done *by* ReplacedBox
|
||||
auto& replaced = verify_cast<ReplacedBox>(box);
|
||||
// FIXME: This const_cast is gross.
|
||||
const_cast<ReplacedBox&>(replaced).prepare_for_replaced_layout();
|
||||
compute_width_for_block_level_replaced_element_in_normal_flow(replaced, available_space);
|
||||
compute_width_for_block_level_replaced_element_in_normal_flow(replaced, remaining_available_space);
|
||||
// NOTE: We don't return here.
|
||||
}
|
||||
|
||||
|
@ -131,8 +147,8 @@ void BlockFormattingContext::compute_width(Box const& box, AvailableSpace const&
|
|||
|
||||
auto const& computed_values = box.computed_values();
|
||||
|
||||
auto width_of_containing_block = available_space.width.to_px();
|
||||
auto width_of_containing_block_as_length_for_resolve = available_space.width.is_definite() ? CSS::Length::make_px(width_of_containing_block) : CSS::Length::make_px(0);
|
||||
auto width_of_containing_block = remaining_available_space.width.to_px();
|
||||
auto width_of_containing_block_as_length_for_resolve = remaining_available_space.width.is_definite() ? CSS::Length::make_px(width_of_containing_block) : CSS::Length::make_px(0);
|
||||
|
||||
auto zero_value = CSS::Length::make_px(0);
|
||||
|
||||
|
@ -216,10 +232,10 @@ void BlockFormattingContext::compute_width(Box const& box, AvailableSpace const&
|
|||
return CSS::Length::make_px(box_state.content_width());
|
||||
}
|
||||
if (is<TableWrapper>(box))
|
||||
return CSS::Length::make_px(compute_width_for_table_wrapper(box, available_space));
|
||||
if (should_treat_width_as_auto(box, available_space))
|
||||
return CSS::Length::make_px(compute_width_for_table_wrapper(box, remaining_available_space));
|
||||
if (should_treat_width_as_auto(box, remaining_available_space))
|
||||
return CSS::Length::make_auto();
|
||||
return calculate_inner_width(box, available_space.width, computed_values.width());
|
||||
return calculate_inner_width(box, remaining_available_space.width, computed_values.width());
|
||||
}();
|
||||
|
||||
// 1. The tentative used width is calculated (without 'min-width' and 'max-width')
|
||||
|
@ -228,8 +244,8 @@ void BlockFormattingContext::compute_width(Box const& box, AvailableSpace const&
|
|||
// 2. The tentative used width is greater than 'max-width', the rules above are applied again,
|
||||
// but this time using the computed value of 'max-width' as the computed value for 'width'.
|
||||
if (!computed_values.max_width().is_none()) {
|
||||
auto max_width = calculate_inner_width(box, available_space.width, computed_values.max_width());
|
||||
auto used_width_px = used_width.is_auto() ? available_space.width.to_px() : used_width.to_px(box);
|
||||
auto max_width = calculate_inner_width(box, remaining_available_space.width, computed_values.max_width());
|
||||
auto used_width_px = used_width.is_auto() ? remaining_available_space.width.to_px() : used_width.to_px(box);
|
||||
if (used_width_px > max_width.to_px(box)) {
|
||||
used_width = try_compute_width(max_width);
|
||||
}
|
||||
|
@ -238,8 +254,8 @@ void BlockFormattingContext::compute_width(Box const& box, AvailableSpace const&
|
|||
// 3. If the resulting width is smaller than 'min-width', the rules above are applied again,
|
||||
// but this time using the value of 'min-width' as the computed value for 'width'.
|
||||
if (!computed_values.min_width().is_auto()) {
|
||||
auto min_width = calculate_inner_width(box, available_space.width, computed_values.min_width());
|
||||
auto used_width_px = used_width.is_auto() ? available_space.width.to_px() : used_width.to_px(box);
|
||||
auto min_width = calculate_inner_width(box, remaining_available_space.width, computed_values.min_width());
|
||||
auto used_width_px = used_width.is_auto() ? remaining_available_space.width.to_px() : used_width.to_px(box);
|
||||
if (used_width_px < min_width.to_px(box)) {
|
||||
used_width = try_compute_width(min_width);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue