Skip to content

Commit 0406533

Browse files
kalenikaliaksandrawesomekling
authored andcommitted
LibWeb: Fix background clip for elements nested into scrollable boxes
add_clip_rect() accepts a rectangle in viewport-relative coordinates, so it must be translated by the enclosing scroll offset to be displayed correctly inside a scrollable box.
1 parent f574e2b commit 0406533

File tree

3 files changed

+64
-2
lines changed

3 files changed

+64
-2
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<!DOCTYPE html>
2+
<style type="text/css">
3+
* {
4+
scrollbar-width: none;
5+
}
6+
7+
.box {
8+
width: 180px;
9+
height: 64px;
10+
background: linear-gradient(rgb(109, 152, 204), rgb(138, 100, 229));
11+
border-radius: 100px;
12+
}
13+
14+
.scrollable {
15+
width: 200px;
16+
height: 200px;
17+
overflow: scroll;
18+
border: 10px solid orchid;
19+
}
20+
</style>
21+
<div class="scrollable">
22+
<div class="box"></div>
23+
</div>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<!DOCTYPE html>
2+
<link rel="match" href="reference/scrollable-contains-box-with-gradient-background-ref.html" />
3+
<style type="text/css">
4+
* {
5+
scrollbar-width: none;
6+
}
7+
8+
.box {
9+
width: 180px;
10+
height: 64px;
11+
background: linear-gradient(rgb(109, 152, 204), rgb(138, 100, 229));
12+
border-radius: 100px;
13+
}
14+
15+
#scrollable {
16+
width: 200px;
17+
height: 200px;
18+
overflow: scroll;
19+
border: 10px solid orchid;
20+
}
21+
</style>
22+
<div id="scrollable">
23+
<div style="height: 100px"></div>
24+
<div class="box"></div>
25+
<div style="height: 200px"></div>
26+
</div>
27+
<script>
28+
const scrollContainer = document.getElementById("scrollable");
29+
scrollContainer.scrollTop = 100;
30+
</script>

Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,15 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
159159
clip_shrink.right = context.rounded_device_pixels(border_right.width);
160160
}
161161

162+
CSSPixelPoint enclosing_scroll_offset;
163+
if (is<PaintableBox>(layout_node.paintable())) {
164+
auto const& paintable_box = static_cast<PaintableBox const&>(*layout_node.paintable());
165+
enclosing_scroll_offset = paintable_box.enclosing_scroll_frame_offset().value_or({});
166+
} else if (is<InlinePaintable>(layout_node.paintable())) {
167+
auto const& inline_paintable = static_cast<InlinePaintable const&>(*layout_node.paintable());
168+
enclosing_scroll_offset = inline_paintable.enclosing_scroll_frame_offset().value_or({});
169+
}
170+
162171
// Note: Background layers are ordered front-to-back, so we paint them in reverse
163172
for (auto& layer : resolved_background.layers.in_reverse()) {
164173
DisplayListRecorderStateSaver state { display_list_recorder };
@@ -167,9 +176,9 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
167176
auto clip_box = get_box(layer.clip, border_box, layout_node);
168177

169178
CSSPixelRect const& css_clip_rect = clip_box.rect;
170-
auto clip_rect = context.rounded_device_rect(css_clip_rect);
179+
auto clip_rect = context.rounded_device_rect(css_clip_rect.translated(enclosing_scroll_offset));
171180
display_list_recorder.add_clip_rect(clip_rect.to_type<int>());
172-
ScopedCornerRadiusClip corner_clip { context, clip_rect, clip_box.radii };
181+
ScopedCornerRadiusClip corner_clip { context, context.rounded_device_rect(css_clip_rect), clip_box.radii };
173182

174183
if (layer.clip == CSS::BackgroundBox::BorderBox) {
175184
// Shrink the effective clip rect if to account for the bits the borders will definitely paint over

0 commit comments

Comments
 (0)