@@ -39,6 +39,14 @@ const isAtRight = ref(false);
39
39
const isAtBottom = ref (false );
40
40
const isAtLeft = ref (true );
41
41
42
+ /**
43
+ * We have to check if the scroll amount is close enough to some threshold in order to
44
+ * more accurately calculate arrivedState. This is because scrollTop/scrollLeft are non-rounded
45
+ * numbers, while scrollHeight/scrollWidth and clientHeight/clientWidth are rounded.
46
+ * https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#determine_if_an_element_has_been_totally_scrolled
47
+ */
48
+ const ARRIVED_STATE_THRESHOLD_PIXELS = 1 ;
49
+
42
50
const showShadowTop = computed (() => props .shadow && props .shadowTop );
43
51
const showShadowBottom = computed (() => props .shadow && props .shadowBottom );
44
52
const showShadowLeft = computed (() => props .shadow && props .shadowLeft );
@@ -60,14 +68,18 @@ function handleScroll(event: Event) {
60
68
const target = event .target as HTMLElement ;
61
69
const scrollTop = target ?.scrollTop ?? 0 ;
62
70
const scrollLeft = target ?.scrollLeft ?? 0 ;
63
- const offsetHeight = target ?.offsetHeight ?? 0 ;
64
- const offsetWidth = target ?.offsetWidth ?? 0 ;
71
+ const clientHeight = target ?.clientHeight ?? 0 ;
72
+ const clientWidth = target ?.clientWidth ?? 0 ;
65
73
const scrollHeight = target ?.scrollHeight ?? 0 ;
66
74
const scrollWidth = target ?.scrollWidth ?? 0 ;
67
75
isAtTop .value = scrollTop <= 0 ;
68
76
isAtLeft .value = scrollLeft <= 0 ;
69
- isAtBottom .value = scrollTop + offsetHeight >= scrollHeight ;
70
- isAtRight .value = scrollLeft + offsetWidth >= scrollWidth ;
77
+ isAtBottom .value =
78
+ Math .abs (scrollTop ) + clientHeight >=
79
+ scrollHeight - ARRIVED_STATE_THRESHOLD_PIXELS ;
80
+ isAtRight .value =
81
+ Math .abs (scrollLeft ) + clientWidth >=
82
+ scrollWidth - ARRIVED_STATE_THRESHOLD_PIXELS ;
71
83
72
84
emit (' scrollAt' , {
73
85
bottom: isAtBottom .value ,
0 commit comments