The Hunt for justify-content
One visit to w3schools' CSS Flexbox tutorial, recorded with the LogNroll logger and replayed below. The visitor wanted one property. It took a consent wall, a search box that ignored their typing, two dead clicks and six thousand pixels of scrolling to reach a link to it.
Dmytro Vavreniuk
Product Engineer
Press play, or use any timestamp below to jump there. Orange marks are clicks, red is a rage click, green is a page change. The player skips idle stretches.
Analytics would record this visit as two page views and a search. The replay shows a visitor who knew what they wanted and spent 100 seconds working around the page to get it. That gap is what session replay is for.
What happened, second by second
The visitor is learning CSS layout. They know what they want to do: centre a row of items. They don't remember the property name. Here is their visit as the recording tells it.
Lands on CSS Flexbox. A consent dialog covers the page and the document is scroll-locked (
data-fast-cmp-lockedon<html>). In the replay it shows as a grey veil: the dialog itself is drawn inside a shadow root, which the snapshot doesn't include.The lock attribute disappears and the dialog's class flips off: the visitor declined. The click itself isn't in the recording, because the consent manager draws its buttons where the logger can't see them. Keep that blind spot in mind when reading any replay of a consented page.
Three clicks in a hundred milliseconds on Item 3 of the blue demo container. The grey tiles look like buttons. They are an
<h3>inside a static figure, so nothing happens.Reads down the page in three scrolls, past a 300 px ad container that stays empty except for a Remove ads link.
Clicks the magnifier in the top bar. The search field slides open and the visitor types justify content center. The recording shows no input events for the next sixteen seconds: the field opened without focus, so every keystroke went to the page.
Clicks into the field and types again. The input arrives at 1:14 with
justify content; the suggestion list offers CSS Flexbox Container, and the visitor takes it at 1:22.The second page, CSS Flex Container. Its property list mentions
justify-contentfifth from the top.Two clicks on that mention, a second apart. It is a
<code>label, not a link.Scrolls 6,081 px in six moves through
flex-direction,flex-wrapandflex-flow. None of them is the property they came for.At the bottom, a section called Flex Container Subpages finally links to
justify-content. The cursor rests on it as the session ends, 100 seconds after the search began.
What the replay tells the team
A single session is an anecdote, so treat these as leads to check against many sessions, not conclusions. Each one links to the moment in the recording that shows it. For how to turn findings like these into product work, see from rage clicks to roadmap.
The search box opens without focus
Opening search and starting to type is the natural sequence. On this page it throws the first query away, and the visitor has to notice, click the field and type again.
Fix: Focus the input when the search panel opens. Then watch for the pattern at scale: a click on the search icon followed by no input event within a few seconds.
The property list names the answer but doesn’t link it
The search suggestion lands on an overview page. The list at its top names every container property, yet only a footer section 6,000 px lower links to the justify-content subpage.
Fix: Make each property in that list a link to its section or subpage, and include the subpages in search suggestions for their own property names.
Demo items invite clicks they can’t answer
The flex items are bordered grey tiles on a blue field, which reads as a row of buttons. The rage click on Item 3 is the visitor checking.
Fix: Either make the demo respond (toggle justify-content values on click, exactly what this visitor was after) or style the tiles so they read as a diagram.
Invisible menus account for 92% of DOM changes
Of 3,385 DOM mutations, 3,120 are class toggles on cards inside the closed Tutorials, Exercises and Certificates menus. Nobody sees them, but the browser still restyles them, and they make up 1.3 MB of this 3.7 MB recording.
Fix: Stop animating menu cards while their menu is closed. On the recording side, ignore that subtree to keep sessions small.
Declining consent doesn’t quiet the network
The page was locked for its first 25 seconds. After the visitor declined, 149 more requests went to advertising, bidding and consent hosts; over the whole session, 211 of 301 requests went to 24 hosts other than the site itself. Declining personal-data processing doesn't rule out contextual ads, so read this as a load-time cost, not necessarily a compliance problem.
How this recording was made
The LogNroll SDK loads a logger that snapshots the page, then records mutations, clicks, scrolls, inputs, console output and network calls. Its save-local mode also keeps every event in the browser's private file storage, so a session can be exported as a file. On a site you don't own, you can switch it on from the browser console:
// 1. Keep events locally, starting from a clean capture
localStorage.setItem('lnr-save-local', '1');
localStorage.setItem('lnr-save-local-reset', '1');
// 2. Load the SDK and start a session
const s = document.createElement('script');
s.src = 'https://cdn.jsdelivr.net/npm/@lognroll/[email protected]/dist/index.js';
s.onload = () => LognRoll.initSession('<your company id>', {});
document.head.appendChild(s);
// 3. Browse. On each new page, run step 2 again: the logger
// restores earlier events from storage and keeps appending.
// 4. Export everything as one file
logger.downloadSession();The visit was driven by an AI agent in a browser on 9 November 2026, following a realistic task, so the visitor here is a stand-in, not a member of the public. Read it as a demonstration of how to use replay, not as research about w3schools' users.
Before publishing, the file was cleaned: the logger's own retry warnings, the device's language and user agent, and the consent manager's user ID and country were removed, the same kind of scrubbing we recommend in privacy-first session recording. The page's stylesheets, fonts and images were packed into a separate asset bundle so the replay renders without loading anything from the original site.
The second page was instrumented by hand a few seconds after it loaded, so about 20 seconds between the suggestion click at 1:22 and the second snapshot at 1:42 are missing.
The embedded player
The player on this page is a small web component that reads an exported session from a URL. It decodes the file in the browser (a stream of timestamped points: snapshot HTML, mutation records, clicks, scrolls, inputs, console and network entries), rebuilds the page inside a sandboxed frame with scripts disabled, and replays mutations in order. Seeking backwards reloads the nearest snapshot and fast-forwards. If you want the engineering detail, we cover the same pipeline in session replay architecture.
<script src="https://lognroll.com/replays/player.js"></script>
<lnr-replay src="session.bin.gz" assets="assets.json.gz"></lnr-replay>Rage and dead clicks are flagged by simple rules: three or more clicks within 1.2 seconds and 40 px of each other, or a click on an element that isn't interactive. You can also download this recording (gzipped) and open it in the LogNroll player after unzipping.
Try it on your own site
Every finding above came from one recording and about ten minutes of watching. On your own product, start from a filter rather than random sessions: sessions with an error, sessions that abandoned a step, or sessions with rage clicks. LogNroll bundles session replay, heatmaps, error tracking and product analytics, with a free tier of 1,000 sessions per month.
See what your users actually do. Start session replay for free.