mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-29 08:11:13 +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: https://github.com/LadybirdBrowser/ladybird/commit/5f74da6ae8a Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1410
|
@ -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
|
||||
{
|
||||
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
|
||||
if (flex_direction == CSS::FlexDirection::Row || flex_direction == CSS::FlexDirection::RowReverse) {
|
||||
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_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_after = item.box->computed_values().padding().bottom().to_px(item.box, width_of_containing_block);
|
||||
item.padding.cross_before = item.box->computed_values().padding().left().to_px(item.box, width_of_containing_block);
|
||||
item.padding.cross_after = item.box->computed_values().padding().right().to_px(item.box, width_of_containing_block);
|
||||
item.padding.main_before = state.padding_top;
|
||||
item.padding.main_after = state.padding_bottom;
|
||||
item.padding.cross_before = state.padding_left;
|
||||
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_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) {
|
||||
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_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());
|
||||
|
|
|
@ -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 const& computed_values = box.computed_values();
|
||||
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_right = CSS::Length::make_auto();
|
||||
auto const border_left = computed_values.border_left().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_right = computed_values.padding().right().to_px(box, width_of_containing_block);
|
||||
auto const padding_left = box_state.padding_left;
|
||||
auto const padding_right = box_state.padding_right;
|
||||
|
||||
auto computed_left = computed_values.inset().left();
|
||||
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.inset_left = left;
|
||||
box_state.inset_right = right;
|
||||
box_state.margin_left = margin_left.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)
|
||||
|
@ -962,7 +960,7 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el
|
|||
auto top = box.computed_values().inset().top();
|
||||
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();
|
||||
|
||||
enum class ClampToZero {
|
||||
|
@ -970,15 +968,16 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el
|
|||
Yes,
|
||||
};
|
||||
|
||||
auto& state = m_state.get(box);
|
||||
auto try_compute_height = [&](CSS::Length height) -> CSS::Length {
|
||||
auto solve_for = [&](CSS::Length length, ClampToZero clamp_to_zero = ClampToZero::No) {
|
||||
auto unclamped_value = height_of_containing_block
|
||||
- top.to_px(box, height_of_containing_block)
|
||||
- margin_top.to_px(box, width_of_containing_block)
|
||||
- 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)
|
||||
- box.computed_values().padding().bottom().to_px(box, width_of_containing_block)
|
||||
- state.padding_bottom
|
||||
- box.computed_values().border_bottom().width
|
||||
- margin_bottom.to_px(box, width_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.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.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.
|
||||
|
@ -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_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);
|
||||
|
||||
// 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();
|
||||
if (computed_values.box_sizing() == CSS::BoxSizing::BorderBox) {
|
||||
auto const padding_left = computed_values.padding().left().resolved(box, width_of_containing_block);
|
||||
auto const padding_right = computed_values.padding().right().resolved(box, width_of_containing_block);
|
||||
|
||||
auto const& state = m_state.get(box);
|
||||
auto inner_width = width.to_px(box, width_of_containing_block)
|
||||
- computed_values.border_left().width
|
||||
- padding_left.to_px(box)
|
||||
- state.padding_left
|
||||
- computed_values.border_right().width
|
||||
- padding_right.to_px(box);
|
||||
- state.padding_right;
|
||||
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& computed_values = box.computed_values();
|
||||
if (computed_values.box_sizing() == CSS::BoxSizing::BorderBox) {
|
||||
auto width_of_containing_block = containing_block_width_for(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 const& state = m_state.get(box);
|
||||
auto inner_height = height.to_px(box, height_of_containing_block)
|
||||
- computed_values.border_top().width
|
||||
- padding_top.to_px(box)
|
||||
- state.padding_top
|
||||
- computed_values.border_bottom().width
|
||||
- padding_bottom.to_px(box);
|
||||
- state.padding_bottom;
|
||||
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_top = box.computed_values().border_top().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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue