mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-26 04:07:51 +00:00
LibWeb: Fix "box-sizing: border-box" resolution for abspos items
The `calculate_inner_width()` and `calculate_inner_height()` resolve percentage paddings using the width returned by `containing_block_width_for()`. However, this function does not account for grids where the containing block is defined by the grid area to which an item belongs. This change fixes the issue by modifying `calculate_inner_width()` and `calculate_inner_height()` to use the already resolved paddings from the layout state. Corresponding changes ensure that paddings are resolved and saved in the state before box-sizing is handled. As a side effect, this change also improves abspos layout for BFC where now paddings are resolved using padding box of containing block instead of content box of containing block.
This commit is contained in:
parent
805b0fed13
commit
5f74da6ae8
Notes:
github-actions[bot]
2024-09-17 05:57:08 +00:00
Author: https://github.com/kalenikaliaksandr
Commit: 5f74da6ae8
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1410
7 changed files with 105 additions and 31 deletions
|
@ -0,0 +1,11 @@
|
||||||
|
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||||
|
BlockContainer <html> at (1,1) content-size 798x330 [BFC] children: not-inline
|
||||||
|
BlockContainer <body> at (10,10) content-size 780x312 children: not-inline
|
||||||
|
BlockContainer <div.box> at (31,21) content-size 200x200 positioned children: not-inline
|
||||||
|
BlockContainer <div.inner> at (66,76) content-size 100x100 positioned [BFC] children: not-inline
|
||||||
|
|
||||||
|
ViewportPaintable (Viewport<#document>) [0,0 800x600]
|
||||||
|
PaintableWithLines (BlockContainer<HTML>) [0,0 800x332]
|
||||||
|
PaintableWithLines (BlockContainer<BODY>) [9,9 782x314]
|
||||||
|
PaintableWithLines (BlockContainer<DIV>.box) [10,10 272x312]
|
||||||
|
PaintableWithLines (BlockContainer<DIV>.inner) [11,21 210x210]
|
|
@ -0,0 +1,11 @@
|
||||||
|
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||||
|
BlockContainer <html> at (1,1) content-size 798x120 [BFC] children: not-inline
|
||||||
|
BlockContainer <body> at (10,10) content-size 780x102 children: not-inline
|
||||||
|
Box <div.grid> at (11,11) content-size 200x100 positioned [GFC] children: not-inline
|
||||||
|
BlockContainer <div.abspos-item> at (122,22) content-size 28x28 positioned [BFC] children: not-inline
|
||||||
|
|
||||||
|
ViewportPaintable (Viewport<#document>) [0,0 800x600]
|
||||||
|
PaintableWithLines (BlockContainer<HTML>) [0,0 800x122]
|
||||||
|
PaintableWithLines (BlockContainer<BODY>) [9,9 782x104]
|
||||||
|
PaintableBox (Box<DIV>.grid) [10,10 202x102]
|
||||||
|
PaintableWithLines (BlockContainer<DIV>.abspos-item) [111,11 50x50]
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!DOCTYPE html><style>
|
||||||
|
* {
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box {
|
||||||
|
position: relative;
|
||||||
|
padding: 10px 50px 100px 20px;
|
||||||
|
background-color: mediumseagreen;
|
||||||
|
width: 200px;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inner {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
width : 100px;
|
||||||
|
height: 100px;
|
||||||
|
padding: 20%;
|
||||||
|
background-color: magenta;
|
||||||
|
}
|
||||||
|
</style><div class="box"><div class="inner"></div></div>
|
|
@ -0,0 +1,27 @@
|
||||||
|
<!DOCTYPE html><style>
|
||||||
|
* {
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 100px 100px;
|
||||||
|
grid-template-areas: "a b";
|
||||||
|
position: relative;
|
||||||
|
width: 200px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abspos-item {
|
||||||
|
position: absolute;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 10%;
|
||||||
|
background-color: magenta;
|
||||||
|
background-clip: content-box;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
grid-area: b;
|
||||||
|
}
|
||||||
|
</style><div class="grid"><div class="abspos-item"></div></div>
|
|
@ -216,6 +216,13 @@ bool FlexFormattingContext::is_direction_reverse() const
|
||||||
void FlexFormattingContext::populate_specified_margins(FlexItem& item, CSS::FlexDirection flex_direction) const
|
void FlexFormattingContext::populate_specified_margins(FlexItem& item, CSS::FlexDirection flex_direction) const
|
||||||
{
|
{
|
||||||
auto width_of_containing_block = m_flex_container_state.content_width();
|
auto width_of_containing_block = m_flex_container_state.content_width();
|
||||||
|
|
||||||
|
auto& state = m_state.get_mutable(*item.box);
|
||||||
|
state.padding_left = item.box->computed_values().padding().left().to_px(item.box, width_of_containing_block);
|
||||||
|
state.padding_right = item.box->computed_values().padding().right().to_px(item.box, width_of_containing_block);
|
||||||
|
state.padding_top = item.box->computed_values().padding().top().to_px(item.box, width_of_containing_block);
|
||||||
|
state.padding_bottom = item.box->computed_values().padding().bottom().to_px(item.box, width_of_containing_block);
|
||||||
|
|
||||||
// FIXME: This should also take reverse-ness into account
|
// FIXME: This should also take reverse-ness into account
|
||||||
if (flex_direction == CSS::FlexDirection::Row || flex_direction == CSS::FlexDirection::RowReverse) {
|
if (flex_direction == CSS::FlexDirection::Row || flex_direction == CSS::FlexDirection::RowReverse) {
|
||||||
item.borders.main_before = item.box->computed_values().border_left().width;
|
item.borders.main_before = item.box->computed_values().border_left().width;
|
||||||
|
@ -243,10 +250,10 @@ void FlexFormattingContext::populate_specified_margins(FlexItem& item, CSS::Flex
|
||||||
item.borders.cross_before = item.box->computed_values().border_left().width;
|
item.borders.cross_before = item.box->computed_values().border_left().width;
|
||||||
item.borders.cross_after = item.box->computed_values().border_right().width;
|
item.borders.cross_after = item.box->computed_values().border_right().width;
|
||||||
|
|
||||||
item.padding.main_before = item.box->computed_values().padding().top().to_px(item.box, width_of_containing_block);
|
item.padding.main_before = state.padding_top;
|
||||||
item.padding.main_after = item.box->computed_values().padding().bottom().to_px(item.box, width_of_containing_block);
|
item.padding.main_after = state.padding_bottom;
|
||||||
item.padding.cross_before = item.box->computed_values().padding().left().to_px(item.box, width_of_containing_block);
|
item.padding.cross_before = state.padding_left;
|
||||||
item.padding.cross_after = item.box->computed_values().padding().right().to_px(item.box, width_of_containing_block);
|
item.padding.cross_after = state.padding_right;
|
||||||
|
|
||||||
item.margins.main_before = item.box->computed_values().margin().top().to_px(item.box, width_of_containing_block);
|
item.margins.main_before = item.box->computed_values().margin().top().to_px(item.box, width_of_containing_block);
|
||||||
item.margins.main_after = item.box->computed_values().margin().bottom().to_px(item.box, width_of_containing_block);
|
item.margins.main_after = item.box->computed_values().margin().bottom().to_px(item.box, width_of_containing_block);
|
||||||
|
@ -1604,11 +1611,6 @@ void FlexFormattingContext::copy_dimensions_from_flex_items_to_boxes()
|
||||||
for (auto& item : m_flex_items) {
|
for (auto& item : m_flex_items) {
|
||||||
auto const& box = item.box;
|
auto const& box = item.box;
|
||||||
|
|
||||||
item.used_values.padding_left = box->computed_values().padding().left().to_px(box, m_flex_container_state.content_width());
|
|
||||||
item.used_values.padding_right = box->computed_values().padding().right().to_px(box, m_flex_container_state.content_width());
|
|
||||||
item.used_values.padding_top = box->computed_values().padding().top().to_px(box, m_flex_container_state.content_width());
|
|
||||||
item.used_values.padding_bottom = box->computed_values().padding().bottom().to_px(box, m_flex_container_state.content_width());
|
|
||||||
|
|
||||||
item.used_values.margin_left = box->computed_values().margin().left().to_px(box, m_flex_container_state.content_width());
|
item.used_values.margin_left = box->computed_values().margin().left().to_px(box, m_flex_container_state.content_width());
|
||||||
item.used_values.margin_right = box->computed_values().margin().right().to_px(box, m_flex_container_state.content_width());
|
item.used_values.margin_right = box->computed_values().margin().right().to_px(box, m_flex_container_state.content_width());
|
||||||
item.used_values.margin_top = box->computed_values().margin().top().to_px(box, m_flex_container_state.content_width());
|
item.used_values.margin_top = box->computed_values().margin().top().to_px(box, m_flex_container_state.content_width());
|
||||||
|
|
|
@ -667,13 +667,14 @@ void FormattingContext::compute_width_for_absolutely_positioned_non_replaced_ele
|
||||||
auto width_of_containing_block = available_space.width.to_px_or_zero();
|
auto width_of_containing_block = available_space.width.to_px_or_zero();
|
||||||
auto const& computed_values = box.computed_values();
|
auto const& computed_values = box.computed_values();
|
||||||
auto zero_value = CSS::Length::make_px(0);
|
auto zero_value = CSS::Length::make_px(0);
|
||||||
|
auto& box_state = m_state.get_mutable(box);
|
||||||
|
|
||||||
auto margin_left = CSS::Length::make_auto();
|
auto margin_left = CSS::Length::make_auto();
|
||||||
auto margin_right = CSS::Length::make_auto();
|
auto margin_right = CSS::Length::make_auto();
|
||||||
auto const border_left = computed_values.border_left().width;
|
auto const border_left = computed_values.border_left().width;
|
||||||
auto const border_right = computed_values.border_right().width;
|
auto const border_right = computed_values.border_right().width;
|
||||||
auto const padding_left = computed_values.padding().left().to_px(box, width_of_containing_block);
|
auto const padding_left = box_state.padding_left;
|
||||||
auto const padding_right = computed_values.padding().right().to_px(box, width_of_containing_block);
|
auto const padding_right = box_state.padding_right;
|
||||||
|
|
||||||
auto computed_left = computed_values.inset().left();
|
auto computed_left = computed_values.inset().left();
|
||||||
auto computed_right = computed_values.inset().right();
|
auto computed_right = computed_values.inset().right();
|
||||||
|
@ -835,14 +836,11 @@ void FormattingContext::compute_width_for_absolutely_positioned_non_replaced_ele
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& box_state = m_state.get_mutable(box);
|
|
||||||
box_state.set_content_width(used_width.to_px(box));
|
box_state.set_content_width(used_width.to_px(box));
|
||||||
box_state.inset_left = left;
|
box_state.inset_left = left;
|
||||||
box_state.inset_right = right;
|
box_state.inset_right = right;
|
||||||
box_state.margin_left = margin_left.to_px(box);
|
box_state.margin_left = margin_left.to_px(box);
|
||||||
box_state.margin_right = margin_right.to_px(box);
|
box_state.margin_right = margin_right.to_px(box);
|
||||||
box_state.padding_left = padding_left;
|
|
||||||
box_state.padding_right = padding_right;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FormattingContext::compute_width_for_absolutely_positioned_replaced_element(Box const& box, AvailableSpace const& available_space)
|
void FormattingContext::compute_width_for_absolutely_positioned_replaced_element(Box const& box, AvailableSpace const& available_space)
|
||||||
|
@ -962,7 +960,7 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el
|
||||||
auto top = box.computed_values().inset().top();
|
auto top = box.computed_values().inset().top();
|
||||||
auto bottom = box.computed_values().inset().bottom();
|
auto bottom = box.computed_values().inset().bottom();
|
||||||
|
|
||||||
auto width_of_containing_block = containing_block_width_for(box);
|
auto width_of_containing_block = available_space.width.to_px_or_zero();
|
||||||
auto height_of_containing_block = available_space.height.to_px_or_zero();
|
auto height_of_containing_block = available_space.height.to_px_or_zero();
|
||||||
|
|
||||||
enum class ClampToZero {
|
enum class ClampToZero {
|
||||||
|
@ -970,15 +968,16 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el
|
||||||
Yes,
|
Yes,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto& state = m_state.get(box);
|
||||||
auto try_compute_height = [&](CSS::Length height) -> CSS::Length {
|
auto try_compute_height = [&](CSS::Length height) -> CSS::Length {
|
||||||
auto solve_for = [&](CSS::Length length, ClampToZero clamp_to_zero = ClampToZero::No) {
|
auto solve_for = [&](CSS::Length length, ClampToZero clamp_to_zero = ClampToZero::No) {
|
||||||
auto unclamped_value = height_of_containing_block
|
auto unclamped_value = height_of_containing_block
|
||||||
- top.to_px(box, height_of_containing_block)
|
- top.to_px(box, height_of_containing_block)
|
||||||
- margin_top.to_px(box, width_of_containing_block)
|
- margin_top.to_px(box, width_of_containing_block)
|
||||||
- box.computed_values().border_top().width
|
- box.computed_values().border_top().width
|
||||||
- box.computed_values().padding().top().to_px(box, width_of_containing_block)
|
- state.padding_top
|
||||||
- apply_min_max_height_constraints(height).to_px(box)
|
- apply_min_max_height_constraints(height).to_px(box)
|
||||||
- box.computed_values().padding().bottom().to_px(box, width_of_containing_block)
|
- state.padding_bottom
|
||||||
- box.computed_values().border_bottom().width
|
- box.computed_values().border_bottom().width
|
||||||
- margin_bottom.to_px(box, width_of_containing_block)
|
- margin_bottom.to_px(box, width_of_containing_block)
|
||||||
- bottom.to_px(box, height_of_containing_block)
|
- bottom.to_px(box, height_of_containing_block)
|
||||||
|
@ -1157,8 +1156,6 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el
|
||||||
box_state.inset_bottom = bottom.to_px(box, height_of_containing_block);
|
box_state.inset_bottom = bottom.to_px(box, height_of_containing_block);
|
||||||
box_state.margin_top = margin_top.to_px(box, width_of_containing_block);
|
box_state.margin_top = margin_top.to_px(box, width_of_containing_block);
|
||||||
box_state.margin_bottom = margin_bottom.to_px(box, width_of_containing_block);
|
box_state.margin_bottom = margin_bottom.to_px(box, width_of_containing_block);
|
||||||
box_state.padding_top = box.computed_values().padding().top().to_px(box, width_of_containing_block);
|
|
||||||
box_state.padding_bottom = box.computed_values().padding().bottom().to_px(box, width_of_containing_block);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: This is different from content_box_rect_in_ancestor_coordinate_space() as this does *not* follow the containing block chain up, but rather the parent() chain.
|
// NOTE: This is different from content_box_rect_in_ancestor_coordinate_space() as this does *not* follow the containing block chain up, but rather the parent() chain.
|
||||||
|
@ -1241,6 +1238,12 @@ void FormattingContext::layout_absolutely_positioned_element(Box const& box, Ava
|
||||||
box_state.border_top = box.computed_values().border_top().width;
|
box_state.border_top = box.computed_values().border_top().width;
|
||||||
box_state.border_bottom = box.computed_values().border_bottom().width;
|
box_state.border_bottom = box.computed_values().border_bottom().width;
|
||||||
|
|
||||||
|
auto const containing_block_width = available_space.width.to_px_or_zero();
|
||||||
|
box_state.padding_left = box.computed_values().padding().left().to_px(box, containing_block_width);
|
||||||
|
box_state.padding_right = box.computed_values().padding().right().to_px(box, containing_block_width);
|
||||||
|
box_state.padding_top = box.computed_values().padding().top().to_px(box, containing_block_width);
|
||||||
|
box_state.padding_bottom = box.computed_values().padding().bottom().to_px(box, containing_block_width);
|
||||||
|
|
||||||
compute_width_for_absolutely_positioned_element(box, available_space);
|
compute_width_for_absolutely_positioned_element(box, available_space);
|
||||||
|
|
||||||
// NOTE: We compute height before *and* after doing inside layout.
|
// NOTE: We compute height before *and* after doing inside layout.
|
||||||
|
@ -1625,14 +1628,12 @@ CSSPixels FormattingContext::calculate_inner_width(Layout::Box const& box, Avail
|
||||||
|
|
||||||
auto& computed_values = box.computed_values();
|
auto& computed_values = box.computed_values();
|
||||||
if (computed_values.box_sizing() == CSS::BoxSizing::BorderBox) {
|
if (computed_values.box_sizing() == CSS::BoxSizing::BorderBox) {
|
||||||
auto const padding_left = computed_values.padding().left().resolved(box, width_of_containing_block);
|
auto const& state = m_state.get(box);
|
||||||
auto const padding_right = computed_values.padding().right().resolved(box, width_of_containing_block);
|
|
||||||
|
|
||||||
auto inner_width = width.to_px(box, width_of_containing_block)
|
auto inner_width = width.to_px(box, width_of_containing_block)
|
||||||
- computed_values.border_left().width
|
- computed_values.border_left().width
|
||||||
- padding_left.to_px(box)
|
- state.padding_left
|
||||||
- computed_values.border_right().width
|
- computed_values.border_right().width
|
||||||
- padding_right.to_px(box);
|
- state.padding_right;
|
||||||
return max(inner_width, 0);
|
return max(inner_width, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1645,16 +1646,12 @@ CSSPixels FormattingContext::calculate_inner_height(Layout::Box const& box, Avai
|
||||||
auto height_of_containing_block = available_height.to_px_or_zero();
|
auto height_of_containing_block = available_height.to_px_or_zero();
|
||||||
auto& computed_values = box.computed_values();
|
auto& computed_values = box.computed_values();
|
||||||
if (computed_values.box_sizing() == CSS::BoxSizing::BorderBox) {
|
if (computed_values.box_sizing() == CSS::BoxSizing::BorderBox) {
|
||||||
auto width_of_containing_block = containing_block_width_for(box);
|
auto const& state = m_state.get(box);
|
||||||
|
|
||||||
auto const padding_top = computed_values.padding().top().resolved(box, width_of_containing_block);
|
|
||||||
auto const padding_bottom = computed_values.padding().bottom().resolved(box, width_of_containing_block);
|
|
||||||
|
|
||||||
auto inner_height = height.to_px(box, height_of_containing_block)
|
auto inner_height = height.to_px(box, height_of_containing_block)
|
||||||
- computed_values.border_top().width
|
- computed_values.border_top().width
|
||||||
- padding_top.to_px(box)
|
- state.padding_top
|
||||||
- computed_values.border_bottom().width
|
- computed_values.border_bottom().width
|
||||||
- padding_bottom.to_px(box);
|
- state.padding_bottom;
|
||||||
return max(inner_height, 0);
|
return max(inner_height, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1923,6 +1923,10 @@ void GridFormattingContext::layout_absolutely_positioned_element(Box const& box)
|
||||||
box_state.border_right = box.computed_values().border_right().width;
|
box_state.border_right = box.computed_values().border_right().width;
|
||||||
box_state.border_top = box.computed_values().border_top().width;
|
box_state.border_top = box.computed_values().border_top().width;
|
||||||
box_state.border_bottom = box.computed_values().border_bottom().width;
|
box_state.border_bottom = box.computed_values().border_bottom().width;
|
||||||
|
box_state.padding_left = box.computed_values().padding().left().to_px(grid_container(), grid_area_rect.width());
|
||||||
|
box_state.padding_right = box.computed_values().padding().right().to_px(grid_container(), grid_area_rect.width());
|
||||||
|
box_state.padding_top = box.computed_values().padding().top().to_px(grid_container(), grid_area_rect.width());
|
||||||
|
box_state.padding_bottom = box.computed_values().padding().bottom().to_px(grid_container(), grid_area_rect.width());
|
||||||
|
|
||||||
compute_width_for_absolutely_positioned_element(box, available_space);
|
compute_width_for_absolutely_positioned_element(box, available_space);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue