Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

html2canvas normally captures ::before and ::after by reading their computed styles and inserting supported generated content into its cloned document. If a pseudo-element is missing or looks different, render a controlled clone with onclone; for simple generated text, append a real replacement element in that clone. This leaves the live page unchanged.

Why pseudo-elements disappear in html2canvas

html2canvas does not take a native browser screenshot. It reconstructs the target from the DOM, CSS rules and computed styles. Its source asks the browser for getComputedStyle(node, ':before') and getComputedStyle(node, ':after'), then resolves supported content values and places them into the cloned node.

That process is deliberate, but it cannot reproduce every CSS feature. The project describes the result as a DOM-based reconstruction that may not be 100% accurate to the browser’s representation. A pseudo-element can therefore be visible in Chrome while being absent or visually different on the canvas.

Cases html2canvas intentionally skips

  • content: none, an empty value, or an otherwise unresolved value.
  • display: none on the pseudo-element.
  • CSS effects that html2canvas has not implemented.
  • Frames captured before fonts, images, animations or layout have settled.

Remember that content is required even when the pseudo-element is purely decorative. A rule such as .card::before { background: red; } without a nonempty content value may not be represented.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Sale
Philips 24 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 241V8LB
  • CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
  • WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
  • A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents

Recommended capture pattern: stabilize the clone

Start by selecting the element and pass an onclone callback. The callback runs after html2canvas has cloned the document but before it renders that copy, so animation and transition changes do not mutate the page the user is viewing.

const target = document.querySelector('#capture');

html2canvas(target, {
  backgroundColor: null,
  scale: window.devicePixelRatio,
  onclone: (clonedDocument) => {
    const clonedTarget = clonedDocument.querySelector('#capture');
    if (!clonedTarget) return;

    // Make the render frame deterministic without changing the live page.
    clonedTarget.querySelectorAll('*').forEach((el) => {
      el.style.animation = 'none';
      el.style.transition = 'none';
    });
  }
}).then((canvas) => {
  document.body.appendChild(canvas);
  const png = canvas.toDataURL('image/png');
});

Use backgroundColor: null when transparency is required; omit it or provide a color for an opaque background. A device-pixel-ratio scale generally produces sharper output, while increasing the canvas dimensions and memory required.

Fallback: materialize a missing pseudo-element

If the computed pseudo-style contains simple quoted text but html2canvas still misses it, create a real child only in the cloned document. The example below copies the most useful visual properties from ::before.

function unquoteCssContent(value) {
  if (!value || value === 'none' || value === 'normal') return '';
  const first = value[0];
  const last = value[value.length - 1];
  if ((first === '"' && last === '"') || (first === "'" && last === "'")) {
    return value.slice(1, -1);
  }
  return value;
}

const source = document.querySelector('.card');

html2canvas(source, {
  onclone: (doc) => {
    const clone = doc.querySelector('.card');
    if (!clone) return;

    const pseudo = getComputedStyle(source, '::before');
    const text = unquoteCssContent(pseudo.content);
    if (!text) return;

    const replacement = doc.createElement('span');
    replacement.textContent = text;
    replacement.setAttribute('aria-hidden', 'true');
    replacement.style.cssText = [
      `display: ${pseudo.display}`,
      `position: ${pseudo.position}`,
      `top: ${pseudo.top}`,
      `right: ${pseudo.right}`,
      `bottom: ${pseudo.bottom}`,
      `left: ${pseudo.left}`,
      `color: ${pseudo.color}`,
      `background: ${pseudo.background}`,
      `font: ${pseudo.font}`,
      `padding: ${pseudo.padding}`,
      `margin: ${pseudo.margin}`,
      `z-index: ${pseudo.zIndex}`
    ].join(';');
    clone.insertBefore(replacement, clone.firstChild);
  }
}).then((canvas) => {
  console.log(canvas.toDataURL('image/png'));
});

This handles a quoted string such as content: "New". It does not automatically resolve counters, attr(), an image combined with text, or complex generated layouts. For those, calculate the final value yourself and reproduce the required positioning and dimensions explicitly in the clone. Keep the replacement aria-hidden so it cannot create duplicate accessible content if the clone is ever inspected.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Philips 22 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 221V8LB
  • CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
  • SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors

Step-by-step checklist before changing your CSS

  1. Inspect the computed rule. In DevTools, check getComputedStyle(element, '::before').content and the corresponding ::after value. Confirm it is not empty, none, normal, or hidden by display: none.
  2. Capture the intended element. Verify the selector points at the component that owns the pseudo-element and record its width and height before rendering.
  3. Wait for assets. Load web fonts and images first. Font substitution changes text metrics, and an early capture can produce different wrapping or missing backgrounds.
  4. Freeze motion in onclone. Disable animations and transitions so the clone cannot be rendered between layout states.
  5. Check CSS support. html2canvas requires each CSS property to be implemented manually; full CSS support is not available. If the pseudo-element relies on an unsupported effect, use the materialized-child fallback or simplify the cloned styling.
  6. Handle external images. Set useCORS: true only when the image server sends suitable CORS headers. Otherwise configure a proxy. Cross-origin resources can be skipped or taint the canvas under browser security rules.
  7. Choose output scale deliberately. scale: window.devicePixelRatio improves sharpness, but very large, full-page or high-DPI captures consume more memory.

Common symptoms and fixes

The pseudo-element is visible in the page but absent in the canvas

First check computed content and display. If both are valid, inspect the properties that create the visual effect. A supported text string may still lose a filter, blend mode, mask, or other unsupported CSS. Recreate the visible result as a real child in onclone.

Text appears in the wrong place

Absolute positioning depends on the containing block and the clone’s dimensions. Copy the relevant position, inset, padding, margin, font and stacking values, and ensure the cloned parent retains the same position context. Capture only after layout has settled.

Icons or background images are missing

Wait for image loading and check CORS. A data URL or same-origin asset avoids many canvas security problems. For a remote asset, use useCORS: true with server headers or a proxy; the option cannot override a server that refuses cross-origin access.

The result changes between captures

Animations, transitions, delayed fonts and network-loaded content are likely causes. Disable motion in onclone, await the font and image promises in your application, and capture after the component reports that it is ready.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #3
Sale
Dell 24 Monitor - SE2426H - 23.8-inch FHD (1920x1080) 144Hz 1ms Display, in-Plane Switching (IPS) Technology, AMD FreeSync™, TÜV 3-Star 2X HDMI, Tilt
  • Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
  • Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
  • Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
  • In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
  • Ultra-thin bezels: Maximize your viewing experience with thin bezels.

The code works in a browser but fails in Node.js

html2canvas depends on browser APIs including window, document and computed styles. It is not a Node-only renderer. For server-side screenshots, use a real browser automation workflow such as Puppeteer or Playwright, where the browser itself paints the page.

When a native browser screenshot is the better choice

Use html2canvas when rendering can happen in the user’s browser and you need a canvas or data URL without sending page content to a server. It is convenient for previews, exports and client-side sharing, but its reconstruction model means pixel parity is not guaranteed.

Use browser automation when you need server-side execution, advanced CSS fidelity, cross-origin control, or a screenshot generated without a visible browser tab. A real browser paints pseudo-elements as part of its normal rendering pipeline rather than asking a JavaScript library to recreate them.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP or PDF, so you do not need to install html2canvas or manage a browser process. Before capture it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Only clean shots are billed. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits cost nothing, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info and capture_pdf for Claude, Cursor and other MCP clients.

Rank #4
Samsung 27" Essential S3 (S36GD) Series FHD 1800R Curved Computer Monitor
  • CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
  • SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
  • MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
  • KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
  • INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient

For API options and parameter details, see the ScreenshotNeo documentation. This cURL request captures a page as WebP:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Equivalent Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Equivalent Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Features include full-page lazy-image loading, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, PDF controls, custom CSS and JavaScript, pre-capture clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone and geolocation, transparent backgrounds, resizing, chosen-TTL caching, signed image links, asynchronous jobs with signed webhooks, bulk capture for 100 URLs per call, a usage API and an OpenAPI specification. Parameter names used by other screenshot APIs also work, which can simplify migration.

The Free plan includes 1,000 screenshots each month with no card. Paid plans start at $5 for 3,000 shots; yearly billing provides two months free, and every feature is available on every plan. Sign up free for ScreenshotNeo and start with the no-card allowance.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

FAQ

Does html2canvas support both pseudo-elements?

Yes. Its clone logic checks both ::before and ::after; failures usually involve empty content, hidden styles or unsupported CSS rather than the pseudo-element selector itself.

Best Value
Sale
Sceptre New 22-Inch Gaming Monitor, FHD 1080p, Up to 144Hz, HDMI, DisplayPort, Built-in Speakers, Machine Black (E225W-FW144 Series, 2026)
  • 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
  • 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
  • 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.

Can I modify the original page in the fallback?

You can, but it is unnecessary and risks visible flicker. Put the replacement in onclone so only the render copy changes.

Will a CSS counter always be converted to text?

No. The simple fallback above only unquotes a resolved string. Counters, attr() and compound generated content need an explicit resolved value and layout in the clone.

What format does toDataURL() produce?

With no argument it produces a PNG data URL. Pass an image MIME type such as image/jpeg when your export requirements allow it; transparency is then handled differently.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.