Repository navigation
[Bug] viewBox-only SVG background images show cropped when the SVG text does not start with "<svg " #16128
Description
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 '):
darkreader/src/inject/dynamic-theme/image.ts
Lines 49 to 53 in a59c051
| 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:
darkreader/src/inject/dynamic-theme/image.ts
Line 307 in a59c051
| 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
- 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
- A: starts with
- Turn on Dark Reader in Dynamic mode.
- 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
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:
- [Broken Website] mozillafoundation.org #14849: a logo disappeared in Dynamic mode, and
IGNORE IMAGE ANALYSISdid not help. TheuseViewBoxcode (f8a4743) came one day after this issue closed. - [Broken Website] www.mozilla.org, SVG background image is not handled correctly #11069: SVG background images without
widthorheightvanished or did not invert. The issue closed with "It works now". - [Bug] DR not invert SVG file stored in CSS code properly #9906 (open): an SVG background image showed incorrectly and was correct only with
background-size: contain.
Workaround for users: a site fix with background-size: cover !important; background-position: center !important; for the affected elements.
Activity
Myshor commentedon Oct 23, 2026
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), wherestartsWith('<svg ')fails on XML prologs, comments, and leading whitespaces, as well as the false positive onstroke-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.