@hortonstudio/main 1.9.6 → 1.9.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/autoInit/accessibility/README.md +126 -0
- package/autoInit/accessibility/accessibility.js +56 -0
- package/autoInit/accessibility/functions/blog-remover/README.md +61 -0
- package/autoInit/accessibility/functions/blog-remover/blog-remover.js +31 -0
- package/autoInit/accessibility/functions/click-forwarding/README.md +60 -0
- package/autoInit/accessibility/functions/click-forwarding/click-forwarding.js +82 -0
- package/autoInit/accessibility/functions/convert-to-span/README.md +59 -0
- package/autoInit/accessibility/functions/convert-to-span/convert-to-span.js +70 -0
- package/autoInit/accessibility/functions/custom-values-replacement/README.md +71 -0
- package/autoInit/accessibility/functions/custom-values-replacement/custom-values-replacement.js +102 -0
- package/autoInit/accessibility/functions/dropdown/README.md +212 -0
- package/autoInit/accessibility/functions/dropdown/dropdown.js +167 -0
- package/autoInit/accessibility/functions/list-accessibility/README.md +56 -0
- package/autoInit/accessibility/functions/list-accessibility/list-accessibility.js +23 -0
- package/autoInit/accessibility/functions/prevent-default/README.md +58 -0
- package/autoInit/accessibility/functions/prevent-default/prevent-default.js +58 -0
- package/autoInit/accessibility/functions/remove-list-accessibility/README.md +57 -0
- package/autoInit/accessibility/functions/remove-list-accessibility/remove-list-accessibility.js +68 -0
- package/autoInit/accessibility/functions/text-synchronization/README.md +62 -0
- package/autoInit/accessibility/functions/text-synchronization/text-synchronization.js +101 -0
- package/autoInit/accessibility/functions/toc/README.md +79 -0
- package/autoInit/accessibility/functions/toc/toc.js +191 -0
- package/autoInit/accessibility/functions/year-replacement/README.md +54 -0
- package/autoInit/accessibility/functions/year-replacement/year-replacement.js +43 -0
- package/autoInit/button/README.md +122 -0
- package/autoInit/counter/README.md +274 -0
- package/autoInit/{counter.js → counter/counter.js} +20 -5
- package/autoInit/form/README.md +338 -0
- package/autoInit/{form.js → form/form.js} +44 -29
- package/autoInit/navbar/README.md +366 -0
- package/autoInit/site-settings/README.md +218 -0
- package/autoInit/smooth-scroll/README.md +386 -0
- package/autoInit/transition/README.md +301 -0
- package/autoInit/{transition.js → transition/transition.js} +13 -2
- package/index.js +7 -7
- package/package.json +1 -1
- package/autoInit/accessibility.js +0 -786
- /package/autoInit/{button.js → button/button.js} +0 -0
- /package/autoInit/{site-settings.js → site-settings/site-settings.js} +0 -0
- /package/autoInit/{smooth-scroll.js → smooth-scroll/smooth-scroll.js} +0 -0
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
# **Smooth Scroll System Documentation**
|
|
2
|
+
|
|
3
|
+
## **Overview**
|
|
4
|
+
|
|
5
|
+
The smooth scroll system provides GSAP-powered smooth scrolling for anchor links, replacing Webflow's default behavior with a more customizable solution. It supports scroll offsets, reduced motion preferences, and automatically triggers scroll-based animations on page load.
|
|
6
|
+
|
|
7
|
+
**Note:** This module auto-initializes on every page load.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## **Smooth Scroll**
|
|
12
|
+
|
|
13
|
+
### **Required Dependencies**
|
|
14
|
+
|
|
15
|
+
**GSAP Core**
|
|
16
|
+
* Must be loaded before this script
|
|
17
|
+
|
|
18
|
+
**GSAP ScrollToPlugin**
|
|
19
|
+
* Required for smooth scrolling functionality
|
|
20
|
+
|
|
21
|
+
**Typical setup:**
|
|
22
|
+
```html
|
|
23
|
+
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>
|
|
24
|
+
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/ScrollToPlugin.min.js"></script>
|
|
25
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@hortonstudio/main@latest"></script>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### **What It Does**
|
|
29
|
+
|
|
30
|
+
1. **Disables native smooth scroll** - Removes Webflow's jQuery-based anchor link handler
|
|
31
|
+
2. **Disables CSS smooth scrolling** - Sets `scroll-behavior: auto` on html and body
|
|
32
|
+
3. **GSAP smooth scrolling** - Uses GSAP ScrollToPlugin for animated scrolling
|
|
33
|
+
4. **Respects reduced motion** - Instant scroll if user has `prefers-reduced-motion` enabled
|
|
34
|
+
5. **Custom offset support** - Reads `--misc--scroll-offset` CSS variable for scroll offset
|
|
35
|
+
6. **Focus management** - Sets focus on target element after scroll
|
|
36
|
+
7. **URL hash updates** - Updates browser URL with hash when scrolling to anchor
|
|
37
|
+
8. **Mock scroll trigger** - Triggers scroll-based animations on page load with quick scroll
|
|
38
|
+
9. **Keyboard support** - Handles Enter/Space key activation on anchor links
|
|
39
|
+
|
|
40
|
+
### **When It Runs**
|
|
41
|
+
|
|
42
|
+
* Auto-initializes on page load
|
|
43
|
+
* Runs on every page in a multi-page site
|
|
44
|
+
* Listed in `autoInitModules` in index.js
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## **Scroll Offset**
|
|
49
|
+
|
|
50
|
+
### **CSS Variable**
|
|
51
|
+
|
|
52
|
+
Define a scroll offset using a CSS custom property:
|
|
53
|
+
|
|
54
|
+
```css
|
|
55
|
+
:root {
|
|
56
|
+
--misc--scroll-offset: 100px;
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**What it does:** When scrolling to an anchor, the page scrolls to the target element minus this offset. Useful for fixed headers.
|
|
61
|
+
|
|
62
|
+
**Default:** `0` (no offset)
|
|
63
|
+
|
|
64
|
+
**Units:** Pixels only (parsed as integer)
|
|
65
|
+
|
|
66
|
+
### **Example with Fixed Header**
|
|
67
|
+
|
|
68
|
+
```css
|
|
69
|
+
:root {
|
|
70
|
+
--misc--scroll-offset: 80px; /* Height of fixed navbar */
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Result:** When clicking an anchor link, the page scrolls so the target element is 80px from the top of the viewport.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## **Anchor Links**
|
|
79
|
+
|
|
80
|
+
### **Supported Anchor Links**
|
|
81
|
+
|
|
82
|
+
Any link with `href` starting with `#`:
|
|
83
|
+
|
|
84
|
+
```html
|
|
85
|
+
<a href="#section-1">Go to Section 1</a>
|
|
86
|
+
<a href="#about">About Us</a>
|
|
87
|
+
<a href="#contact">Contact</a>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Requirements:**
|
|
91
|
+
- Must have `href` attribute starting with `#`
|
|
92
|
+
- Target element must have matching `id` attribute
|
|
93
|
+
- Cannot be just `#` (empty hash)
|
|
94
|
+
|
|
95
|
+
### **Target Elements**
|
|
96
|
+
|
|
97
|
+
```html
|
|
98
|
+
<section id="section-1">
|
|
99
|
+
<h2>Section 1</h2>
|
|
100
|
+
</section>
|
|
101
|
+
|
|
102
|
+
<div id="about">
|
|
103
|
+
<h2>About Us</h2>
|
|
104
|
+
</div>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**Requirements:**
|
|
108
|
+
- Must have `id` attribute matching the anchor's `href` (without `#`)
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## **Animation Settings**
|
|
113
|
+
|
|
114
|
+
### **GSAP Configuration**
|
|
115
|
+
|
|
116
|
+
The scroll animation uses these GSAP settings:
|
|
117
|
+
|
|
118
|
+
**Duration:** `1` second
|
|
119
|
+
**Easing:** `power2.out` (fast start, slow end)
|
|
120
|
+
**Plugin:** ScrollToPlugin with `offsetY` support
|
|
121
|
+
|
|
122
|
+
### **Example of smooth scroll behavior:**
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
gsap.to(window, {
|
|
126
|
+
duration: 1,
|
|
127
|
+
scrollTo: {
|
|
128
|
+
y: target,
|
|
129
|
+
offsetY: offset,
|
|
130
|
+
},
|
|
131
|
+
ease: "power2.out"
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Result:** Smooth 1-second scroll with deceleration easing.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## **Reduced Motion Support**
|
|
140
|
+
|
|
141
|
+
### **What It Does**
|
|
142
|
+
|
|
143
|
+
If user has `prefers-reduced-motion: reduce` enabled:
|
|
144
|
+
- Skips GSAP animation entirely
|
|
145
|
+
- Uses instant scroll with `window.scrollTo()`
|
|
146
|
+
- Still respects scroll offset
|
|
147
|
+
- Still sets focus on target element
|
|
148
|
+
|
|
149
|
+
### **Detection**
|
|
150
|
+
|
|
151
|
+
```javascript
|
|
152
|
+
window.matchMedia("(prefers-reduced-motion: reduce)").matches
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Result:** Users with motion sensitivity get instant, non-animated scrolling while maintaining all functionality.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## **Focus Management**
|
|
160
|
+
|
|
161
|
+
### **Automatic Focus**
|
|
162
|
+
|
|
163
|
+
After scrolling to target element:
|
|
164
|
+
1. Sets `tabindex="-1"` on target (makes it focusable without adding to tab order)
|
|
165
|
+
2. Calls `focus({ preventScroll: true })` on target
|
|
166
|
+
3. Announces target to screen readers
|
|
167
|
+
|
|
168
|
+
**Why:** Improves accessibility by moving keyboard focus to the section you scrolled to, similar to native anchor link behavior.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## **Mock Scroll (Animation Trigger)**
|
|
173
|
+
|
|
174
|
+
### **What It Does**
|
|
175
|
+
|
|
176
|
+
On page load, performs a quick scroll:
|
|
177
|
+
1. Scrolls to `1px`
|
|
178
|
+
2. Immediately scrolls back to `0px`
|
|
179
|
+
|
|
180
|
+
**Why:** Triggers scroll-based animations (IntersectionObserver, scroll triggers) that only fire when the page scrolls.
|
|
181
|
+
|
|
182
|
+
**Condition:** Only runs if page is scrollable (`document.body.scrollHeight > window.innerHeight`)
|
|
183
|
+
|
|
184
|
+
**Result:** Scroll-based animations initialize properly on page load without user interaction.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## **URL Hash Updates**
|
|
189
|
+
|
|
190
|
+
When clicking an anchor link:
|
|
191
|
+
1. Prevents default browser behavior
|
|
192
|
+
2. Updates URL hash using `history.replaceState()`
|
|
193
|
+
3. Scrolls to target
|
|
194
|
+
|
|
195
|
+
**Example:**
|
|
196
|
+
- Click `<a href="#about">`
|
|
197
|
+
- URL changes from `example.com` to `example.com#about`
|
|
198
|
+
- Page smoothly scrolls to `#about` element
|
|
199
|
+
|
|
200
|
+
**Note:** Uses `replaceState` (not `pushState`), so it doesn't create a new browser history entry.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## **Keyboard Support**
|
|
205
|
+
|
|
206
|
+
### **Supported Keys**
|
|
207
|
+
|
|
208
|
+
When an anchor link is focused:
|
|
209
|
+
- **Enter** � Triggers smooth scroll to target
|
|
210
|
+
- **Space** � Triggers smooth scroll to target
|
|
211
|
+
|
|
212
|
+
**Implementation:** Keyboard events are handled the same as clicks, providing consistent behavior.
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## **Usage Examples**
|
|
217
|
+
|
|
218
|
+
### **Basic Anchor Link**
|
|
219
|
+
|
|
220
|
+
```html
|
|
221
|
+
<nav>
|
|
222
|
+
<a href="#section-1">Section 1</a>
|
|
223
|
+
<a href="#section-2">Section 2</a>
|
|
224
|
+
</nav>
|
|
225
|
+
|
|
226
|
+
<section id="section-1">
|
|
227
|
+
<h2>Section 1</h2>
|
|
228
|
+
<p>Content here...</p>
|
|
229
|
+
</section>
|
|
230
|
+
|
|
231
|
+
<section id="section-2">
|
|
232
|
+
<h2>Section 2</h2>
|
|
233
|
+
<p>More content...</p>
|
|
234
|
+
</section>
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
**Result:** Clicking links smoothly scrolls to corresponding sections with 1-second animation.
|
|
238
|
+
|
|
239
|
+
### **With Scroll Offset**
|
|
240
|
+
|
|
241
|
+
```css
|
|
242
|
+
:root {
|
|
243
|
+
--misc--scroll-offset: 100px;
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
```html
|
|
248
|
+
<header style="position: fixed; height: 100px;">
|
|
249
|
+
<nav>
|
|
250
|
+
<a href="#content">Skip to content</a>
|
|
251
|
+
</nav>
|
|
252
|
+
</header>
|
|
253
|
+
|
|
254
|
+
<main id="content" style="margin-top: 100px;">
|
|
255
|
+
<h1>Main Content</h1>
|
|
256
|
+
</main>
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
**Result:** Clicking "Skip to content" scrolls so the main content appears 100px from top (below the fixed header).
|
|
260
|
+
|
|
261
|
+
### **Table of Contents**
|
|
262
|
+
|
|
263
|
+
```html
|
|
264
|
+
<nav class="toc">
|
|
265
|
+
<a href="#introduction">Introduction</a>
|
|
266
|
+
<a href="#features">Features</a>
|
|
267
|
+
<a href="#installation">Installation</a>
|
|
268
|
+
<a href="#usage">Usage</a>
|
|
269
|
+
</nav>
|
|
270
|
+
|
|
271
|
+
<article>
|
|
272
|
+
<section id="introduction">
|
|
273
|
+
<h2>Introduction</h2>
|
|
274
|
+
</section>
|
|
275
|
+
|
|
276
|
+
<section id="features">
|
|
277
|
+
<h2>Features</h2>
|
|
278
|
+
</section>
|
|
279
|
+
|
|
280
|
+
<section id="installation">
|
|
281
|
+
<h2>Installation</h2>
|
|
282
|
+
</section>
|
|
283
|
+
|
|
284
|
+
<section id="usage">
|
|
285
|
+
<h2>Usage</h2>
|
|
286
|
+
</section>
|
|
287
|
+
</article>
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
**Result:** Fully functional table of contents with smooth scrolling and focus management.
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## **Webflow Integration**
|
|
295
|
+
|
|
296
|
+
### **Disables Webflow's Default Behavior**
|
|
297
|
+
|
|
298
|
+
This script automatically disables:
|
|
299
|
+
1. **jQuery scroll handler** - Removes `click.wf-scroll` event listener
|
|
300
|
+
2. **CSS smooth scrolling** - Sets `scroll-behavior: auto`
|
|
301
|
+
|
|
302
|
+
**When:** On Webflow ready (`afterWebflowReady()` callback)
|
|
303
|
+
|
|
304
|
+
**Why:** Prevents conflicts between Webflow's scroll and GSAP scroll.
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## **Key Attributes Summary**
|
|
309
|
+
|
|
310
|
+
This module doesn't require any data attributes - it works automatically with standard HTML anchor links.
|
|
311
|
+
|
|
312
|
+
| Element | Requirement |
|
|
313
|
+
| ----- | ----- |
|
|
314
|
+
| Anchor link | `href="#target-id"` |
|
|
315
|
+
| Target element | `id="target-id"` |
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## **API**
|
|
320
|
+
|
|
321
|
+
This module has no public API methods. It runs automatically and handles all anchor links on the page.
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## **Notes**
|
|
326
|
+
|
|
327
|
+
1. **GSAP required** - Must load GSAP and ScrollToPlugin before this script
|
|
328
|
+
2. **Auto-initializes** - Runs on every page load
|
|
329
|
+
3. **Disables Webflow scroll** - Replaces Webflow's default anchor link behavior
|
|
330
|
+
4. **Accessibility first** - Respects reduced motion, manages focus
|
|
331
|
+
5. **No configuration** - Works out of the box with standard HTML
|
|
332
|
+
6. **CSS variable for offset** - Use `--misc--scroll-offset` for custom offset
|
|
333
|
+
7. **Mock scroll triggers animations** - Ensures scroll-based animations initialize
|
|
334
|
+
8. **Clean destroy** - Removes listeners and re-enables CSS smooth scrolling on cleanup
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## **Common Issues**
|
|
339
|
+
|
|
340
|
+
**Smooth scroll not working:**
|
|
341
|
+
|
|
342
|
+
1. Verify GSAP and ScrollToPlugin are loaded before main script
|
|
343
|
+
2. Check browser console for GSAP errors
|
|
344
|
+
3. Ensure anchor `href` starts with `#` and matches target `id`
|
|
345
|
+
4. Verify target element exists in DOM
|
|
346
|
+
|
|
347
|
+
**Scroll offset not working:**
|
|
348
|
+
|
|
349
|
+
1. Check CSS variable is defined: `--misc--scroll-offset: 100px`
|
|
350
|
+
2. Verify it's on `:root` or `html` element (computed style)
|
|
351
|
+
3. Ensure value is in pixels (no other units supported)
|
|
352
|
+
4. Check computed styles in browser DevTools
|
|
353
|
+
|
|
354
|
+
**Focus not working after scroll:**
|
|
355
|
+
|
|
356
|
+
1. This is expected behavior for accessibility
|
|
357
|
+
2. Target element gets `tabindex="-1"` and focus
|
|
358
|
+
3. Use CSS to style `:focus` state if needed
|
|
359
|
+
4. Don't prevent this - it's important for screen reader users
|
|
360
|
+
|
|
361
|
+
**Scroll animations not triggering on load:**
|
|
362
|
+
|
|
363
|
+
1. Mock scroll only runs if page is scrollable
|
|
364
|
+
2. Check that `document.body.scrollHeight > window.innerHeight`
|
|
365
|
+
3. If page isn't tall enough, animations may not trigger
|
|
366
|
+
4. Add more content or adjust animation triggers
|
|
367
|
+
|
|
368
|
+
**Reduced motion not instant:**
|
|
369
|
+
|
|
370
|
+
1. Check browser/OS motion settings
|
|
371
|
+
2. Test with DevTools: Rendering � Emulate CSS media `prefers-reduced-motion: reduce`
|
|
372
|
+
3. Verify scroll is instant (no animation)
|
|
373
|
+
|
|
374
|
+
**URL hash not updating:**
|
|
375
|
+
|
|
376
|
+
1. Check `history.replaceState` is supported (all modern browsers)
|
|
377
|
+
2. Verify no errors in console
|
|
378
|
+
3. Ensure target element has `id` attribute
|
|
379
|
+
4. Check that link click isn't being prevented elsewhere
|
|
380
|
+
|
|
381
|
+
**Conflicts with other scroll libraries:**
|
|
382
|
+
|
|
383
|
+
1. This module disables Webflow's scroll on init
|
|
384
|
+
2. If using Lenis or other smooth scroll libraries, may conflict
|
|
385
|
+
3. Choose one smooth scroll solution per site
|
|
386
|
+
4. Remove this module if using another smooth scroll library
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
# **Page Transition System Documentation**
|
|
2
|
+
|
|
3
|
+
## **Overview**
|
|
4
|
+
|
|
5
|
+
The page transition system provides smooth animated transitions between pages in your Webflow site. It automatically triggers entrance animations on page load and exit animations when clicking internal links, creating a seamless single-page-application feel.
|
|
6
|
+
|
|
7
|
+
**Note:** This module auto-initializes by default unless the `no-transition` attribute is added to the script tag.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## **Page Transitions**
|
|
12
|
+
|
|
13
|
+
### **Required Elements**
|
|
14
|
+
|
|
15
|
+
**Transition Trigger** *(invisible element that triggers Webflow IX animation)*
|
|
16
|
+
|
|
17
|
+
* data-hs-transition="trigger"
|
|
18
|
+
* Webflow IX interaction attached (entrance and exit animations)
|
|
19
|
+
|
|
20
|
+
**Transition Element** *(visual overlay that covers the page during transition)*
|
|
21
|
+
|
|
22
|
+
* data-hs-transition="element"
|
|
23
|
+
* Should cover entire viewport
|
|
24
|
+
* Contains visual transition effect (fade, slide, etc.)
|
|
25
|
+
|
|
26
|
+
**Exit Time** *(optional attribute on transition element)*
|
|
27
|
+
|
|
28
|
+
* data-hs-exit-time="0.5"
|
|
29
|
+
* Time in seconds to wait before navigating to new page
|
|
30
|
+
* Should match your Webflow exit animation duration
|
|
31
|
+
|
|
32
|
+
**Entrance Delay** *(optional attribute on transition element)*
|
|
33
|
+
|
|
34
|
+
* data-hs-delay="0.3"
|
|
35
|
+
* Delay in seconds before triggering entrance animation on FIRST page load only
|
|
36
|
+
* Subsequent page loads trigger instantly (no delay)
|
|
37
|
+
* Default: 0 (instant trigger)
|
|
38
|
+
|
|
39
|
+
**Typical element layout:**
|
|
40
|
+
|
|
41
|
+
1. Transition Wrapper
|
|
42
|
+
1. Transition Trigger (data-hs-transition="trigger")
|
|
43
|
+
1. Hidden element (0px × 0px, invisible)
|
|
44
|
+
2. Transition Element (data-hs-transition="element")
|
|
45
|
+
1. Full-screen overlay with animation
|
|
46
|
+
2. Attribute: data-hs-exit-time="0.5"
|
|
47
|
+
3. Attribute: data-hs-delay="0.3"
|
|
48
|
+
|
|
49
|
+
### **What It Does**
|
|
50
|
+
|
|
51
|
+
1. **Page load animation** - Clicks trigger on load to play entrance animation
|
|
52
|
+
2. **Link interception** - Captures clicks on internal links
|
|
53
|
+
3. **Exit animation** - Clicks trigger before navigation
|
|
54
|
+
4. **Timed navigation** - Waits for exit animation to complete, then navigates
|
|
55
|
+
5. **Back button handling** - Reloads page when using browser back button
|
|
56
|
+
6. **Resize handling** - Hides transition element on window resize to prevent visual bugs
|
|
57
|
+
7. **Session awareness** - Tracks first page load via sessionStorage
|
|
58
|
+
|
|
59
|
+
### **When It Runs**
|
|
60
|
+
|
|
61
|
+
* Auto-initializes on page load (unless `no-transition` attribute is present)
|
|
62
|
+
* Waits for Webflow to be ready (`afterWebflowReady()`)
|
|
63
|
+
* Adds 50ms delay after Webflow ready to ensure IX is fully loaded
|
|
64
|
+
* Runs on every page in a multi-page site
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## **Disabling Transitions**
|
|
69
|
+
|
|
70
|
+
### **no-transition Attribute**
|
|
71
|
+
|
|
72
|
+
Add `no-transition` attribute to the script tag to disable page transitions:
|
|
73
|
+
|
|
74
|
+
```html
|
|
75
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@hortonstudio/main@latest" no-transition></script>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**When to use:**
|
|
79
|
+
- During development/testing
|
|
80
|
+
- On sites where transitions cause issues
|
|
81
|
+
- For specific pages where you don't want transitions
|
|
82
|
+
|
|
83
|
+
**Result:** The transition module will not load, and pages will navigate normally without animations.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## **Interaction Requirements (IX3)**
|
|
88
|
+
|
|
89
|
+
**CRITICAL:** Webflow interactions MUST be set up on the trigger element.
|
|
90
|
+
|
|
91
|
+
**Triggers:**
|
|
92
|
+
|
|
93
|
+
1. **Click trigger** on `[data-hs-transition="trigger"]`
|
|
94
|
+
1. First click: Play entrance animation
|
|
95
|
+
2. Second click: Play exit animation (or reverse)
|
|
96
|
+
|
|
97
|
+
**Timeline (Entrance):**
|
|
98
|
+
|
|
99
|
+
1. 0s: Transition element visible (covering page)
|
|
100
|
+
2. 0s-0.5s: Fade out or slide out animation
|
|
101
|
+
3. 0.5s: Transition element hidden
|
|
102
|
+
|
|
103
|
+
**Timeline (Exit):**
|
|
104
|
+
|
|
105
|
+
1. 0s: Transition element hidden
|
|
106
|
+
2. 0s-0.5s: Fade in or slide in animation
|
|
107
|
+
3. 0.5s: Transition element visible (covering page)
|
|
108
|
+
|
|
109
|
+
**Important:** The `data-hs-exit-time` should match the exit animation duration.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## **Link Behavior**
|
|
114
|
+
|
|
115
|
+
### **Links that trigger transitions:**
|
|
116
|
+
|
|
117
|
+
- Internal links (same hostname)
|
|
118
|
+
- Links without `target="_blank"`
|
|
119
|
+
- Links without `#` hash in href
|
|
120
|
+
- Links with valid `href` attribute
|
|
121
|
+
|
|
122
|
+
### **Links that DON'T trigger transitions:**
|
|
123
|
+
|
|
124
|
+
- External links (different domain)
|
|
125
|
+
- Links with `target="_blank"`
|
|
126
|
+
- Anchor links (`href="#section"`)
|
|
127
|
+
- Links without `href` attribute
|
|
128
|
+
- `mailto:` and `tel:` links
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## **Fallback Script (Recommended)**
|
|
133
|
+
|
|
134
|
+
Add this script to your site's `<head>` BEFORE the main script to prevent transition elements from blocking the page if the codebase fails to load:
|
|
135
|
+
|
|
136
|
+
```html
|
|
137
|
+
<script>
|
|
138
|
+
// Prevent transition if codebase hasn't loaded
|
|
139
|
+
new MutationObserver((m,o)=>{if(document.documentElement.classList.contains('w-mod-ix3')){if(!document.documentElement.classList.contains('hs-main'))document.querySelectorAll('[data-hs-transition="element"]').forEach(el=>el.remove());o.disconnect()}}).observe(document.documentElement,{attributes:true,attributeFilter:['class']})
|
|
140
|
+
</script>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**What it does:**
|
|
144
|
+
1. Waits for Webflow IX to load (`w-mod-ix3` class)
|
|
145
|
+
2. Checks if main codebase loaded (`hs-main` class)
|
|
146
|
+
3. If main codebase didn't load, removes all transition elements
|
|
147
|
+
4. Prevents transition overlay from blocking page content
|
|
148
|
+
|
|
149
|
+
**Why it's needed:** If the CDN fails or the script errors, the transition element could cover the entire page permanently, making the site unusable.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## **Usage Example**
|
|
154
|
+
|
|
155
|
+
### **Basic Setup**
|
|
156
|
+
|
|
157
|
+
```html
|
|
158
|
+
<!-- Fallback script in <head> -->
|
|
159
|
+
<script>
|
|
160
|
+
new MutationObserver((m,o)=>{if(document.documentElement.classList.contains('w-mod-ix3')){if(!document.documentElement.classList.contains('hs-main'))document.querySelectorAll('[data-hs-transition="element"]').forEach(el=>el.remove());o.disconnect()}}).observe(document.documentElement,{attributes:true,attributeFilter:['class']})
|
|
161
|
+
</script>
|
|
162
|
+
|
|
163
|
+
<!-- Main script -->
|
|
164
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@hortonstudio/main@latest"></script>
|
|
165
|
+
|
|
166
|
+
<!-- Transition wrapper in <body> -->
|
|
167
|
+
<div class="page-transition">
|
|
168
|
+
<!-- Invisible trigger -->
|
|
169
|
+
<div data-hs-transition="trigger" style="width: 0; height: 0; opacity: 0;"></div>
|
|
170
|
+
|
|
171
|
+
<!-- Visual overlay with 0.5s exit time -->
|
|
172
|
+
<div data-hs-transition="element" data-hs-exit-time="0.5" style="position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: black; z-index: 9999;">
|
|
173
|
+
<!-- Optional loading animation or logo -->
|
|
174
|
+
</div>
|
|
175
|
+
</div>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### **With Custom Exit Time**
|
|
179
|
+
|
|
180
|
+
```html
|
|
181
|
+
<div data-hs-transition="element" data-hs-exit-time="1.2">
|
|
182
|
+
<!-- Longer transition: 1.2 seconds -->
|
|
183
|
+
</div>
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
**Result:** JavaScript waits 1200ms after clicking the trigger before navigating to the new page.
|
|
187
|
+
|
|
188
|
+
### **With Entrance Delay**
|
|
189
|
+
|
|
190
|
+
```html
|
|
191
|
+
<div data-hs-transition="element" data-hs-exit-time="0.5" data-hs-delay="0.3">
|
|
192
|
+
<!-- First page load: waits 300ms before entrance animation -->
|
|
193
|
+
<!-- Subsequent loads: instant entrance animation -->
|
|
194
|
+
</div>
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Result:**
|
|
198
|
+
- First visit to site: Waits 300ms, then triggers entrance animation
|
|
199
|
+
- Navigating to other pages: Triggers entrance animation immediately
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## **Session Storage**
|
|
204
|
+
|
|
205
|
+
The system uses `sessionStorage` to track the first page load:
|
|
206
|
+
|
|
207
|
+
**Key:** `transition-loaded`
|
|
208
|
+
**Value:** `'true'`
|
|
209
|
+
|
|
210
|
+
**Purpose:** Differentiates between initial site visit and subsequent page navigations. Used to determine whether to apply the entrance delay (`data-hs-delay`):
|
|
211
|
+
- **First load:** Delay is applied before entrance animation
|
|
212
|
+
- **Subsequent loads:** No delay, entrance animation triggers immediately
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## **Resize Handling**
|
|
217
|
+
|
|
218
|
+
When the browser window is resized:
|
|
219
|
+
- The transition element is hidden (`display: none`)
|
|
220
|
+
- Prevents visual bugs with fixed positioning during resize
|
|
221
|
+
- Transition will work again on next navigation
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## **Back Button Behavior**
|
|
226
|
+
|
|
227
|
+
When using the browser back button:
|
|
228
|
+
- Page is fully reloaded (not cached)
|
|
229
|
+
- Ensures transition animations play correctly
|
|
230
|
+
- Uses `window.onpageshow` event with `persisted` check
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## **Key Attributes Summary**
|
|
235
|
+
|
|
236
|
+
| Attribute | Purpose | Required On |
|
|
237
|
+
| ----- | ----- | ----- |
|
|
238
|
+
| `data-hs-transition="trigger"` | Animation trigger | Hidden trigger element |
|
|
239
|
+
| `data-hs-transition="element"` | Visual transition overlay | Transition element |
|
|
240
|
+
| `data-hs-exit-time="0.5"` | Exit duration in seconds | Transition element (optional) |
|
|
241
|
+
| `data-hs-delay="0.3"` | First load entrance delay in seconds | Transition element (optional) |
|
|
242
|
+
| `no-transition` | Disable transitions | Script tag (optional) |
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## **Notes**
|
|
247
|
+
|
|
248
|
+
1. **Auto-initializes** - Runs by default unless `no-transition` attribute is present
|
|
249
|
+
2. **Webflow IX required** - Must have click interaction on trigger element
|
|
250
|
+
3. **Exit time critical** - Should match your Webflow animation duration
|
|
251
|
+
4. **Fallback script recommended** - Prevents site from being blocked if script fails
|
|
252
|
+
5. **Session tracking** - Uses sessionStorage to track first load
|
|
253
|
+
6. **Back button reloads** - Forces full page reload on back navigation
|
|
254
|
+
7. **Resize hides transition** - Prevents visual bugs during window resize
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## **Common Issues**
|
|
259
|
+
|
|
260
|
+
**Transition element blocks entire page:**
|
|
261
|
+
|
|
262
|
+
1. Ensure main script is loading correctly (check for `hs-main` class on `<html>`)
|
|
263
|
+
2. Add the fallback script to `<head>` to auto-remove transition on failure
|
|
264
|
+
3. Check browser console for script errors
|
|
265
|
+
|
|
266
|
+
**Page navigates without exit animation:**
|
|
267
|
+
|
|
268
|
+
1. Verify `data-hs-exit-time` attribute is set on transition element
|
|
269
|
+
2. Check that Webflow IX click interaction is on trigger element
|
|
270
|
+
3. Ensure exit animation is playing when trigger is clicked second time
|
|
271
|
+
|
|
272
|
+
**Exit animation is cut short:**
|
|
273
|
+
|
|
274
|
+
1. Increase `data-hs-exit-time` to match animation duration
|
|
275
|
+
2. Test animation by manually clicking trigger element
|
|
276
|
+
3. Verify Webflow IX timeline duration matches exit time
|
|
277
|
+
|
|
278
|
+
**Entrance animation not playing:**
|
|
279
|
+
|
|
280
|
+
1. Check that Webflow IX is loaded (`w-mod-ix3` class on `<html>`)
|
|
281
|
+
2. Verify 50ms delay is sufficient (can be timing issue)
|
|
282
|
+
3. Ensure trigger element exists before script runs
|
|
283
|
+
|
|
284
|
+
**Links not triggering transitions:**
|
|
285
|
+
|
|
286
|
+
1. Check link is internal (same hostname)
|
|
287
|
+
2. Verify link doesn't have `target="_blank"`
|
|
288
|
+
3. Ensure href doesn't contain `#` hash
|
|
289
|
+
4. Check that click event listener is attached (inspect in debugger)
|
|
290
|
+
|
|
291
|
+
**Transition shows on window resize:**
|
|
292
|
+
|
|
293
|
+
1. This is expected - resize handler hides it with `display: none`
|
|
294
|
+
2. Will work again on next navigation
|
|
295
|
+
3. Check that resize handler is attached correctly
|
|
296
|
+
|
|
297
|
+
**Back button doesn't work:**
|
|
298
|
+
|
|
299
|
+
1. Page should reload when using back button
|
|
300
|
+
2. Check that `onpageshow` handler is attached
|
|
301
|
+
3. Verify `event.persisted` is true when using back button
|
|
@@ -33,6 +33,10 @@ export async function init() {
|
|
|
33
33
|
const exitTimeAttr = transitionElement.getAttribute('data-hs-exit-time');
|
|
34
34
|
const exitTime = exitTimeAttr ? parseFloat(exitTimeAttr) * 1000 : 0;
|
|
35
35
|
|
|
36
|
+
// Get delay time for first load from data attribute (in seconds)
|
|
37
|
+
const delayAttr = transitionElement.getAttribute('data-hs-delay');
|
|
38
|
+
const delayTime = delayAttr ? parseFloat(delayAttr) * 1000 : 0;
|
|
39
|
+
|
|
36
40
|
// Page Load - Trigger entrance animation
|
|
37
41
|
// Check if this is the first page load of the session
|
|
38
42
|
const isFirstLoad = !sessionStorage.getItem('transition-loaded');
|
|
@@ -43,9 +47,16 @@ export async function init() {
|
|
|
43
47
|
});
|
|
44
48
|
};
|
|
45
49
|
|
|
46
|
-
|
|
47
|
-
if (isFirstLoad) {
|
|
50
|
+
// If first load and delay is set, wait before triggering
|
|
51
|
+
if (isFirstLoad && delayTime > 0) {
|
|
52
|
+
setTimeout(triggerAnimation, delayTime);
|
|
48
53
|
sessionStorage.setItem('transition-loaded', 'true');
|
|
54
|
+
} else {
|
|
55
|
+
// Subsequent loads or no delay: trigger immediately
|
|
56
|
+
triggerAnimation();
|
|
57
|
+
if (isFirstLoad) {
|
|
58
|
+
sessionStorage.setItem('transition-loaded', 'true');
|
|
59
|
+
}
|
|
49
60
|
}
|
|
50
61
|
|
|
51
62
|
// On Link Click
|