Pull to Refresh
A mobile pull-to-refresh simulation on a CSS smartphone mockup: click or press Space to trigger the indicator + content refresh sequence. Ideal for documenting or demonstrating this interaction pattern.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Hover has 48 effects, including 5 free. Explore the category →
3 usage examples



How it works
The .fx-0365-root root (250 px tall, rgb(26, 26, 36) background) centers a CSS phone mockup (.mi-pull-phone, 160×280 px, rounded corners, dark background). The phone holds a refresh indicator (.mi-pull-indicator) and a content area (.mi-pull-content) with three placeholder lines. The indicator starts off-screen (negative translateY), the SVG arrow pointing upward.
The script fires on a click on the phone (or via Space / Enter on the keyboard), or on a downward pointer drag of at least 70 px. It checks that no animation is in progress, then chains three steps via setTimeout: (1) add .pulling — the indicator slides into view with translateY(0), the arrow rotates 180°, and the content shifts down; (2) after 800 ms, remove .pulling and add .refreshing — the CSS spinner replaces the arrow (infinite rotation); (3) after 1 500 ms, remove .refreshing and reset. The total duration is about 2.3 s.
The phone has tabindex="0", role="button", and aria-label="Simulate refresh". The sequence is intentionally a clicked demo, not a real downward finger drag. This is stated honestly in the fiche: for a real tactile pull-to-refresh, use a React Native component or a native library.
Accessibility
- Keyboard: the phone has
tabindex="0",role="button", andaria-label; Tab reaches it, Space or Enter triggers the simulation. The focus outline (:focus-visible) appears on keyboard navigation. - Reduced motion: under
prefers-reduced-motion: reduce, all CSS transitions (indicator drop, content shift) and the spinner animation are removed. The state sequence still plays on click, but changes are instant. - Touch limitation honestly stated: on a real mobile device, the effect responds to a simple click/tap only. It does not simulate a real downward drag gesture. This component suits a demo or tutorial; for a functional pull-to-refresh in a mobile app, use a native component.
Browser compatibility
CSS (transitions, spinner animation) + 0.7 KB of JavaScript (classList, setTimeout, keydown), no dependency. Verified in Chromium 151: full 4-step sequence, click and keyboard triggers, two independent copies, reduced-motion with no animation, 0 errors. The preview captures show the animation auto-replayed by the scene code: this behaviour is not included in the sold code.
Without JavaScript, the phone is displayed at rest with no interaction. Without CSS transitions, state changes are instant with no animation.
The code
HTML structure to paste into your page (the CSS + JS come with your purchase):
<div class="fx-0365-root">
<div class="mi-pull-scene">
<div>
<div class="mi-pull-phone" tabindex="0" role="button" aria-label="Pull to refresh">
<div class="mi-pull-indicator">
<svg viewBox="0 0 24 24">
<path d="M12 19V5M5 12l7-7 7 7"></path>
</svg>
</div>
<div class="mi-pull-content">
<div class="mi-pull-item"></div>
<!-- repeat for 4 more items -->
</div>
</div>
<p class="mi-pull-hint">Pull down, click or press Space</p>
</div>
</div>
</div>
One-time payment, no subscription — the code is yours forever
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
Sequence durations (JS — setTimeout values) |
400 ms (pull), 1 200 ms (refresh), 500 ms (return) | Extend the refresh delay (e.g. 2 000 ms) for a more contemplative demo; reduce to 600 ms for a quick one. |
Phone content (HTML — .mi-pull-content) |
Three CSS placeholder lines | Replace the divs with real cards, simulated text lines, colored avatars. Keep the .mi-pull-item classes so transitions apply correctly. |
Indicator color (CSS — stroke on .mi-pull-indicator svg and spinner color) |
Blue #818cf8 |
Change to green or orange to match your brand. Adjust the spinner color in .mi-pull-indicator::after with the same border value. |
Button label (HTML — aria-label on .mi-pull-phone) |
Simulate refresh | Adapt to the language and context of your page. This label is read by screen readers and shown in the visible hint above the phone. |
FAQ
pointerdown, pointermove, pointerup), compatible with both mouse and touch screens. Pull down at least 70 px to trigger the sequence. A simple tap or click also works, as does the keyboard (Enter or Space).setTimeout step (after removing the classes) to restart the sequence automatically. Check prefers-reduced-motion before starting a loop..fx-0365-root is managed independently by the script. Each phone has its own sequence state; triggering one does not affect the others.