diff --git a/Userland/Libraries/LibWeb/HTML/HTMLVideoElement.h b/Userland/Libraries/LibWeb/HTML/HTMLVideoElement.h
index a581ba24076..95262163db0 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLVideoElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLVideoElement.h
@@ -39,6 +39,7 @@ public:
struct CachedLayoutBoxes {
Optional control_box_rect;
Optional playback_button_rect;
+ Optional timeline_rect;
};
CachedLayoutBoxes& cached_layout_boxes(Badge) const { return m_layout_boxes; }
diff --git a/Userland/Libraries/LibWeb/Painting/VideoPaintable.cpp b/Userland/Libraries/LibWeb/Painting/VideoPaintable.cpp
index 6a4762a2de1..3bef49d4201 100644
--- a/Userland/Libraries/LibWeb/Painting/VideoPaintable.cpp
+++ b/Userland/Libraries/LibWeb/Painting/VideoPaintable.cpp
@@ -170,6 +170,7 @@ DevicePixelRect VideoPaintable::paint_control_bar_timeline(PaintContext& context
auto timeline_rect = control_box_rect;
timeline_rect.set_width(min(control_box_rect.width() * 6 / 10, timeline_rect.width()));
+ layout_box().dom_node().cached_layout_boxes({}).timeline_rect = context.scale_to_css_rect(timeline_rect);
auto playback_percentage = video_element.current_time() / video_element.duration();
auto playback_position = static_cast(static_cast(timeline_rect.width())) * playback_percentage;
@@ -287,6 +288,16 @@ VideoPaintable::DispatchEventOfSameName VideoPaintable::handle_mouseup(Badgecontains(position)) {
+ auto x_offset = position.x() - cached_layout_boxes.timeline_rect->x();
+ auto x_percentage = static_cast(x_offset) / static_cast(cached_layout_boxes.timeline_rect->width());
+
+ auto position = static_cast(x_percentage) * video_element.duration();
+ video_element.set_current_time(position);
+
+ return DispatchEventOfSameName::Yes;
+ }
+
return DispatchEventOfSameName::No;
}