Mobile Stories Viewer — Free HTML CSS JS UI Snippet
Mobile Stories Viewer · Mobile · Plain HTML, CSS & JS · Live preview
What's included
Features
About this UI Snippet
Mobile Stories Viewer — Segmented Story UI

A stories viewer is a self-driving slideshow — segmented progress bars across the top that fill one at a time, tap zones to jump forward or back, and hold-to-pause. This snippet builds a complete, interactive one inside a CSS phone frame: the active segment fills over four seconds and auto-advances, tapping the left or right of the screen navigates, pressing and holding pauses, and a reply bar with a like button sits at the bottom — in HTML, CSS, and vanilla JavaScript with no dependency.
CSS-driven segment timing
Each story has a progress bar whose inner fill runs a four-second msvFill keyframe animation. The timing lives entirely in CSS, so there is no setInterval counting milliseconds — the browser drives the fill, and JavaScript only listens for when it finishes. Completed segments get a done class that pins them full, and future segments stay empty, so the bar row always reflects your position in the story.
Auto-advance via animationend
Rather than a timer, the viewer advances when the active bar's fill animation ends: an animationend listener checks the event's animationName and moves to the next slide, or stops at the last one. This ties the advance precisely to the visual completion, so the story never jumps early or late relative to the bar.
Tap zones and restarting a segment
Two invisible buttons cover the left and right ~38% of the stage for previous and next — the exact gesture zones stories apps use. Navigating re-shows a slide and restarts its bar by clearing the animation, forcing a reflow with void inner.offsetWidth, and re-applying it, so replaying a segment always starts its timer from zero.
Hold to pause
Pressing anywhere on the stage sets a paused class on the active bar that flips animation-play-state to paused, freezing both the fill and the countdown; releasing resumes it. Because pausing is pure CSS state, the fill picks up exactly where it stopped — the same read-without-rushing behavior real viewers offer.
Reply and like
The bottom bar has a reply input that fires a confirmation toast on send (Enter or the send button), and a like heart that toggles filled — the two lightweight engagement actions every story overlay includes.
Accessibility and performance
The navigation zones, the close and like buttons, and the send control are real buttons with aria-labels, so the viewer can be driven from the keyboard and screen readers announce each action. Auto-advancing content is inherently tricky for accessibility, so when you adapt this, honor prefers-reduced-motion by pausing the auto-advance and letting users step through manually, and expose the current position — "story 2 of 4" — through an aria-live region so non-visual users know where they are. The hold-to-pause gesture also gives everyone a way to stop the timer, which is a WCAG-friendly escape hatch for moving content. Performance is a strength of the CSS-timed design: the segment fill and its pause are pure CSS, so no timer runs on the main thread and pausing costs nothing, and advancing is driven by a single animationend event rather than polling. Slides cross-fade with opacity, which the browser composites cheaply. Swapping the gradients for images or video is the only heavier part; preload the next slide so transitions stay seamless.
Reusing it
Replace the gradient slides with real images or video, feed the segments from a story array, and post replies to your API. Lift the overlay out of the phone frame for a responsive web stories player, or keep it framed after a mobile feed screen to present a full social app.
Step by step
How to Use
- 1Paste HTML, CSS, and JSA full-screen story opens and the first segment bar begins filling.
- 2Let it auto-advanceWhen a segment bar finishes, the viewer moves to the next story automatically.
- 3Tap to navigateTap the right side to skip ahead or the left side to go back a story.
- 4Hold to pausePress and hold anywhere to freeze the current segment; release to resume where it stopped.
- 5Like the storyThe heart toggles between outline and filled.
- 6Send a replyType in the reply bar and press Enter or send — a confirmation toast appears.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
Each segment's fill runs a four-second CSS keyframe animation. Instead of counting time in JS, an animationend listener checks the event's animationName and advances to the next slide when the active bar's fill completes. The browser owns the timing, so the advance stays perfectly in step with the visible bar.
Pressing the stage adds a paused class to the active bar that sets animation-play-state to paused, freezing the fill. Releasing removes it and the animation resumes from the exact point it stopped, because pausing a CSS animation preserves its progress. No time bookkeeping is needed in JavaScript.
A CSS animation will not replay just by re-adding a class. When you navigate back to a story, the code clears the fill's animation, reads offsetWidth to force a reflow, then restores it. That reflow makes the browser start the animation fresh, so the segment's timer begins again at zero.
Two transparent buttons overlay the left and right roughly 38 percent of the stage. Tapping the right one advances and the left one goes back, matching how stories apps split the screen into gesture regions. Because they are real buttons, they are also keyboard-focusable.
Hold the current index and paused flag in state. Advance on the fill's onAnimationEnd, and drive the active and done bar classes from the index. Restart a segment with a key change keyed to the index so it remounts. Bind pause to pointer handlers. Replace the gradient slides with media and post replies to your API. Tailwind expresses the bars and slides with utilities.