Skip to content
← writing

Freeze any hover state with one line of JavaScript

devtools
debugging
css
bookmarklet

Some elements only exist while you're hovering: a tooltip, a dropdown, a custom cursor, the :hover styles on a button. The moment you move your mouse toward the DevTools panel to inspect them — they're gone. You can't select what you can't keep on screen.

There's a one-line trick that's been quietly passed around for years, and it solves exactly this:

setTimeout(() => { debugger; }, 3000);

Open the console, run it, then hover the thing you care about. After 3 seconds the debugger statement trips, the JS event loop halts, and the page is frozen mid-state. Now you can poke around the Elements panel freely — the tooltip is still open, the dropdown still expanded, the :hover styles still applied.

Try it

Drag this to your bookmarks bar, or copy it. Pick how long you need to get your mouse into position:

⛶ Freeze in 3.0s← drag to your bookmarks bar
…or paste in the console
(function () {
var ms = 3000;
var b = document.createElement("div");
b.style.cssText =
"position:fixed;z-index:2147483647;left:16px;bottom:16px;padding:8px 12px;" +
"font:600 13px ui-monospace,SFMono-Regular,monospace;color:#fff;" +
"background:#0a0a0a;border:1px solid #333;border-radius:8px;pointer-events:none";
document.body.appendChild(b);
var end = Date.now() + ms;
var id = setInterval(function () {
var left = end - Date.now();
if (left <= 0) {
clearInterval(id);
b.remove();
debugger;
return;
}
b.textContent = "freezing in " + (left / 1000).toFixed(1) + "s — hover now";
}, 80);
})();

The bookmarklet adds a tiny countdown badge so you know how long you've got, then freezes. Hit the button (or your bookmark) on any page, mouse over the hover-only element, and wait for the freeze.

Why it works

debugger; is a real JavaScript statement — when DevTools is open, it acts like a breakpoint at that line. Wrapping it in setTimeout buys you a window to move the mouse and trigger the transient state before execution pauses.

When the breakpoint hits, the whole event loop stops. Nothing re-renders, no mouseleave fires, no animation advances. The DOM is suspended exactly as it was, so :hover / :focus-within styles and any JS-driven open state stay put while you inspect.

Two things to know:

  • DevTools must be open for debugger; to break. No open DevTools, no pause.
  • To resume, hit the ▶ (resume) button in the Sources panel, or press F8.

When you don't need it

Chrome and Firefox both let you force element states directly:

  1. Select the element in the Elements panel.
  2. In the Styles pane, click :hov.
  3. Tick :hover, :focus, :active, etc.

That's cleaner for pure-CSS states. The debugger trick wins when the element only exists while hovering — JS-mounted tooltips, portals, menus that unmount on mouseleave — because forcing :hover can't bring back a node that isn't in the DOM yet. Freeze first, inspect second.

Takeaways

  • setTimeout(() => { debugger; }, 3000) freezes the page mid-interaction so hover-/focus-only UI stays on screen.
  • DevTools must be open; resume with F8.
  • For plain CSS states, the :hov toggle is tidier — reach for the freeze when the node disappears the instant you stop hovering.