@@ -35,9 +35,14 @@ export function NestedSticky({
35
35
36
36
let width = 0 ;
37
37
let height = 0 ;
38
- let isSticky = false ;
39
38
let rafId : number | null = null ;
40
39
40
+ // relative at the top
41
+ // fixed when we scroll
42
+ // absolute when we're near the bottom
43
+ let state : 'fixed' | 'absolute' | 'relative' = 'relative' ;
44
+ let prevState : 'fixed' | 'absolute' | 'relative' = 'relative' ;
45
+
41
46
const measureDimensions = ( ) => {
42
47
const rect = sticky . getBoundingClientRect ( ) ;
43
48
width = rect . width ;
@@ -48,13 +53,23 @@ export function NestedSticky({
48
53
} ;
49
54
50
55
const updateStyles = ( ) => {
51
- placeholder . style . height = isSticky ? `${ height } px` : '0' ;
56
+ placeholder . style . height = state !== 'relative' ? `${ height } px` : '0' ;
52
57
53
- if ( isSticky ) {
58
+ if ( state === 'fixed' ) {
54
59
sticky . style . position = 'fixed' ;
55
60
sticky . style . top = `${ offsetTop } px` ;
56
61
sticky . style . width = `${ width } px` ;
57
62
sticky . setAttribute ( 'data-fixed' , '' ) ;
63
+ } else if ( state === 'absolute' ) {
64
+ const containerRect = container . getBoundingClientRect ( ) ;
65
+ const stickyRect = sticky . getBoundingClientRect ( ) ;
66
+
67
+ const relativeTop = stickyRect . top - containerRect . top ;
68
+
69
+ sticky . style . position = 'absolute' ;
70
+ sticky . style . top = `${ relativeTop } px` ;
71
+ sticky . style . width = `${ width } px` ;
72
+ sticky . setAttribute ( 'data-fixed' , '' ) ;
58
73
} else {
59
74
sticky . style . position = 'relative' ;
60
75
sticky . style . top = '' ;
@@ -74,13 +89,14 @@ export function NestedSticky({
74
89
75
90
const shouldBeFixed = containerRect . top < offsetTop ;
76
91
77
- if ( shouldBeFixed && parentRect . bottom < offsetTop + height + offsetBottom + 10 ) {
78
- isSticky = false ;
79
- } else {
80
- isSticky = shouldBeFixed ;
81
- }
92
+ const nearBottom = parentRect . bottom < offsetTop + height + offsetBottom + 10 ;
82
93
83
- updateStyles ( ) ;
94
+ state = shouldBeFixed && nearBottom ? 'absolute' : shouldBeFixed ? 'fixed' : 'relative' ;
95
+
96
+ if ( state !== prevState ) {
97
+ prevState = state ;
98
+ updateStyles ( ) ;
99
+ }
84
100
} ) ;
85
101
} ;
86
102
0 commit comments