In a nutshell:
In this simplified example, I don't understand why my third cross is smaller than the others, I would have expected all cross to be the same
<svg width="512" height="128" xmlns="http://www.w3.org/2000/svg">
<!-- My baseline: no viewbox, and I use percentages -->
<svg x="0%" width="25%" height="100%">
<line x1="50%" y1="0" x2="50%" y2="100%" stroke="black" stroke-width="5%"/>
<line x1="0" y1="50%" x2="100%" y2="50%" stroke="black" stroke-width="5%"/>
</svg>
<!-- With a viewbox, to be able to not use percentages but still have something independant from my viewport -->
<svg x="25%" width="25%" height="100%" viewBox="0 0 100 100">
<line x1="50" y1="0" x2="50" y2="100" stroke="black" stroke-width="5"/>
<line x1="0" y1="50" x2="100" y2="50" stroke="black" stroke-width="5"/>
</svg>
<!-- with a viewbox one level below. Why is this cross smaller? -->
<svg x="50%" width="25%" height="100%">
<g viewBox="0 0 100 100">
<line x1="50" y1="0" x2="50" y2="100" stroke="black" stroke-width="5"/>
<line x1="0" y1="50" x2="100" y2="50" stroke="black" stroke-width="5"/>
</g>
</svg>
<!-- with a viewbox inside a viewbox. The size is restored by I have no clue why... -->
<svg x="75%" width="25%" height="100%" viewBox="0 0 100 100">
<g viewBox="0 0 100 100">
<line x1="50" y1="0" x2="50" y2="100" stroke="black" stroke-width="5"/>
<line x1="0" y1="50" x2="100" y2="50" stroke="black" stroke-width="5"/>
</g>
</svg>
</svg>
More context
Why I expect all crosses to be the same:
viewBox
it should be the same (which is the case)viewBox
is defined one level below. But the viewport and the viewBox
are still the same so I don't expect any change (but I'm wrong)viewBox
directive, but I have no clue why.The full context of my question is that I'm trying to create a tilesheet. It contains an element with different rotations, so I define this elements in a <defs>
and then apply some transform
on it, in successive sub-svg. I define this element with a viewBox
because it's the only way I'm aware of, to be able to use a <path>
while still being independent of the viewPort. But I've noticed this behavior where some of my tiles have an unexpected scale. (my example above has no <defs>
and no <path>
because I managed to get a simpler example than with my original svg)
That viewBox
on you <g>
Group element is ignored
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox
viewBox
is only valid on elements:
For a tile game a native Web Component with SVG only for one tile might be easier.
All positioning is done with HTML and CSS
<tiles style="display:grid;grid:repeat(3,1fr)/repeat(3,1fr);background:teal;width:240px">
<svg-tile></svg-tile> <svg-tile></svg-tile> <svg-tile></svg-tile>
<svg-tile></svg-tile> <svg-tile rotate=0></svg-tile> <svg-tile></svg-tile>
<svg-tile></svg-tile> <svg-tile></svg-tile> <svg-tile></svg-tile>
</tiles>
<script>
customElements.define("svg-tile", class extends HTMLElement {
constructor() {
const createElement = (tag, props = {}) => Object.assign(document.createElement(tag), props);
super().attachShadow({ mode: "open" })
.append(
createElement("style", {
innerHTML: `svg {display:inline-block;vertical-align:top}` +
`path {stroke:black}`
}),
this.rotation = createElement("style"), // set by rotate(x)
createElement("div", {
innerHTML: `<svg viewBox="0 0 6 6"><path d="M3 0v6M0 3h6"/></svg>`
})
);
}
connectedCallback() {
this.rotate = ~~(this.getAttribute("rotate") || 45);
this.onclick = (evt) => this.rotate = this._rotate + 45;
}
set rotate(value) {
this.rotation.innerHTML = `svg{transform:rotate(${this._rotate=value}deg)}`;
}
})
</script>