Skip to content

fix(svg): an element that is display: none is not drawn, nor anything in it - #483

Merged
sidorares merged 1 commit into
masterfrom
zg/svg-display-none
Sep 30, 2026
Merged

sidorares merged 1 commit into
masterfrom
zg/svg-display-none

Conversation

@sidorares

@sidorares sidorares commented Sep 30, 2026 •

Copy link
Copy Markdown
Owner

SVG 1.1 (11.5) leaves out an element whose display is none, and
everything in it: the property is not inherited, so a child that says
display="inline" is still in an element that is not rendered. SvgView
did not read display at all, and drew every element it was handed.

An editor exports a hidden layer that way. Illustrator writes each as
<g display="none"> around shapes it marks display="inline", so a file
with six layers and one showing was drawn as all six, one over another:
the CSS Zen Garden's 221 sets a star icon behind its heading, a white disc
with four orange strokes, and what was drawn was the disc under two
magenta squares and a stack of rings from the layers the file hides.

An element that is display: none, by its attribute or in its style,
which wins, is now left out of the drawing and of the paint scan, with all
it holds. The test draws a document of a layer that shows, hidden ones by
attribute and by style around shapes that say inline, and a hidden
shape, and scans one for its paints; it fails without either half.
docs/svg.md lists it.

… in it

SVG 1.1 (11.5) leaves out an element whose `display` is `none`, and
everything in it: the property is not inherited, so a child that says
`display="inline"` is still in an element that is not rendered. `SvgView`
did not read `display` at all, and drew every element it was handed.

An editor exports a hidden layer that way. Illustrator writes each as
`<g display="none">` around shapes it marks `display="inline"`, so a file
with six layers and one showing was drawn as all six, one over another:
the CSS Zen Garden's 221 sets a star icon behind its heading, a white disc
with four orange strokes, and what was drawn was the disc under two
magenta squares and a stack of rings from the layers the file hides.

An element that is `display: none`, by its attribute or in its `style`,
which wins, is now left out of the drawing and of the paint scan, with all
it holds. The test draws a document of a layer that shows, hidden ones by
attribute and by style around shapes that say `inline`, and a hidden
shape, and scans one for its paints; it fails without either half.
docs/svg.md lists it.
@sidorares

Copy link
Copy Markdown
Owner Author

Chrome, before and after, the icons under the header of the CSS Zen Garden's design 221, drawn by <Html> in react-x11-components with this svgview.js: the first is icon-star.svg, six Illustrator layers of which one shows.

Chrome, before, after

@sidorares
sidorares merged commit 3ece30b into master Sep 30, 2026
6 checks passed
@sidorares
sidorares deleted the zg/svg-display-none branch September 30, 2026 14:37
sidorares pushed a commit that referenced this pull request Sep 30, 2026
🤖 I have created a release *beep* *boop*
---


## [8.17.3](v8.17.2...v8.17.3)
(2026-09-30)


### Bug Fixes

* **deps:** fontkit comes from npm again, and a variable face in a WOFF
or a WOFF2 is read as the sfnt inside it
([#485](#485))
([b5d5320](b5d5320))
* **svg:** an element that is display: none is not drawn, nor anything
in it ([#483](#483))
([3ece30b](3ece30b))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
sidorares added a commit that referenced this pull request Sep 30, 2026
… and a nested svg is a viewport of its own (#487)

Three things a browser does with an inline `<svg>` that `SvgView` did
not, found by drawing the same page through react-x11-components'
`<Html>`
and through headless Chrome. The fourth that report listed, `display:
none`, landed in #483.

`visibility` was not read at all, so `visibility="hidden"` drew an
opaque
shape. It is now read by attribute and in `style`, which wins. It is
inherited, and hides only what an element paints itself: a group that is
hidden walks on, and a shape in it that says `visibility="visible"` is
drawn. `collapse` is `hidden`.

`opacity` was read from the attribute only, where `fill-opacity` and
`stroke-opacity` are read from `style` as well, so `style="opacity:.2"`
drew an opaque shape. All three now take a number or a percentage,
clamped to 0..1, and a declaration that cannot be read leaves the
attribute's value, as CSS drops an invalid declaration.

A nested `<svg>` was drawn as a group: at 0,0 of its parent whatever its
`x` and `y`, and unclipped. It is now a viewport, as SVG 2 has it in
8.2:
`width` by `height` at `x`,`y`, all of the viewport around it where they
are unset and percentages of that, its `viewBox` fitted in as
`preserveAspectRatio` says, and what it draws clipped to it unless its
`overflow` is `visible` or `auto`.

The paint scan behind `paintKind` now reads style through the same
function `_renderNode` does, rather than a copy of part of it, so a
hidden
shape adds no colour to it and the two cannot drift apart.

Sixteen documents, drawn by Chrome, by master and by this branch. 1 to 5
are the report's. 6 to 16 are visibility inheritance, style over
attribute, percentages, and nested viewports under each alignment,
slice,
none, overflow and nesting. This branch matches Chrome to within one
level in every channel, save 9 antialiased edge pixels of the stretched
circle in 11.

![Chrome, master and this
branch](https://github.com/user-attachments/assets/af11163b-0edd-468e-882d-b9f49c5e7ed2)

svgview.test.js draws each case into a recording context, and each new
test fails on master; smoke-canvas.test.js draws the report's five
documents on a real server and reads their pixels back. docs/svg.md
lists
what is read now, and lists as unsupported only the root's
`preserveAspectRatio` and a `symbol`'s `viewBox`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant