mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-05 23:59:49 +00:00
LibWeb: Resolve "position: sticky" insets relative to scrollport
Reading of https://drafts.csswg.org/css-position revealed I was wrong assuming sticky insets need to be resolved relative to containing block.
This commit is contained in:
parent
dcbb073b3e
commit
415ea4ec0c
Notes:
github-actions[bot]
2024-09-03 09:35:18 +00:00
Author: https://github.com/kalenikaliaksandr
Commit: 415ea4ec0c
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1260
3 changed files with 80 additions and 4 deletions
|
@ -0,0 +1,28 @@
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
scrollbar-width: 0;
|
||||||
|
}
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.sticky {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background-color: cyan;
|
||||||
|
border-top: 20px solid magenta;
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
#scrollable {
|
||||||
|
width: 300px;
|
||||||
|
height: 200px;
|
||||||
|
overflow: auto;
|
||||||
|
position: relative;
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div id="scrollable">
|
||||||
|
<div style="height: 10000px"><div class="sticky">I'm sticky</div></div>
|
||||||
|
</div>
|
29
Tests/LibWeb/Ref/sticky-box-with-percentage-insets.html
Normal file
29
Tests/LibWeb/Ref/sticky-box-with-percentage-insets.html
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<link rel="match" href="reference/sticky-box-with-percentage-insets-ref.html" />
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
scrollbar-width: 0;
|
||||||
|
}
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.sticky {
|
||||||
|
position: sticky;
|
||||||
|
top: 50%;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background-color: cyan;
|
||||||
|
border-top: 20px solid magenta;
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
#scrollable {
|
||||||
|
width: 300px;
|
||||||
|
height: 200px;
|
||||||
|
overflow: auto;
|
||||||
|
position: relative;
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div id="scrollable">
|
||||||
|
<div style="height: 10000px"><div class="sticky">I'm sticky</div></div>
|
||||||
|
</div>
|
|
@ -376,21 +376,40 @@ void LayoutState::commit(Box& root)
|
||||||
auto& paintable_box = const_cast<Painting::PaintableBox&>(*box.paintable_box());
|
auto& paintable_box = const_cast<Painting::PaintableBox&>(*box.paintable_box());
|
||||||
if (!paintable_box.scroll_offset().is_zero())
|
if (!paintable_box.scroll_offset().is_zero())
|
||||||
paintable_box.set_scroll_offset(paintable_box.scroll_offset());
|
paintable_box.set_scroll_offset(paintable_box.scroll_offset());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& it : used_values_per_layout_node) {
|
||||||
|
auto& used_values = *it.value;
|
||||||
|
if (!used_values.node().is_box())
|
||||||
|
continue;
|
||||||
|
auto const& box = static_cast<Layout::Box const&>(used_values.node());
|
||||||
|
|
||||||
|
auto& paintable_box = const_cast<Painting::PaintableBox&>(*box.paintable_box());
|
||||||
|
|
||||||
if (box.is_sticky_position()) {
|
if (box.is_sticky_position()) {
|
||||||
|
// https://drafts.csswg.org/css-position/#insets
|
||||||
|
// For sticky positioned boxes, the inset is instead relative to the relevant scrollport’s size. Negative values are allowed.
|
||||||
|
|
||||||
auto sticky_insets = make<Painting::PaintableBox::StickyInsets>();
|
auto sticky_insets = make<Painting::PaintableBox::StickyInsets>();
|
||||||
auto const& inset = box.computed_values().inset();
|
auto const& inset = box.computed_values().inset();
|
||||||
|
|
||||||
|
auto const* nearest_scrollable_ancestor = paintable_box.nearest_scrollable_ancestor();
|
||||||
|
CSSPixelSize scrollport_size;
|
||||||
|
if (nearest_scrollable_ancestor) {
|
||||||
|
scrollport_size = nearest_scrollable_ancestor->absolute_rect().size();
|
||||||
|
}
|
||||||
|
|
||||||
if (!inset.top().is_auto()) {
|
if (!inset.top().is_auto()) {
|
||||||
sticky_insets->top = inset.top().to_px(box, used_values.containing_block_used_values()->content_height());
|
sticky_insets->top = inset.top().to_px(box, scrollport_size.height());
|
||||||
}
|
}
|
||||||
if (!inset.right().is_auto()) {
|
if (!inset.right().is_auto()) {
|
||||||
sticky_insets->right = inset.right().to_px(box, used_values.containing_block_used_values()->content_width());
|
sticky_insets->right = inset.right().to_px(box, scrollport_size.width());
|
||||||
}
|
}
|
||||||
if (!inset.bottom().is_auto()) {
|
if (!inset.bottom().is_auto()) {
|
||||||
sticky_insets->bottom = inset.bottom().to_px(box, used_values.containing_block_used_values()->content_height());
|
sticky_insets->bottom = inset.bottom().to_px(box, scrollport_size.height());
|
||||||
}
|
}
|
||||||
if (!inset.left().is_auto()) {
|
if (!inset.left().is_auto()) {
|
||||||
sticky_insets->left = inset.left().to_px(box, used_values.containing_block_used_values()->content_width());
|
sticky_insets->left = inset.left().to_px(box, scrollport_size.width());
|
||||||
}
|
}
|
||||||
paintable_box.set_sticky_insets(move(sticky_insets));
|
paintable_box.set_sticky_insets(move(sticky_insets));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue