0
# Built-in Modifiers
1
2
Nine built-in modifiers that control positioning behavior including automatic flipping, overflow prevention, offsetting, arrow positioning, and style application.
3
4
## Capabilities
5
6
### flip Modifier
7
8
Flips the popper to the opposite placement when it would overflow the boundary.
9
10
```javascript { .api }
11
interface FlipOptions {
12
/** Check overflow on main axis */
13
mainAxis: boolean;
14
/** Check overflow on alternate axis */
15
altAxis: boolean;
16
/** Custom fallback placements to try in order */
17
fallbackPlacements: Array<Placement>;
18
/** Padding around boundary for overflow detection */
19
padding: Padding;
20
/** Boundary element(s) or boundary type */
21
boundary: Boundary;
22
/** Root boundary for overflow checking */
23
rootBoundary: RootBoundary;
24
/** Use alternate boundary context */
25
altBoundary: boolean;
26
/** Allow flipping to variation placements */
27
flipVariations: boolean;
28
/** Allowed auto placements when using 'auto' */
29
allowedAutoPlacements: Array<Placement>;
30
}
31
32
type Boundary = Element | Array<Element> | 'clippingParents';
33
type RootBoundary = 'viewport' | 'document';
34
type Padding = number | { top?: number; right?: number; bottom?: number; left?: number };
35
```
36
37
**Usage Examples:**
38
39
```javascript
40
import { createPopper } from '@popperjs/core';
41
42
// Enable flip with default options
43
const popper = createPopper(button, tooltip, {
44
modifiers: [
45
{
46
name: 'flip',
47
enabled: true,
48
},
49
],
50
});
51
52
// Custom flip configuration
53
const popper = createPopper(button, tooltip, {
54
modifiers: [
55
{
56
name: 'flip',
57
options: {
58
fallbackPlacements: ['top', 'right', 'bottom'],
59
boundary: document.querySelector('.container'),
60
padding: 5,
61
},
62
},
63
],
64
});
65
66
// Disable main axis flipping but allow alt axis
67
const popper = createPopper(button, tooltip, {
68
modifiers: [
69
{
70
name: 'flip',
71
options: {
72
mainAxis: false,
73
altAxis: true,
74
},
75
},
76
],
77
});
78
```
79
80
### preventOverflow Modifier
81
82
Prevents the popper from overflowing its boundary by adjusting its position.
83
84
```javascript { .api }
85
interface PreventOverflowOptions {
86
/** Prevent overflow on main axis */
87
mainAxis: boolean;
88
/** Prevent overflow on alternate axis */
89
altAxis: boolean;
90
/** Boundary for overflow detection */
91
boundary: Boundary;
92
/** Root boundary context */
93
rootBoundary: RootBoundary;
94
/** Use alternate boundary context */
95
altBoundary: boolean;
96
/** Allow popper to overflow to stay near reference */
97
tether: boolean;
98
/** Offset when tether option activates */
99
tetherOffset: TetherOffset;
100
/** Padding around boundary */
101
padding: Padding;
102
}
103
104
type TetherOffset =
105
| number
106
| { mainAxis: number; altAxis: number }
107
| ((args: { popper: Rect; reference: Rect; placement: Placement }) => number | { mainAxis: number; altAxis: number });
108
```
109
110
**Usage Examples:**
111
112
```javascript
113
// Basic overflow prevention
114
const popper = createPopper(button, tooltip, {
115
modifiers: [
116
{
117
name: 'preventOverflow',
118
options: {
119
boundary: 'clippingParents',
120
padding: 8,
121
},
122
},
123
],
124
});
125
126
// Tethering to keep popper near reference
127
const popper = createPopper(button, tooltip, {
128
modifiers: [
129
{
130
name: 'preventOverflow',
131
options: {
132
tether: true,
133
tetherOffset: 10,
134
},
135
},
136
],
137
});
138
139
// Prevent overflow only on main axis
140
const popper = createPopper(button, tooltip, {
141
modifiers: [
142
{
143
name: 'preventOverflow',
144
options: {
145
mainAxis: true,
146
altAxis: false,
147
},
148
},
149
],
150
});
151
```
152
153
### offset Modifier
154
155
Applies offset to the popper position along main and alternate axes.
156
157
```javascript { .api }
158
interface OffsetOptions {
159
/** Offset specification as array [skidding, distance] or function */
160
offset: OffsetsFunction | [number?, number?];
161
}
162
163
type OffsetsFunction = (args: {
164
popper: Rect;
165
reference: Rect;
166
placement: Placement;
167
}) => [number?, number?];
168
```
169
170
**Usage Examples:**
171
172
```javascript
173
// Static offset [skidding, distance]
174
const popper = createPopper(button, tooltip, {
175
modifiers: [
176
{
177
name: 'offset',
178
options: {
179
offset: [0, 8], // 0 skidding, 8px distance
180
},
181
},
182
],
183
});
184
185
// Dynamic offset based on context
186
const popper = createPopper(button, tooltip, {
187
modifiers: [
188
{
189
name: 'offset',
190
options: {
191
offset: ({ reference, popper, placement }) => {
192
// Larger offset for larger references
193
const distance = reference.width > 100 ? 12 : 6;
194
return [0, distance];
195
},
196
},
197
},
198
],
199
});
200
```
201
202
### arrow Modifier
203
204
Positions an arrow element to point to the reference element.
205
206
```javascript { .api }
207
interface ArrowOptions {
208
/** Arrow element or selector */
209
element: HTMLElement | string | null;
210
/** Padding around arrow positioning */
211
padding: Padding | ((args: { popper: Rect; reference: Rect; placement: Placement }) => Padding);
212
}
213
```
214
215
**Usage Examples:**
216
217
```javascript
218
// Arrow with element reference
219
const arrowElement = tooltip.querySelector('.arrow');
220
const popper = createPopper(button, tooltip, {
221
modifiers: [
222
{
223
name: 'arrow',
224
options: {
225
element: arrowElement,
226
padding: 5,
227
},
228
},
229
],
230
});
231
232
// Arrow with CSS selector
233
const popper = createPopper(button, tooltip, {
234
modifiers: [
235
{
236
name: 'arrow',
237
options: {
238
element: '.arrow',
239
padding: { left: 10, right: 10 },
240
},
241
},
242
],
243
});
244
245
// Dynamic arrow padding
246
const popper = createPopper(button, tooltip, {
247
modifiers: [
248
{
249
name: 'arrow',
250
options: {
251
element: '.arrow',
252
padding: ({ placement }) => placement.startsWith('top') ? 8 : 4,
253
},
254
},
255
],
256
});
257
```
258
259
### computeStyles Modifier
260
261
Computes CSS styles for positioning the popper element.
262
263
```javascript { .api }
264
interface ComputeStylesOptions {
265
/** GPU acceleration using transform3d */
266
gpuAcceleration: boolean;
267
/** Adaptive positioning that adjusts for device pixel ratio */
268
adaptive: boolean;
269
/** Round pixel values to avoid blurry rendering */
270
roundOffsets: boolean;
271
}
272
```
273
274
**Usage Examples:**
275
276
```javascript
277
// Disable GPU acceleration
278
const popper = createPopper(button, tooltip, {
279
modifiers: [
280
{
281
name: 'computeStyles',
282
options: {
283
gpuAcceleration: false,
284
},
285
},
286
],
287
});
288
289
// Configure pixel rounding
290
const popper = createPopper(button, tooltip, {
291
modifiers: [
292
{
293
name: 'computeStyles',
294
options: {
295
roundOffsets: true,
296
adaptive: false,
297
},
298
},
299
],
300
});
301
```
302
303
### applyStyles Modifier
304
305
Applies computed styles to the popper and arrow elements.
306
307
```javascript { .api }
308
// applyStyles has no configurable options
309
// It automatically applies styles from computeStyles modifier
310
```
311
312
**Usage Examples:**
313
314
```javascript
315
// applyStyles is included by default in full createPopper
316
// Disable if you want to handle styles manually
317
const popper = createPopper(button, tooltip, {
318
modifiers: [
319
{
320
name: 'applyStyles',
321
enabled: false,
322
},
323
],
324
});
325
326
// Access computed styles from state instead
327
const styles = popper.state.styles.popper;
328
Object.assign(tooltip.style, styles);
329
```
330
331
### eventListeners Modifier
332
333
Manages scroll and resize event listeners for automatic position updates.
334
335
```javascript { .api }
336
interface EventListenersOptions {
337
/** Listen for scroll events */
338
scroll: boolean;
339
/** Listen for resize events */
340
resize: boolean;
341
}
342
```
343
344
**Usage Examples:**
345
346
```javascript
347
// Disable automatic resize handling
348
const popper = createPopper(button, tooltip, {
349
modifiers: [
350
{
351
name: 'eventListeners',
352
options: {
353
resize: false,
354
scroll: true,
355
},
356
},
357
],
358
});
359
360
// Disable all automatic event handling
361
const popper = createPopper(button, tooltip, {
362
modifiers: [
363
{
364
name: 'eventListeners',
365
enabled: false,
366
},
367
],
368
});
369
```
370
371
### hide Modifier
372
373
Detects when the reference element is not visible and hides the popper.
374
375
```javascript { .api }
376
// hide modifier has no configurable options
377
// It sets data-popper-reference-hidden and data-popper-escaped attributes
378
```
379
380
**Usage Examples:**
381
382
```javascript
383
// hide modifier is included by default
384
// Access visibility state from modifiersData
385
const hideData = popper.state.modifiersData.hide;
386
if (hideData?.isReferenceHidden) {
387
console.log('Reference element is not visible');
388
}
389
390
// Style based on visibility attributes
391
const css = `
392
[data-popper-reference-hidden] {
393
visibility: hidden;
394
pointer-events: none;
395
}
396
397
[data-popper-escaped] {
398
opacity: 0.5;
399
}
400
`;
401
```
402
403
### popperOffsets Modifier
404
405
Computes the basic positioning offsets for the popper element.
406
407
```javascript { .api }
408
// popperOffsets modifier has no configurable options
409
// It computes the base x, y coordinates for popper positioning
410
```
411
412
**Usage Examples:**
413
414
```javascript
415
// popperOffsets is a core modifier required by most others
416
// Access computed offsets from state
417
const offsets = popper.state.modifiersData.popperOffsets;
418
console.log('Popper position:', offsets.x, offsets.y);
419
420
// This modifier should not be disabled as it's foundational
421
```
422
423
## Modifier System
424
425
### Modifier Interface
426
427
Structure that all modifiers must follow.
428
429
```javascript { .api }
430
interface Modifier<Name, Options> {
431
/** Unique name identifier */
432
name: Name;
433
/** Whether the modifier is enabled */
434
enabled: boolean;
435
/** Execution phase during update cycle */
436
phase: ModifierPhases;
437
/** Required modifier names that must run before this one */
438
requires?: Array<string>;
439
/** Optional modifier names that should run before if present */
440
requiresIfExists?: Array<string>;
441
/** Main modifier function executed during updates */
442
fn: (args: ModifierArguments<Options>) => State | void;
443
/** Effect function for setup/cleanup (runs once) */
444
effect?: (args: ModifierArguments<Options>) => (() => void) | void;
445
/** Default options for the modifier */
446
options?: Partial<Options>;
447
/** Static data for the modifier */
448
data?: any;
449
}
450
451
interface ModifierArguments<Options> {
452
state: State;
453
instance: Instance;
454
options: Partial<Options>;
455
name: string;
456
}
457
458
type ModifierPhases =
459
| 'beforeRead' | 'read' | 'afterRead'
460
| 'beforeMain' | 'main' | 'afterMain'
461
| 'beforeWrite' | 'write' | 'afterWrite';
462
```
463
464
**Usage Examples:**
465
466
```javascript
467
// Custom modifier example
468
const customModifier = {
469
name: 'customOffset',
470
enabled: true,
471
phase: 'main',
472
requires: ['popperOffsets'],
473
fn({ state }) {
474
// Apply custom offset logic
475
state.modifiersData.popperOffsets.y += 10;
476
},
477
};
478
479
const popper = createPopper(button, tooltip, {
480
modifiers: [customModifier],
481
});
482
```