Hover✨ Premium

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.

CSSJSMobile

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

Feed refresh in a messaging app — native pull-down interaction to load new conversations — Pull to Refresh example 1

① Feed refresh in a messaging app — native pull-down interaction to load new conversations

WhenThe user pulls the message feed down to load recent conversations. The phone occupies the full central area; the indicator and content shift visibly.
WhyPull-to-refresh is the dominant navigation pattern on mobile; showing it in its native context (a message feed) is more convincing than in an isolated demo.
SettingsPhone scaled up to 220×260 px, content items alternating between two violet tones to evoke message bubbles.
Mobile sync widget in a B2B dashboard — on-demand sync action inside an analytics card — Pull to Refresh example 2

② Mobile sync widget in a B2B dashboard — on-demand sync action inside an analytics card

WhenA 'Mobile sync' card in a dashboard displays a mini-phone; clicking triggers the refresh sequence to signal that mobile data is being updated.
WhyThe pull-to-refresh visual metaphor reassures users that data comes from mobile devices and refreshes on demand.
SettingsPhone scaled down to 72×92 px inside the card, indicator and content sized proportionally; 'Click to sync' hint above the last-sync timestamp.
Animated feature illustration on a mobile app landing page — two-column marketing split section — Pull to Refresh example 3

③ Animated feature illustration on a mobile app landing page — two-column marketing split section

WhenThe left half presents the product pitch; the phone on the right replays the pulling → refreshing loop to show the app behaviour without a video or GIF.
WhyA native HTML animation avoids video production costs and remains interactive (click to restart), while concretely demonstrating what the app does.
SettingsPhone at 160×220 px in the landing colour scheme (indigo border), slightly taller and two-tone items; auto-loop started by scene script.

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", and aria-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.

Chrome 49+✓ Full (measured)
Firefox 55+✓ Full
Safari 9+✓ Full
Edge 79+✓ Full (Chromium engine)
Mobile iOS 9+✓ Full (simple tap)
Android Chrome 49+✓ Full (simple tap)

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):

index.html — structure
<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 / propertyDefaultEffect
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

Yes. The code handles vertical drag via pointer events (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).
Yes. Call the trigger in the fourth setTimeout step (after removing the classes) to restart the sequence automatically. Check prefers-reduced-motion before starting a loop.
Yes. Each .fx-0365-root is managed independently by the script. Each phone has its own sequence state; triggering one does not affect the others.