0
# Constraints and Boundaries
1
2
Advanced positioning constraints to keep elements within specified boundaries and handle viewport clipping. The constraint system prevents elements from being positioned outside visible areas and provides intelligent attachment point flipping.
3
4
## Capabilities
5
6
### Constraint Configuration
7
8
Define boundaries and behaviors for positioned elements.
9
10
```javascript { .api }
11
interface ConstraintOptions {
12
/** Boundary definition - can be a selector, element, or coordinate array */
13
to: string | HTMLElement | Array<number>;
14
/** How to handle constraint violations - flip attachments */
15
attachment?: string;
16
/** Whether and how to pin elements to boundaries */
17
pin?: boolean | string | Array<string>;
18
/** Custom CSS class for out-of-bounds state */
19
outOfBoundsClass?: string;
20
/** Custom CSS class for pinned state */
21
pinnedClass?: string;
22
}
23
```
24
25
**Usage in Tether Options:**
26
27
```javascript
28
import Tether from "tether";
29
30
const tether = new Tether({
31
element: '.dropdown',
32
target: '.trigger',
33
attachment: 'top left',
34
targetAttachment: 'bottom left',
35
constraints: [
36
{
37
to: 'scrollParent',
38
attachment: 'together',
39
pin: true
40
},
41
{
42
to: 'window',
43
attachment: 'together',
44
pin: ['top', 'left']
45
}
46
]
47
});
48
```
49
50
### Boundary Types
51
52
Different types of boundaries for constraint checking.
53
54
```javascript { .api }
55
// String boundary identifiers
56
type BoundaryIdentifier =
57
| "scrollParent" // First scrollable ancestor
58
| "window" // Browser viewport
59
| string; // CSS selector
60
61
// Element boundary
62
type ElementBoundary = HTMLElement;
63
64
// Coordinate boundary [left, top, right, bottom]
65
type CoordinateBoundary = [number, number, number, number];
66
```
67
68
**Usage Examples:**
69
70
```javascript
71
// Constrain to viewport
72
{
73
to: 'window',
74
attachment: 'together',
75
pin: true
76
}
77
78
// Constrain to scrollable parent
79
{
80
to: 'scrollParent',
81
attachment: 'both',
82
pin: ['top', 'bottom']
83
}
84
85
// Constrain to specific element
86
{
87
to: '.container',
88
attachment: 'target',
89
pin: true
90
}
91
92
// Constrain to custom coordinates
93
{
94
to: [100, 50, 800, 600], // [left, top, right, bottom]
95
attachment: 'together',
96
pin: true
97
}
98
```
99
100
### Attachment Flipping
101
102
Control how attachment points change when constraints are violated.
103
104
```javascript { .api }
105
type AttachmentFlipBehavior =
106
| "target" // Flip target attachment only
107
| "element" // Flip element attachment only
108
| "both" // Flip both attachments independently
109
| "together"; // Flip both attachments as a unit
110
```
111
112
**Attachment Behaviors:**
113
114
- **"target"**: When element goes out of bounds, flip the target attachment
115
- **"element"**: When element goes out of bounds, flip the element attachment
116
- **"both"**: Flip target and element attachments independently based on bounds
117
- **"together"**: Flip both attachments together maintaining their relationship
118
119
```javascript
120
// Flip target attachment when constrained
121
{
122
to: 'window',
123
attachment: 'target',
124
pin: false
125
}
126
127
// Flip both attachments together
128
{
129
to: 'scrollParent',
130
attachment: 'together',
131
pin: true
132
}
133
```
134
135
### Pinning Behavior
136
137
Control how elements are pinned to constraint boundaries.
138
139
```javascript { .api }
140
type PinConfiguration =
141
| boolean // Pin to all sides
142
| string // Single side or comma-separated sides
143
| Array<string>; // Array of sides
144
145
type PinSide = "top" | "bottom" | "left" | "right";
146
```
147
148
**Usage Examples:**
149
150
```javascript
151
// Pin to all sides
152
{ pin: true }
153
154
// Pin to specific sides
155
{ pin: 'top,left' }
156
{ pin: ['top', 'left'] }
157
158
// No pinning (allow out-of-bounds)
159
{ pin: false }
160
```
161
162
### Custom CSS Classes
163
164
Override default CSS classes for constraint states.
165
166
```javascript { .api }
167
interface CustomConstraintClasses {
168
/** Class applied when element is outside boundaries */
169
outOfBoundsClass?: string;
170
/** Class applied when element is pinned to boundaries */
171
pinnedClass?: string;
172
}
173
```
174
175
**Usage Example:**
176
177
```javascript
178
const tether = new Tether({
179
element: '.menu',
180
target: '.button',
181
attachment: 'top left',
182
targetAttachment: 'bottom left',
183
constraints: [
184
{
185
to: 'window',
186
attachment: 'together',
187
pin: true,
188
outOfBoundsClass: 'menu-overflow',
189
pinnedClass: 'menu-pinned'
190
}
191
]
192
});
193
```
194
195
## Constraint Examples
196
197
### Dropdown Menu Constraints
198
199
```javascript
200
// Dropdown that flips when near viewport edges
201
const dropdown = new Tether({
202
element: '.dropdown-menu',
203
target: '.dropdown-trigger',
204
attachment: 'top left',
205
targetAttachment: 'bottom left',
206
constraints: [
207
{
208
// Flip attachments together when hitting viewport
209
to: 'window',
210
attachment: 'together',
211
pin: false
212
},
213
{
214
// Pin to scrollable container
215
to: 'scrollParent',
216
pin: ['top', 'bottom', 'left', 'right']
217
}
218
]
219
});
220
```
221
222
### Tooltip Constraints
223
224
```javascript
225
// Tooltip that stays within viewport
226
const tooltip = new Tether({
227
element: '.tooltip',
228
target: '.help-icon',
229
attachment: 'bottom center',
230
targetAttachment: 'top center',
231
constraints: [
232
{
233
to: 'window',
234
attachment: 'together',
235
pin: ['top', 'left', 'right']
236
}
237
]
238
});
239
```
240
241
### Modal Dialog Constraints
242
243
```javascript
244
// Modal that stays centered in viewport
245
const modal = new Tether({
246
element: '.modal',
247
target: 'body',
248
attachment: 'middle center',
249
targetAttachment: 'middle center',
250
constraints: [
251
{
252
to: 'window',
253
pin: ['top', 'left', 'right', 'bottom']
254
}
255
]
256
});
257
```
258
259
## CSS Classes Applied
260
261
The constraint system automatically applies CSS classes based on positioning state:
262
263
### Default Classes
264
265
```javascript { .api }
266
// Out of bounds classes
267
".tether-out-of-bounds" // General out-of-bounds state
268
".tether-out-of-bounds-top" // Out of bounds on top
269
".tether-out-of-bounds-bottom" // Out of bounds on bottom
270
".tether-out-of-bounds-left" // Out of bounds on left
271
".tether-out-of-bounds-right" // Out of bounds on right
272
273
// Pinned classes
274
".tether-pinned" // General pinned state
275
".tether-pinned-top" // Pinned to top
276
".tether-pinned-bottom" // Pinned to bottom
277
".tether-pinned-left" // Pinned to left
278
".tether-pinned-right" // Pinned to right
279
```
280
281
### Custom Classes
282
283
When `outOfBoundsClass` or `pinnedClass` are specified, they replace the default classes:
284
285
```javascript
286
// With custom classes
287
{
288
outOfBoundsClass: 'menu-overflow',
289
pinnedClass: 'menu-stuck'
290
}
291
292
// Applied classes become:
293
".menu-overflow" // Instead of .tether-out-of-bounds
294
".menu-overflow-top" // Instead of .tether-out-of-bounds-top
295
".menu-stuck" // Instead of .tether-pinned
296
".menu-stuck-left" // Instead of .tether-pinned-left
297
```
298
299
### Additional CSS Classes
300
301
The Tether system also applies these additional classes:
302
303
```javascript { .api }
304
// Marker classes (for debugging/development)
305
".tether-element-marker" // Marker on positioned element
306
".tether-target-marker" // Marker on target element
307
".tether-marker-dot" // Visual dot within markers
308
```