I'm using an svg file produced by graphviz. My goal is to add checkboxes at the top in a foreignObject
to toggle the visibility of certain elements. This is a minimal example where unchecking the checkbox should make the cluster
element disappear.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xhtml="http://www.w3.org/1999/xhtml" width="1000pt" height="1000pt" viewBox="0.00 0.00 1000.00 1000.00">
<g id="graph0" class="graph">
<title>test_config</title>
<polygon fill="white" stroke="none" points="0,1000 0,0 1000,0 1000,1000 0,1000"/>
<g id="clust1" class="cluster">
<title>cluster_icon_1</title>
<g id="a_clust1"><a xlink:title="icon 2025-03-01T00:00:00 -- 2025-05-01T00:00:00">
<polygon fill="#f6f5f4" stroke="none" points="100,900 100,100 900,100 900,900 100,900"/>
<text text-anchor="middle" x="500" y="150" font-family="Fira Sans" font-size="16.00">cluster title</text>
<text text-anchor="middle" x="500" y="200" font-family="Fira Sans" font-size="16.00">2025-03-01T00:00:00 -- 2025-05-01T00:00:00</text>
</a>
</g>
</g>
</g>
<foreignObject x="0" y="0" width="100%" height="100%">
<xhtml:input class="toggleCbx" type="checkbox" id="clusterCbx" name="clusters" value="clusters" checked="true"></xhtml:input>
<xhtml:label class="toggleLabel" for="clusterCbx">Clusters</xhtml:label>
</foreignObject>
<style>
.toggleCbx{ width: 20px; height: 20px; }
.toggleLabel{ font-size: 20px; font-family: "Fira Sans";}
.cluster{ display: block; }
#clusterCbx:not(:checked) ~ .cluster{ display: none;}
#clusterCbx:not(:checked) ~ .toggleLabel{ display: none;}
</style>
</svg>
Unfortunately, it has no influence on the rendered cluster
element but, interestingly, the last part of the conditional css works: the "Clusters" label of the checkbox disappears when the box is checked. So I'm probably incorrectly referencing the cluster
class in the style
part.
https://developer.mozilla.org/en-US/docs/Web/CSS/Subsequent-sibling_combinator:
The subsequent-sibling combinator (
~
, a tilde) separates two selectors and matches all instances of the second element that follow the first element (not necessarily immediately) and share the same parent element.
Neither of those conditions is fulfilled here for #clusterCbx:not(:checked) ~ .cluster
. And the second one can hardly be fulfilled, since you need to wrap the checkbox into foreignObject
- so you will have to use a solution that utilizes :has()
instead.
:has()
basically allows you to select elements, based on what elements they contain, or have following them. You should be able to either go via the root element,
:root:has(#clusterCbx:not(:checked)) .cluster{ display: none; }
or if that doesn't work,
#graph0:has(~ foreignObject #clusterCbx:not(:checked)) .cluster{ display: none; }
- select the #graph0
element if it has a following foreignObject
sibling that contains the unchecked #clusterCbx
, and then the .cluster element
inside of that.