or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

browser-apis.mdbrowser-events.mddevice-sensors.mdelement-tracking.mdindex.mdmouse-pointer.mdscroll-resize.mdtheme-preferences.mdutilities-advanced.mdwindow-document.md

element-tracking.mddocs/

0

# Element Tracking

1

2

Components and directives for tracking element properties like size, position, visibility, and bounding rectangles.

3

4

## Capabilities

5

6

### UseElementBounding Component

7

8

Tracks element bounding rectangle information with reactive updates.

9

10

```typescript { .api }

11

/**

12

* Component that tracks element bounding rectangle

13

* @example

14

* <UseElementBounding v-slot="{ x, y, width, height }">

15

* <div>Position: {{ x }}, {{ y }} Size: {{ width }}x{{ height }}</div>

16

* </UseElementBounding>

17

*/

18

interface UseElementBoundingProps extends RenderableComponent {

19

/** ResizeObserver box type @default 'content-box' */

20

box?: ResizeObserverBoxOptions;

21

}

22

23

/** Slot data exposed by UseElementBounding component */

24

interface UseElementBoundingReturn {

25

/** Distance from left edge of viewport */

26

x: Ref<number>;

27

/** Distance from top edge of viewport */

28

y: Ref<number>;

29

/** Distance from top edge of viewport (alias for y) */

30

top: Ref<number>;

31

/** Distance from right edge of viewport */

32

right: Ref<number>;

33

/** Distance from bottom edge of viewport */

34

bottom: Ref<number>;

35

/** Distance from left edge of viewport (alias for x) */

36

left: Ref<number>;

37

/** Element width */

38

width: Ref<number>;

39

/** Element height */

40

height: Ref<number>;

41

/** Update the bounding information manually */

42

update: () => void;

43

}

44

45

type ResizeObserverBoxOptions = 'border-box' | 'content-box' | 'device-pixel-content-box';

46

```

47

48

**Usage Examples:**

49

50

```vue

51

<template>

52

<!-- Basic usage -->

53

<UseElementBounding v-slot="{ x, y, width, height }">

54

<div class="box">

55

Position: ({{ Math.round(x) }}, {{ Math.round(y) }})

56

<br>

57

Size: {{ Math.round(width) }} × {{ Math.round(height) }}

58

</div>

59

</UseElementBounding>

60

61

<!-- Access all properties -->

62

<UseElementBounding v-slot="{ top, right, bottom, left, width, height, update }">

63

<div class="element">

64

<p>Bounding Rectangle:</p>

65

<ul>

66

<li>Top: {{ Math.round(top) }}px</li>

67

<li>Right: {{ Math.round(right) }}px</li>

68

<li>Bottom: {{ Math.round(bottom) }}px</li>

69

<li>Left: {{ Math.round(left) }}px</li>

70

<li>Width: {{ Math.round(width) }}px</li>

71

<li>Height: {{ Math.round(height) }}px</li>

72

</ul>

73

<button @click="update">Manual Update</button>

74

</div>

75

</UseElementBounding>

76

77

<!-- Custom wrapper element -->

78

<UseElementBounding as="section" v-slot="{ width, height }">

79

<div>Section size: {{ width }} × {{ height }}</div>

80

</UseElementBounding>

81

</template>

82

83

<script setup>

84

import { UseElementBounding } from '@vueuse/components';

85

</script>

86

```

87

88

### vElementBounding Directive

89

90

Directive for element bounding tracking without component wrapper.

91

92

```typescript { .api }

93

/**

94

* Directive for tracking element bounding rectangle

95

* @example

96

* <div v-element-bounding="handleBounding">Track bounding</div>

97

* <div v-element-bounding="[handleBounding, options]">With options</div>

98

*/

99

type ElementBoundingHandler = (rect: UseElementBoundingReturn) => void;

100

101

interface VElementBoundingValue {

102

/** Simple handler function */

103

handler: ElementBoundingHandler;

104

/** Handler with options tuple */

105

handlerWithOptions: [ElementBoundingHandler, UseResizeObserverOptions];

106

}

107

108

interface UseResizeObserverOptions {

109

/** ResizeObserver box type @default 'content-box' */

110

box?: ResizeObserverBoxOptions;

111

}

112

```

113

114

**Usage Examples:**

115

116

```vue

117

<template>

118

<!-- Simple tracking -->

119

<div v-element-bounding="handleBounding" class="tracked-element">

120

Tracked element

121

</div>

122

123

<!-- With options -->

124

<div v-element-bounding="[handleBounding, { box: 'border-box' }]">

125

Border-box tracking

126

</div>

127

</template>

128

129

<script setup>

130

import { vElementBounding } from '@vueuse/components';

131

132

function handleBounding(rect) {

133

console.log('Element bounds:', {

134

x: rect.x.value,

135

y: rect.y.value,

136

width: rect.width.value,

137

height: rect.height.value

138

});

139

}

140

</script>

141

```

142

143

### UseElementSize Component

144

145

Tracks element dimensions with reactive updates.

146

147

```typescript { .api }

148

/**

149

* Component that tracks element size

150

* @example

151

* <UseElementSize v-slot="{ width, height }">

152

* <div>Size: {{ width }}x{{ height }}</div>

153

* </UseElementSize>

154

*/

155

interface UseElementSizeProps extends RenderableComponent {

156

/** Initial size values */

157

initialSize?: { width: number; height: number };

158

/** ResizeObserver box type @default 'content-box' */

159

box?: ResizeObserverBoxOptions;

160

}

161

162

/** Slot data exposed by UseElementSize component */

163

interface UseElementSizeReturn {

164

/** Element width */

165

width: Ref<number>;

166

/** Element height */

167

height: Ref<number>;

168

/** Stop watching for size changes */

169

stop: () => void;

170

}

171

```

172

173

**Usage Examples:**

174

175

```vue

176

<template>

177

<!-- Basic usage -->

178

<UseElementSize v-slot="{ width, height }">

179

<div class="resizable">

180

Current size: {{ Math.round(width) }} × {{ Math.round(height) }}

181

</div>

182

</UseElementSize>

183

184

<!-- With initial size -->

185

<UseElementSize

186

v-slot="{ width, height, stop }"

187

:initial-size="{ width: 300, height: 200 }"

188

>

189

<textarea

190

:style="{ width: width + 'px', height: height + 'px' }"

191

@focus="() => {}"

192

@blur="stop"

193

>

194

Resizable textarea

195

</textarea>

196

</UseElementSize>

197

198

<!-- Custom box type -->

199

<UseElementSize box="border-box" v-slot="{ width, height }">

200

<div class="border-tracked">

201

Border-box size: {{ width }} × {{ height }}

202

</div>

203

</UseElementSize>

204

</template>

205

206

<script setup>

207

import { UseElementSize } from '@vueuse/components';

208

</script>

209

```

210

211

### vElementSize Directive

212

213

Directive for element size tracking without component wrapper.

214

215

```typescript { .api }

216

/**

217

* Directive for tracking element size

218

* @example

219

* <div v-element-size="handleSize">Track size</div>

220

* <div v-element-size="[handleSize, options]">With options</div>

221

*/

222

type ElementSizeHandler = (size: UseElementSizeReturn) => void;

223

224

interface VElementSizeValue {

225

/** Simple handler function */

226

handler: ElementSizeHandler;

227

/** Handler with options tuple */

228

handlerWithOptions: [ElementSizeHandler, UseElementSizeOptions];

229

}

230

231

interface UseElementSizeOptions {

232

/** Initial size values */

233

initialSize?: { width: number; height: number };

234

/** ResizeObserver box type @default 'content-box' */

235

box?: ResizeObserverBoxOptions;

236

}

237

```

238

239

**Usage Examples:**

240

241

```vue

242

<template>

243

<!-- Simple tracking -->

244

<div v-element-size="handleSize" class="size-tracked">

245

Size tracked element

246

</div>

247

248

<!-- With options -->

249

<div v-element-size="[handleSize, { box: 'border-box', initialSize: { width: 100, height: 100 } }]">

250

Custom size tracking

251

</div>

252

</template>

253

254

<script setup>

255

import { vElementSize } from '@vueuse/components';

256

257

function handleSize(size) {

258

console.log('Element size changed:', {

259

width: size.width.value,

260

height: size.height.value

261

});

262

}

263

</script>

264

```

265

266

### UseElementVisibility Component

267

268

Tracks element visibility within the viewport using Intersection Observer.

269

270

```typescript { .api }

271

/**

272

* Component that tracks element visibility in viewport

273

* @example

274

* <UseElementVisibility v-slot="{ isVisible }">

275

* <div>Visible: {{ isVisible }}</div>

276

* </UseElementVisibility>

277

*/

278

interface UseElementVisibilityProps extends RenderableComponent {

279

/** Intersection observer options */

280

options?: IntersectionObserverInit;

281

/** Scroll target element @default window */

282

scrollTarget?: MaybeRefOrGetter<HTMLElement | null | undefined>;

283

}

284

285

/** Slot data exposed by UseElementVisibility component */

286

interface UseElementVisibilityReturn {

287

/** Whether the element is visible in viewport */

288

isVisible: Ref<boolean>;

289

/** Stop the visibility observer */

290

stop: () => void;

291

}

292

293

interface IntersectionObserverInit {

294

/** Root element for intersection @default null */

295

root?: Element | null;

296

/** Root margin @default '0px' */

297

rootMargin?: string;

298

/** Visibility threshold @default 0 */

299

threshold?: number | number[];

300

}

301

```

302

303

**Usage Examples:**

304

305

```vue

306

<template>

307

<!-- Basic visibility tracking -->

308

<UseElementVisibility v-slot="{ isVisible }">

309

<div class="tracked-element" :class="{ visible: isVisible }">

310

{{ isVisible ? 'I am visible!' : 'I am hidden' }}

311

</div>

312

</UseElementVisibility>

313

314

<!-- With custom threshold -->

315

<UseElementVisibility

316

v-slot="{ isVisible, stop }"

317

:options="{ threshold: 0.5 }"

318

>

319

<div class="half-visible">

320

{{ isVisible ? '50% visible' : 'Less than 50% visible' }}

321

<button @click="stop">Stop tracking</button>

322

</div>

323

</UseElementVisibility>

324

325

<!-- With root margin -->

326

<UseElementVisibility

327

v-slot="{ isVisible }"

328

:options="{ rootMargin: '100px' }"

329

>

330

<div class="early-trigger">

331

Triggers 100px before entering viewport: {{ isVisible }}

332

</div>

333

</UseElementVisibility>

334

</template>

335

336

<script setup>

337

import { UseElementVisibility } from '@vueuse/components';

338

</script>

339

340

<style>

341

.tracked-element {

342

padding: 20px;

343

background: #f0f0f0;

344

transition: background 0.3s;

345

}

346

347

.tracked-element.visible {

348

background: #90EE90;

349

}

350

</style>

351

```

352

353

### vElementVisibility Directive

354

355

Directive for element visibility tracking without component wrapper.

356

357

```typescript { .api }

358

/**

359

* Directive for tracking element visibility in viewport

360

* @example

361

* <div v-element-visibility="handleVisibility">Track visibility</div>

362

* <div v-element-visibility="[handleVisibility, options]">With options</div>

363

*/

364

type ElementVisibilityHandler = (isVisible: boolean, entry: IntersectionObserverEntry) => void;

365

366

interface VElementVisibilityValue {

367

/** Simple handler function */

368

handler: ElementVisibilityHandler;

369

/** Handler with options tuple */

370

handlerWithOptions: [ElementVisibilityHandler, UseElementVisibilityOptions];

371

}

372

373

interface UseElementVisibilityOptions {

374

/** Intersection observer options */

375

options?: IntersectionObserverInit;

376

/** Scroll target element @default window */

377

scrollTarget?: MaybeRefOrGetter<HTMLElement | null | undefined>;

378

}

379

```

380

381

**Usage Examples:**

382

383

```vue

384

<template>

385

<!-- Simple visibility tracking -->

386

<div v-element-visibility="handleVisibility" class="visibility-tracked">

387

Visibility tracked element

388

</div>

389

390

<!-- With threshold -->

391

<div v-element-visibility="[handleVisibility, { options: { threshold: 0.8 } }]">

392

80% visibility required

393

</div>

394

395

<!-- Multiple thresholds -->

396

<div v-element-visibility="[handleMultipleVisibility, {

397

options: { threshold: [0, 0.25, 0.5, 0.75, 1.0] }

398

}]">

399

Progressive visibility tracking

400

</div>

401

</template>

402

403

<script setup>

404

import { vElementVisibility } from '@vueuse/components';

405

406

function handleVisibility(isVisible, entry) {

407

console.log('Element visibility changed:', isVisible);

408

console.log('Intersection ratio:', entry.intersectionRatio);

409

}

410

411

function handleMultipleVisibility(isVisible, entry) {

412

const ratio = Math.round(entry.intersectionRatio * 100);

413

console.log(`Element is ${ratio}% visible`);

414

}

415

</script>

416

```

417

418

### vElementHover Directive

419

420

Directive for hover state detection on elements.

421

422

```typescript { .api }

423

/**

424

* Directive for detecting hover state on elements

425

* @example

426

* <div v-element-hover="handleHover">Hover me</div>

427

* <div v-element-hover="[handleHover, options]">With options</div>

428

*/

429

type ElementHoverHandler = (isHovering: boolean) => void;

430

431

interface VElementHoverValue {

432

/** Simple handler function */

433

handler: ElementHoverHandler;

434

/** Handler with options tuple */

435

handlerWithOptions: [ElementHoverHandler, UseElementHoverOptions];

436

}

437

438

interface UseElementHoverOptions {

439

/** Delay in ms before triggering hover @default 0 */

440

delayEnter?: number;

441

/** Delay in ms before removing hover @default 0 */

442

delayLeave?: number;

443

}

444

```

445

446

**Usage Examples:**

447

448

```vue

449

<template>

450

<!-- Simple hover detection -->

451

<div v-element-hover="handleHover" class="hover-element">

452

{{ isHovering ? 'Hovering!' : 'Not hovering' }}

453

</div>

454

455

<!-- With delays -->

456

<div v-element-hover="[handleDelayedHover, { delayEnter: 200, delayLeave: 500 }]">

457

Delayed hover (200ms enter, 500ms leave)

458

</div>

459

</template>

460

461

<script setup>

462

import { ref } from 'vue';

463

import { vElementHover } from '@vueuse/components';

464

465

const isHovering = ref(false);

466

467

function handleHover(hovering) {

468

isHovering.value = hovering;

469

console.log('Hover state:', hovering);

470

}

471

472

function handleDelayedHover(hovering) {

473

console.log('Delayed hover state:', hovering);

474

}

475

</script>

476

```

477

478

## Type Definitions

479

480

```typescript { .api }

481

/** Common types used across element tracking */

482

type MaybeRefOrGetter<T> = T | Ref<T> | (() => T);

483

type MaybeElementRef = HTMLElement | null | undefined;

484

485

interface RenderableComponent {

486

/** The element that the component should be rendered as @default 'div' */

487

as?: object | string;

488

}

489

490

/** Position information */

491

interface Position {

492

x: number;

493

y: number;

494

}

495

496

/** Size information */

497

interface Size {

498

width: number;

499

height: number;

500

}

501

```