Use a <video> element inside a preview container, start muted inline playback on pointer entry, and pause it on exit. Handle the play() Promise because autoplay may be refused, and keep a poster plus an explicit Play button for touch and keyboard users.
Basic hover preview
This pattern previews a clip while a pointer is over a tile and resets it when the pointer leaves. The poster remains visible while the first frame loads or if playback is blocked.
| # | Preview | Product | Price | |
|---|---|---|---|---|
| 1 |
|
HTML5 Pocket Reference: Quick, Comprehensive, Indispensable (Pocket Reference (O'Reilly)) | $11.37 | Buy on Amazon |
| 2 |
|
HTML5 and CSS3 All-in-One For Dummies | $28.49 | Buy on Amazon |
| 3 |
|
Html5: QuickStudy Laminated Reference Guide | $5.95 | Buy on Amazon |
| 4 |
|
HTML5 For Dummies Quick Reference | $5.67 | Buy on Amazon |
| 5 |
|
Beginning HTML5 and CSS3 For Dummies | $23.56 | Buy on Amazon |
<div class="video-preview" tabindex="0" aria-label="Preview video">
<video muted playsinline preload="metadata" poster="preview.jpg">
<source src="preview.mp4" type="video/mp4">
</video>
<button type="button" class="play-button">Play preview</button>
</div>
const preview = document.querySelector(".video-preview");
const video = preview.querySelector("video");
function startPreview() {
video.muted = true;
const playback = video.play();
if (playback) {
playback.catch(() => {
// Keep the poster and explicit play control available.
});
}
}
function stopPreview() {
video.pause();
video.currentTime = 0; // Remove this line to resume at the same point.
}
preview.addEventListener("pointerenter", startPreview);
preview.addEventListener("pointerleave", stopPreview);
preview.addEventListener("focusin", startPreview);
preview.addEventListener("focusout", stopPreview);
The pointerenter and pointerleave events cover a mouse or pen without firing repeatedly as the pointer moves between children. Focus events add a keyboard-oriented preview. This is an illustrative implementation pattern, not a guarantee that every browser will autoplay.
Make the control usable on every input
Keep an explicit Play button
A phone does not provide a hover state. The button must start playback on tap and remain usable with Enter or Space. Give the video native controls when users need seeking, volume, pause, or resume.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minute#1 Best Overall
const playButton = preview.querySelector(".play-button");
playButton.addEventListener("click", async () => {
video.muted = false; // A user gesture may permit sound.
try {
await video.play();
} catch (error) {
// Show a message or leave the poster in place.
console.warn("Playback could not start", error);
}
});
If the preview should always be silent, leave video.muted = true in the click handler and provide a separate, clearly labelled route to full playback with sound. Do not hide the only way to operate the media behind hover.
Prevent focus from stopping too early
When focus moves from the container to its button, a naïve focusout handler can pause the video even though focus remains inside the tile. Test the new focus target before stopping.
preview.addEventListener("focusout", (event) => {
if (!preview.contains(event.relatedTarget)) {
stopPreview();
}
});
Use a similar containment check if your component has links, menus, or other interactive descendants.
Autoplay rules and muted playback
Calling video.play() returns a Promise in modern browsers. The Promise can reject when an autoplay policy, permission, unsupported source, or loading problem prevents playback. Always catch the rejection and preserve a usable poster and control.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Muted or silent media is less likely to be blocked. MDN notes that autoplay blocking does not apply to video without an audio track or with muted audio (autoplay guide). Set the property before calling play(); the markup Boolean attribute is also important:
Rank #2
<video muted playsinline ...>
Boolean attributes do not work like strings: muted="false" still means that muted is present, so the element remains muted. playsinline asks the browser to keep playback in the element instead of switching to a full-screen presentation. Safari’s autoplay examples use it, but it is not a promise that every mobile browser will play automatically.
Choose loading and reset behavior
Preload choices
preload is a request, not a command, and autoplay can take precedence. MDN defines the values as follows (video reference):
| Setting | Request | Use it when |
|---|---|---|
metadata |
Fetch duration, dimensions, and other metadata. | You have a moderate number of tiles and want a quick start without asking for the whole file. |
none |
Do not preload the media. | There are many off-screen previews or bandwidth is more important than instant hover response. |
auto |
Allow the browser to download the whole file. | A small number of short clips justify the extra data. |
Start with posters and preload="metadata". For long lists, defer distant sources until a tile nears the viewport. Lazy loading can delay media work near the viewport, but exact timing depends on browser, network, and the asset.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Restart or resume
Use video.pause() on exit in either design. Add video.currentTime = 0 when every hover should begin at the beginning. Omit the reset when returning visitors should resume where they stopped. Resetting can require the media to be seekable; guard unusual sources if necessary:
function stopPreview() {
video.pause();
if (video.readyState >= 1) video.currentTime = 0;
}
Multiple preview tiles
Give each tile its own video and bind events with querySelectorAll. Stop a previous tile before starting a new one so several videos do not play simultaneously.
let activeVideo = null;
document.querySelectorAll(".video-preview").forEach((preview) => {
const video = preview.querySelector("video");
const start = () => {
if (activeVideo && activeVideo !== video) {
activeVideo.pause();
activeVideo.currentTime = 0;
}
activeVideo = video;
video.muted = true;
const request = video.play();
request?.catch(() => {});
};
const stop = () => {
video.pause();
video.currentTime = 0;
if (activeVideo === video) activeVideo = null;
};
preview.addEventListener("pointerenter", start);
preview.addEventListener("pointerleave", stop);
preview.addEventListener("focusin", start);
preview.addEventListener("focusout", (event) => {
if (!preview.contains(event.relatedTarget)) stop();
});
});
If your design allows several simultaneous previews, remove the active-video arbitration but consider CPU, decoding, and network usage.
Visual and semantic details
- Keep a meaningful
posterthat communicates what the clip contains. - Provide a text label or accessible name for the preview region.
- Do not rely on motion alone to convey status; show a visible Play/Pause state.
- Respect reduced-motion preferences if the preview is decorative or especially distracting.
- Keep full playback controls available somewhere; native controls include play, seek, volume, pause, and resume.
- Use a supported source and an appropriate MIME type. You can provide more than one
<source>format when browser coverage requires it.
Diagnose a preview that does not play
The Promise rejects immediately
Confirm that the video is muted before play(), that playsinline is present, and that the browser has not blocked autoplay. Leave the poster and button visible rather than retrying in a loop. A direct user click is more likely to permit playback.
Recommended Free Tools
Only a blank rectangle appears
Check the poster URL, source URL, server response, and MIME type. Listen for media events while debugging:
["loadedmetadata", "loadeddata", "canplay", "playing", "error"].forEach((name) => {
video.addEventListener(name, () => console.log(name, video.error));
});
loadedmetadata means basic metadata arrived; canplay indicates the browser estimates it can begin. An error event points to a source or decoding failure.
It works with a mouse but not on a phone
That is expected: touch has no hover state. Test the visible button with a tap, and test keyboard focus with Tab, Enter, and Space. Do not make touch users discover a hidden gesture.
Rank #4
- Used Book in Good Condition
It pauses when moving to a button
Use the relatedTarget containment check shown above. The pause should occur only when focus leaves the entire preview, not when it moves between descendants.
Many tiles consume too much data
Use posters, preload="metadata" or none, and defer sources for tiles outside the viewport. Consider assigning the source only after interaction:
const video = preview.querySelector("video");
video.dataset.src = "preview.mp4";
function loadOnDemand() {
if (!video.src) {
video.src = video.dataset.src;
video.load();
}
video.muted = true;
video.play().catch(() => {});
}
preview.addEventListener("pointerenter", loadOnDemand, { once: true });
On-demand loading reduces initial bandwidth but adds delay before the first moving frame. Choose based on tile count, clip size, and connection quality rather than assuming one setting is best.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Option: capture a page instead of running browser automation
Or skip the browser setup
If your goal is to capture a rendered page or document that contains the preview, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns PNG, JPEG, WebP, or PDF. Its cleaner removes cookie banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, with the result identified by X-Page-Verdict and X-Billed headers. The MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.
See the full parameter list in the ScreenshotNeo documentation. This cURL request captures the rendered page:
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minutecurl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
There is a free allowance of 1,000 screenshots each month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan. Create a free ScreenshotNeo account.
Best Value
Cost, reliability, and security considerations
- Short, compressed preview files reduce transfer and decode cost; posters should be optimized separately.
- Do not assume
preloadis enforced. Measure requests in browser developer tools on the browsers and networks you support. - Resetting every tile on exit can trigger extra seeks. If that is costly for your media, leave the playhead where it is or use a short preview asset.
- Serve media over HTTPS when the page is HTTPS, and configure range requests and caching on your media host for responsive seeking.
- Do not autoplay sound on pointer entry. It is surprising, inaccessible for many users, and more likely to be blocked.
Frequently Asked Questions
Can CSS alone play a video on hover?
No. CSS can style a hover state, but starting and stopping media requires JavaScript or a user-operated native control.
Should I use mouseenter instead of pointerenter?
Pointer events cover mouse and pen with one API. They still do not create a hover interaction on touch, so keep an explicit tap action.
Why does muted=”false” still mute the video?
muted is a Boolean HTML attribute. If it is present, including as muted=”false”, the video is muted; change the DOM property with JavaScript or remove the attribute.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Is autoplay guaranteed for muted previews?
No. Muted or silent media is less likely to be blocked, but browser, device, embedded-webview, and user settings differ. Catch play() failures and retain the fallback.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

