Skip to content

[Bug] viewBox-only SVG background images show cropped when the SVG text does not start with "<svg " #16128

Open

Description

@jawshooah

Prerequisites

  • I searched for any existing report about this bug to avoid opening a duplicate.
  • I can reproduce this bug in a new, unmodified web browser profile with Dark Reader installed as the only extension.
  • I understand I need to use the Broken Website Report template if this bug I am reporting occurs on a single website.

Bug Description

In Dynamic mode, Dark Reader shows some SVG background images too large, so the element shows only the top-left corner of the image, or empty space.

This occurs for an SVG that has a viewBox but no width or height, if the SVG text does not start with exactly <svg . Examples are an SVG that starts with an XML declaration (<?xml ...?>), a comment, or a newline.

getImageDetails() has special code for viewBox-only SVGs: it adds width and height from the viewBox and sets useViewBox = true. But this code runs only if svgText.startsWith('<svg '):

if (svgText.startsWith('<svg ')) {
const closingIndex = svgText.indexOf('>');
const svgOpening = svgText.slice(0, closingIndex + 1).toLocaleLowerCase();
if (svgOpening.includes('viewbox=') && !svgOpening.includes('width=') && !svgOpening.includes('height=')) {
useViewBox = true;

If the check fails, the image loads with the browser default size for an SVG with no intrinsic size. getFilteredImageURL() then makes the filtered copy at that size:

const size = useViewBox ? `viewBox="0 0 ${width} ${height}"` : `width="${width}" height="${height}"`;

The page sets no background-size, so the browser shows the copy at its own size, and a 16 × 16 element shows only one corner of it.

Website Address

https://gist.githack.com/jawshooah/dead965d168225bb76eb5876115cc190/raw/repro.html (Source: https://gist.github.com/jawshooah/dead965d168225bb76eb5876115cc190)

Steps To Reproduce

  1. Open the test page (link in Website Address). It shows the same 16 × 16 dark icon four times as a CSS background image. Only the start of the SVG text is different:
    • A: starts with <svg (control)
    • B: starts with <?xml version="1.0" encoding="UTF-8"?>
    • C: starts with a comment
    • D: starts with a newline
  2. Turn on Dark Reader in Dynamic mode.
  3. Compare the four icons.

Expected Behavior

All four icons show the same: the full, inverted icon in its 16 × 16 box.

Actual Behavior

  • A (control): the full, inverted icon shows in its 16 × 16 box.
  • B, C, and D: the 16 × 16 box is empty.

The boxes are probably empty, not cropped, because the icon is in the center of the larger filtered copy, and the top-left corner of the copy is transparent. On the internal app where I found the bug, a different icon showed one cropped corner.

For icon B, the computed style shows that Dark Reader replaced the image with a filtered blob: copy, and the page shows the copy at its own size:

(() => {
    const cs = getComputedStyle($0);
    return {bg: cs.backgroundImage.slice(0, 80), size: cs.backgroundSize, w: cs.width, h: cs.height};
})()
{
    "bg": "url(\"blob:https://gist.githack.com/975c5f4f-255e-4c97-9a73-fb37bc985cfe\")",
    "size": "auto",
    "w": "16px",
    "h": "16px"
}

Screenshots

Image Image

Operating System

macOS 26.7.1 (25G241)

Web Browser name and version

Island 155.1.102.25

Dark Reader version

4.9.133

Additional Context

I found this bug on an internal web app that I cannot share. Its icons are viewBox-only SVG files that start with an XML declaration. On that app, the filtered icon had a blob: URL and background-size: auto in a 16 × 16 element, and only one corner of the icon showed.

A possible fix is to find the root <svg tag after an optional prolog, for example with /<svg[\s>]/i, and not to require it at index 0. The code that adds the width and height would then also need to keep the text before the tag, or remove the prolog.

A related point: the check !svgOpening.includes('width=') also matches stroke-width= on the root <svg> element. Such an SVG also skips the viewBox code. I found this when I read the code, but I did not test it.

Related issues. I did not confirm that these have the same cause:

Workaround for users: a site fix with background-size: cover !important; background-position: center !important; for the affected elements.

Activity

  1. Myshor commented on Oct 23, 2026

    @Myshor
    Collaborator

    Hi @jawshooah,

    Thank you for the detailed analysis and the isolated repro case.

    This is indeed a bug in the Dynamic Theme core engine (src/inject/dynamic-theme/image.ts), where startsWith('<svg ') fails on XML prologs, comments, and leading whitespaces, as well as the false positive on stroke-width=.

    Since this requires changes in the core extension logic rather than site-specific CSS fixes, a PR addressing the SVG root tag matching and attribute parsing would be very welcome.

    cc @alexanderby for visibility on the core image parser.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions