mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 04:27:44 +00:00
LibWeb: Account for scroll offset in overflow clip rect calculation
This change addresses an issue with overflow clipping in scenarios where `overflow: hidden` is applied to boxes nested within elements with `overflow: scroll`. Fixes https://github.com/SerenityOS/serenity/issues/22733
This commit is contained in:
parent
4330cdee74
commit
9dddd6b028
5 changed files with 281 additions and 1 deletions
|
@ -0,0 +1,76 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<style>
|
||||||
|
html {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0px;
|
||||||
|
display: flex;
|
||||||
|
background: pink;
|
||||||
|
}
|
||||||
|
#outer {
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
|
background: orange;
|
||||||
|
margin-top: 100px;
|
||||||
|
}
|
||||||
|
#inner {
|
||||||
|
height: 1000px;
|
||||||
|
background: magenta;
|
||||||
|
}
|
||||||
|
.item {
|
||||||
|
overflow: hidden;
|
||||||
|
background: yellow;
|
||||||
|
}
|
||||||
|
.wrapper {
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px solid black;
|
||||||
|
background: lime;
|
||||||
|
height: 50px;
|
||||||
|
width: 200px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style><body><div id="outer"><div id="inner">
|
||||||
|
<div class="item"><div class="wrapper">11</div></div>
|
||||||
|
<div class="item"><div class="wrapper">12</div></div>
|
||||||
|
<div class="item"><div class="wrapper">13</div></div>
|
||||||
|
<div class="item"><div class="wrapper">14</div></div>
|
||||||
|
<div class="item"><div class="wrapper">15</div></div>
|
||||||
|
<div class="item"><div class="wrapper">16</div></div>
|
||||||
|
<div class="item"><div class="wrapper">17</div></div>
|
||||||
|
<div class="item"><div class="wrapper">18</div></div>
|
||||||
|
<div class="item"><div class="wrapper">19</div></div>
|
||||||
|
<div class="item"><div class="wrapper">20</div></div>
|
||||||
|
<div class="item"><div class="wrapper">21</div></div>
|
||||||
|
<div class="item"><div class="wrapper">22</div></div>
|
||||||
|
<div class="item"><div class="wrapper">23</div></div>
|
||||||
|
<div class="item"><div class="wrapper">24</div></div>
|
||||||
|
<div class="item"><div class="wrapper">25</div></div>
|
||||||
|
<div class="item"><div class="wrapper">26</div></div>
|
||||||
|
<div class="item"><div class="wrapper">27</div></div>
|
||||||
|
<div class="item"><div class="wrapper">28</div></div>
|
||||||
|
<div class="item"><div class="wrapper">29</div></div>
|
||||||
|
<div class="item"><div class="wrapper">30</div></div>
|
||||||
|
<div class="item"><div class="wrapper">31</div></div>
|
||||||
|
<div class="item"><div class="wrapper">32</div></div>
|
||||||
|
<div class="item"><div class="wrapper">33</div></div>
|
||||||
|
<div class="item"><div class="wrapper">34</div></div>
|
||||||
|
<div class="item"><div class="wrapper">35</div></div>
|
||||||
|
<div class="item"><div class="wrapper">36</div></div>
|
||||||
|
<div class="item"><div class="wrapper">37</div></div>
|
||||||
|
<div class="item"><div class="wrapper">38</div></div>
|
||||||
|
<div class="item"><div class="wrapper">39</div></div>
|
||||||
|
<div class="item"><div class="wrapper">40</div></div>
|
||||||
|
<div class="item"><div class="wrapper">41</div></div>
|
||||||
|
<div class="item"><div class="wrapper">42</div></div>
|
||||||
|
<div class="item"><div class="wrapper">43</div></div>
|
||||||
|
<div class="item"><div class="wrapper">44</div></div>
|
||||||
|
<div class="item"><div class="wrapper">45</div></div>
|
||||||
|
<div class="item"><div class="wrapper">46</div></div>
|
||||||
|
<div class="item"><div class="wrapper">47</div></div>
|
||||||
|
<div class="item"><div class="wrapper">48</div></div>
|
||||||
|
<div class="item"><div class="wrapper">49</div></div>
|
||||||
|
<div class="item"><div class="wrapper">50</div></div>
|
|
@ -0,0 +1,48 @@
|
||||||
|
<!DOCTYPE html><style>
|
||||||
|
html {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0px;
|
||||||
|
display: flex;
|
||||||
|
background: pink;
|
||||||
|
}
|
||||||
|
#outer {
|
||||||
|
margin-top: 100px;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
|
background: orange;
|
||||||
|
}
|
||||||
|
#inner {
|
||||||
|
height: 1000px;
|
||||||
|
background: magenta;
|
||||||
|
}
|
||||||
|
.item {
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px solid black;
|
||||||
|
width: 200px;
|
||||||
|
height: 50px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: lime;
|
||||||
|
}
|
||||||
|
</style><body><div id="outer"><div id="inner">
|
||||||
|
<div class="item">11</div>
|
||||||
|
<div class="item">12</div>
|
||||||
|
<div class="item">13</div>
|
||||||
|
<div class="item">14</div>
|
||||||
|
<div class="item">15</div>
|
||||||
|
<div class="item">16</div>
|
||||||
|
<div class="item">17</div>
|
||||||
|
<div class="item">18</div>
|
||||||
|
<div class="item">19</div>
|
||||||
|
<div class="item">20</div>
|
||||||
|
<div class="item">21</div>
|
||||||
|
<div class="item">22</div>
|
||||||
|
<div class="item">23</div>
|
||||||
|
<div class="item">24</div>
|
||||||
|
<div class="item">25</div>
|
||||||
|
<div class="item">26</div>
|
||||||
|
<div class="item">27</div>
|
||||||
|
<div class="item">28</div>
|
||||||
|
<div class="item">29</div>
|
|
@ -0,0 +1,91 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<link rel="match" href="reference/scrollable-contains-boxes-with-hidden-overflow-1-ref.html" />
|
||||||
|
<style>
|
||||||
|
html {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0px;
|
||||||
|
display: flex;
|
||||||
|
background: pink;
|
||||||
|
}
|
||||||
|
#outer {
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
|
background: orange;
|
||||||
|
margin-top: 100px;
|
||||||
|
}
|
||||||
|
#inner {
|
||||||
|
height: 1000px;
|
||||||
|
background: magenta;
|
||||||
|
}
|
||||||
|
.item {
|
||||||
|
overflow: hidden;
|
||||||
|
background: yellow;
|
||||||
|
}
|
||||||
|
.wrapper {
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px solid black;
|
||||||
|
background: lime;
|
||||||
|
height: 50px;
|
||||||
|
width: 200px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style><body><div id="outer"><div id="inner">
|
||||||
|
<div class="item"><div class="wrapper">1</div></div>
|
||||||
|
<div class="item"><div class="wrapper">2</div></div>
|
||||||
|
<div class="item"><div class="wrapper">3</div></div>
|
||||||
|
<div class="item"><div class="wrapper">4</div></div>
|
||||||
|
<div class="item"><div class="wrapper">5</div></div>
|
||||||
|
<div class="item"><div class="wrapper">6</div></div>
|
||||||
|
<div class="item"><div class="wrapper">7</div></div>
|
||||||
|
<div class="item"><div class="wrapper">8</div></div>
|
||||||
|
<div class="item"><div class="wrapper">9</div></div>
|
||||||
|
<div class="item"><div class="wrapper">10</div></div>
|
||||||
|
<div class="item"><div class="wrapper">11</div></div>
|
||||||
|
<div class="item"><div class="wrapper">12</div></div>
|
||||||
|
<div class="item"><div class="wrapper">13</div></div>
|
||||||
|
<div class="item"><div class="wrapper">14</div></div>
|
||||||
|
<div class="item"><div class="wrapper">15</div></div>
|
||||||
|
<div class="item"><div class="wrapper">16</div></div>
|
||||||
|
<div class="item"><div class="wrapper">17</div></div>
|
||||||
|
<div class="item"><div class="wrapper">18</div></div>
|
||||||
|
<div class="item"><div class="wrapper">19</div></div>
|
||||||
|
<div class="item"><div class="wrapper">20</div></div>
|
||||||
|
<div class="item"><div class="wrapper">21</div></div>
|
||||||
|
<div class="item"><div class="wrapper">22</div></div>
|
||||||
|
<div class="item"><div class="wrapper">23</div></div>
|
||||||
|
<div class="item"><div class="wrapper">24</div></div>
|
||||||
|
<div class="item"><div class="wrapper">25</div></div>
|
||||||
|
<div class="item"><div class="wrapper">26</div></div>
|
||||||
|
<div class="item"><div class="wrapper">27</div></div>
|
||||||
|
<div class="item"><div class="wrapper">28</div></div>
|
||||||
|
<div class="item"><div class="wrapper">29</div></div>
|
||||||
|
<div class="item"><div class="wrapper">30</div></div>
|
||||||
|
<div class="item"><div class="wrapper">31</div></div>
|
||||||
|
<div class="item"><div class="wrapper">32</div></div>
|
||||||
|
<div class="item"><div class="wrapper">33</div></div>
|
||||||
|
<div class="item"><div class="wrapper">34</div></div>
|
||||||
|
<div class="item"><div class="wrapper">35</div></div>
|
||||||
|
<div class="item"><div class="wrapper">36</div></div>
|
||||||
|
<div class="item"><div class="wrapper">37</div></div>
|
||||||
|
<div class="item"><div class="wrapper">38</div></div>
|
||||||
|
<div class="item"><div class="wrapper">39</div></div>
|
||||||
|
<div class="item"><div class="wrapper">40</div></div>
|
||||||
|
<div class="item"><div class="wrapper">41</div></div>
|
||||||
|
<div class="item"><div class="wrapper">42</div></div>
|
||||||
|
<div class="item"><div class="wrapper">43</div></div>
|
||||||
|
<div class="item"><div class="wrapper">44</div></div>
|
||||||
|
<div class="item"><div class="wrapper">45</div></div>
|
||||||
|
<div class="item"><div class="wrapper">46</div></div>
|
||||||
|
<div class="item"><div class="wrapper">47</div></div>
|
||||||
|
<div class="item"><div class="wrapper">48</div></div>
|
||||||
|
<div class="item"><div class="wrapper">49</div></div>
|
||||||
|
<div class="item"><div class="wrapper">50</div></div>
|
||||||
|
<script>
|
||||||
|
const scrollContainer = document.getElementById("outer");
|
||||||
|
scrollContainer.scrollTop = 500;
|
||||||
|
</script>
|
|
@ -0,0 +1,64 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<link rel="match" href="reference/scrollable-contains-boxes-with-hidden-overflow-2-ref.html" />
|
||||||
|
<style>
|
||||||
|
html {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0px;
|
||||||
|
display: flex;
|
||||||
|
background: pink;
|
||||||
|
}
|
||||||
|
#outer {
|
||||||
|
margin-top: 100px;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
|
background: orange;
|
||||||
|
}
|
||||||
|
#inner {
|
||||||
|
height: 1000px;
|
||||||
|
background: magenta;
|
||||||
|
}
|
||||||
|
.item {
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px solid black;
|
||||||
|
width: 200px;
|
||||||
|
height: 50px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: lime;
|
||||||
|
}
|
||||||
|
</style><body><div id="outer"><div id="inner">
|
||||||
|
<div class="item">1</div>
|
||||||
|
<div class="item">2</div>
|
||||||
|
<div class="item">3</div>
|
||||||
|
<div class="item">4</div>
|
||||||
|
<div class="item">5</div>
|
||||||
|
<div class="item">6</div>
|
||||||
|
<div class="item">7</div>
|
||||||
|
<div class="item">8</div>
|
||||||
|
<div class="item">9</div>
|
||||||
|
<div class="item">10</div>
|
||||||
|
<div class="item">11</div>
|
||||||
|
<div class="item">12</div>
|
||||||
|
<div class="item">13</div>
|
||||||
|
<div class="item">14</div>
|
||||||
|
<div class="item">15</div>
|
||||||
|
<div class="item">16</div>
|
||||||
|
<div class="item">17</div>
|
||||||
|
<div class="item">18</div>
|
||||||
|
<div class="item">19</div>
|
||||||
|
<div class="item">20</div>
|
||||||
|
<div class="item">21</div>
|
||||||
|
<div class="item">22</div>
|
||||||
|
<div class="item">23</div>
|
||||||
|
<div class="item">24</div>
|
||||||
|
<div class="item">25</div>
|
||||||
|
<div class="item">26</div>
|
||||||
|
<div class="item">27</div>
|
||||||
|
<div class="item">28</div>
|
||||||
|
<div class="item">29</div>
|
||||||
|
<script>
|
||||||
|
const scrollContainer = document.getElementById("outer");
|
||||||
|
scrollContainer.scrollTop = 500;
|
||||||
|
</script>
|
|
@ -128,6 +128,7 @@ CSSPixelRect PaintableBox::compute_absolute_padding_rect_with_css_transform_appl
|
||||||
auto offset = block->paintable_box()->offset();
|
auto offset = block->paintable_box()->offset();
|
||||||
auto affine_transform = Gfx::extract_2d_affine_transform(block->paintable_box()->transform());
|
auto affine_transform = Gfx::extract_2d_affine_transform(block->paintable_box()->transform());
|
||||||
offset.translate_by(affine_transform.translation().to_type<CSSPixels>());
|
offset.translate_by(affine_transform.translation().to_type<CSSPixels>());
|
||||||
|
offset.translate_by(-block->paintable_box()->scroll_offset());
|
||||||
rect.translate_by(offset);
|
rect.translate_by(offset);
|
||||||
}
|
}
|
||||||
auto affine_transform = Gfx::extract_2d_affine_transform(transform());
|
auto affine_transform = Gfx::extract_2d_affine_transform(transform());
|
||||||
|
@ -598,7 +599,7 @@ void PaintableWithLines::paint(PaintContext& context, PaintPhase phase) const
|
||||||
bool should_clip_overflow = computed_values().overflow_x() != CSS::Overflow::Visible && computed_values().overflow_y() != CSS::Overflow::Visible;
|
bool should_clip_overflow = computed_values().overflow_x() != CSS::Overflow::Visible && computed_values().overflow_y() != CSS::Overflow::Visible;
|
||||||
Optional<u32> corner_clip_id;
|
Optional<u32> corner_clip_id;
|
||||||
|
|
||||||
auto clip_box = context.rounded_device_rect(absolute_padding_box_rect());
|
auto clip_box = context.rounded_device_rect(compute_absolute_padding_rect_with_css_transform_applied());
|
||||||
|
|
||||||
if (should_clip_overflow) {
|
if (should_clip_overflow) {
|
||||||
context.recording_painter().save();
|
context.recording_painter().save();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue