or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/npm-react-waypoint

A React component to execute functions when scrolling to specific elements in any scrollable container

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/react-waypoint@10.3.x

To install, run

npx @tessl/cli install tessl/npm-react-waypoint@10.3.0

0

# React Waypoint

1

2

React Waypoint is a React component that executes callback functions whenever you scroll to an element. It works in all containers that can scroll, including the browser window, and provides callbacks for enter/leave events when elements cross viewport boundaries.

3

4

## Package Information

5

6

- **Package Name**: react-waypoint

7

- **Package Type**: npm

8

- **Language**: JavaScript (with TypeScript definitions included)

9

- **Installation**: `npm install react-waypoint`

10

11

## Core Imports

12

13

```javascript

14

import { Waypoint } from 'react-waypoint';

15

```

16

17

For CommonJS:

18

19

```javascript

20

const { Waypoint } = require('react-waypoint');

21

```

22

23

## Basic Usage

24

25

```jsx

26

import React from 'react';

27

import { Waypoint } from 'react-waypoint';

28

29

function App() {

30

const handleWaypointEnter = (args) => {

31

console.log('Waypoint entered!', args.currentPosition);

32

};

33

34

const handleWaypointLeave = (args) => {

35

console.log('Waypoint left!', args.currentPosition);

36

};

37

38

return (

39

<div>

40

<div style={{ height: '1000px' }}>Scroll down...</div>

41

42

{/* Basic waypoint */}

43

<Waypoint

44

onEnter={handleWaypointEnter}

45

onLeave={handleWaypointLeave}

46

/>

47

48

{/* Waypoint with child element */}

49

<Waypoint onEnter={handleWaypointEnter}>

50

<div style={{ padding: '20px', background: '#f0f0f0' }}>

51

This content triggers waypoint events

52

</div>

53

</Waypoint>

54

</div>

55

);

56

}

57

```

58

59

## Architecture

60

61

React Waypoint operates through several key mechanisms:

62

63

- **Event-Driven Architecture**: Uses scroll and resize event listeners to detect position changes

64

- **Position Calculation**: Calculates element position relative to viewport using `getBoundingClientRect()`

65

- **Offset Support**: Supports both pixel and percentage-based offsets for flexible triggering

66

- **Scrollable Ancestor Detection**: Automatically finds the closest scrollable container or allows custom specification

67

- **Lazy Evaluation**: Uses `onNextTick` scheduling to optimize performance and avoid layout thrashing

68

69

## Capabilities

70

71

### Waypoint Component

72

73

The main React component that provides scroll-based element visibility detection.

74

75

```typescript { .api }

76

class Waypoint extends React.Component<WaypointProps, {}> {

77

static above: string;

78

static below: string;

79

static inside: string;

80

static invisible: string;

81

}

82

83

interface WaypointProps {

84

/** Function called when waypoint enters viewport */

85

onEnter?: (args: CallbackArgs) => void;

86

/** Function called when waypoint leaves viewport */

87

onLeave?: (args: CallbackArgs) => void;

88

/** Function called when waypoint position changes */

89

onPositionChange?: (args: CallbackArgs) => void;

90

/** Whether to activate on horizontal scrolling instead of vertical */

91

horizontal?: boolean;

92

/** Distance from top of container in pixels or percentage (e.g., "20px", "20%") */

93

topOffset?: string | number;

94

/** Distance from bottom of container in pixels or percentage (e.g., "20px", "20%") */

95

bottomOffset?: string | number;

96

/** Custom ancestor to determine if the target is visible in it */

97

scrollableAncestor?: any;

98

/** If the onEnter/onLeave events are to be fired on rapid scrolling */

99

fireOnRapidScroll?: boolean;

100

/** Use this prop to get debug information in the console log */

101

debug?: boolean;

102

/** Child elements to wrap with waypoint functionality */

103

children?: React.ReactNode;

104

}

105

106

interface CallbackArgs {

107

/** The position that the waypoint has at the moment */

108

currentPosition: string;

109

/** The position that the waypoint had before */

110

previousPosition: string;

111

/** The native scroll event that triggered the callback (may be missing) */

112

event?: Event;

113

/** The waypoint's distance to the top of the viewport */

114

waypointTop: number;

115

/** The waypoint's distance to the bottom of the viewport */

116

waypointBottom: number;

117

/** The distance from the scrollable ancestor to the viewport top */

118

viewportTop: number;

119

/** The distance from the bottom of the scrollable ancestor to the viewport top */

120

viewportBottom: number;

121

}

122

```

123

124

### Position Constants

125

126

Static constants representing different waypoint positions relative to the viewport.

127

128

```typescript { .api }

129

/** Waypoint is above the viewport */

130

Waypoint.above: string; // "above"

131

/** Waypoint is below the viewport */

132

Waypoint.below: string; // "below"

133

/** Waypoint is inside (visible in) the viewport */

134

Waypoint.inside: string; // "inside"

135

/** Waypoint is invisible (e.g., display: none) */

136

Waypoint.invisible: string; // "invisible"

137

```

138

139

### Callback Events

140

141

React Waypoint provides three main callback events for different use cases:

142

143

**onEnter**: Triggered when the waypoint becomes visible in the viewport

144

```jsx

145

<Waypoint

146

onEnter={({ currentPosition, previousPosition, event, waypointTop, waypointBottom, viewportTop, viewportBottom }) => {

147

console.log('Element entered viewport');

148

// Useful for: lazy loading content, analytics tracking, animations

149

}}

150

/>

151

```

152

153

**onLeave**: Triggered when the waypoint leaves the viewport

154

```jsx

155

<Waypoint

156

onLeave={({ currentPosition, previousPosition, event, waypointTop, waypointBottom, viewportTop, viewportBottom }) => {

157

console.log('Element left viewport');

158

// Useful for: cleanup, pausing videos, stopping animations

159

}}

160

/>

161

```

162

163

**onPositionChange**: Triggered whenever the waypoint's position changes

164

```jsx

165

<Waypoint

166

onPositionChange={({ currentPosition, previousPosition, event, waypointTop, waypointBottom, viewportTop, viewportBottom }) => {

167

console.log(\`Position changed from \${previousPosition} to \${currentPosition}\`);

168

// Useful for: scroll spies, position-based UI updates

169

}}

170

/>

171

```

172

173

### Offset Configuration

174

175

Control when waypoint events trigger using flexible offset options:

176

177

**Percentage-based offsets** (relative to container height):

178

```jsx

179

<Waypoint

180

topOffset="20%" // Trigger 20% from top of viewport

181

bottomOffset="10%" // Trigger 10% from bottom of viewport

182

/>

183

```

184

185

**Pixel-based offsets**:

186

```jsx

187

<Waypoint

188

topOffset={100} // Trigger 100px from top

189

bottomOffset="50px" // Trigger 50px from bottom

190

/>

191

```

192

193

**Negative offsets** (trigger before entering viewport):

194

```jsx

195

<Waypoint

196

topOffset="-100px" // Trigger 100px before entering viewport

197

bottomOffset="-20%" // Trigger when 20% outside bottom

198

/>

199

```

200

201

### Horizontal Scrolling

202

203

Enable horizontal scroll detection for side-scrolling interfaces:

204

205

```jsx

206

<Waypoint

207

horizontal={true}

208

onEnter={() => console.log('Entered horizontal viewport')}

209

/>

210

```

211

212

### Custom Scrollable Containers

213

214

Specify a custom scrollable ancestor instead of auto-detection:

215

216

```jsx

217

function ScrollableContainer() {

218

const containerRef = useRef(null);

219

220

return (

221

<div ref={containerRef} style={{ height: '300px', overflow: 'auto' }}>

222

<div style={{ height: '1000px' }}>

223

<Waypoint

224

scrollableAncestor={containerRef.current}

225

onEnter={() => console.log('Entered custom container viewport')}

226

/>

227

</div>

228

</div>

229

);

230

}

231

```

232

233

### Rapid Scroll Handling

234

235

Control behavior during rapid scrolling where waypoint might be skipped:

236

237

```jsx

238

<Waypoint

239

fireOnRapidScroll={true} // Default: fires both onEnter and onLeave during rapid scroll

240

fireOnRapidScroll={false} // Skip events during rapid scroll

241

/>

242

```

243

244

### Debug Mode

245

246

Enable detailed console logging for development:

247

248

```jsx

249

<Waypoint

250

debug={true}

251

onEnter={() => console.log('Debug information will show in console')}

252

/>

253

```

254

255

### Child Element Wrapping

256

257

Wrap existing elements to track their visibility:

258

259

```jsx

260

{/* Without children - creates invisible span element */}

261

<Waypoint onEnter={handleEnter} />

262

263

{/* With children - tracks the child element */}

264

<Waypoint onEnter={handleEnter}>

265

<img src="image.jpg" alt="Lazy loaded image" />

266

</Waypoint>

267

268

{/* Multiple children */}

269

<Waypoint onEnter={handleEnter}>

270

<div className="content-section">

271

<h2>Section Title</h2>

272

<p>Section content...</p>

273

</div>

274

</Waypoint>

275

```

276

277

## Common Use Cases

278

279

**Lazy Loading Images**:

280

```jsx

281

<Waypoint

282

onEnter={() => setImageSrc(actualImageUrl)}

283

topOffset="-100px" // Start loading before entering viewport

284

>

285

<img src={imageSrc || placeholderSrc} alt="Lazy loaded" />

286

</Waypoint>

287

```

288

289

**Infinite Scroll**:

290

```jsx

291

<Waypoint

292

key={currentPage} // Important: use key to recreate waypoint

293

onEnter={loadMoreContent}

294

bottomOffset="100px" // Trigger before reaching bottom

295

/>

296

```

297

298

**Scroll Spy Navigation**:

299

```jsx

300

<Waypoint

301

onPositionChange={({ currentPosition }) => {

302

if (currentPosition === 'inside') {

303

setActiveSection('section1');

304

}

305

}}

306

>

307

<section id="section1">Content...</section>

308

</Waypoint>

309

```

310

311

**Analytics Tracking**:

312

```jsx

313

<Waypoint

314

onEnter={() => analytics.track('Section Viewed')}

315

topOffset="50%" // Trigger when 50% visible

316

/>

317

```