I'm trying to change the width
/height
of a <use>
element, which according to the spec and various docs should be possible as long as the element it inherits from does not have these properties set.
Unfortunately, it seems that a <use>
element will not display at all if it references a <rect>
which does not have width
and height
attributes set. Can anyone explain this?
If you instead inherit from an element which can not have a width
and height
and has its dimensions described in another way (e.g. a <circle>
, whose width and height are determined by its radius attribute r
) then the <use>
element will display, but its width
and height
attributes are then ignored. The radius value is used instead.
In any case, if I wrap a rect definition (with no width or height attributes) in a symbol
, and inherit that, again, the <use>
element (with width and height set) fails to appear.
Seems like width and height on <use>
elements don't really work according to SVG 1.1 spec. Apparently if you don't set a width and height on the referenced element, it defaults to auto (i.e. zero), and I suppose setting the width and height afterwards is just scaling something with zero dimensions or something?
Here's a small example which shows the problem (tested on Chrome, FF, Safari and Edge).
/*selects a rect def*/
#rc {
width:24px;
height:24px;
}
/*selects a use instance*/
#u4 {
width:80px;
height:80px;
}
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="320px" height="240px" viewBox="0 0 320 240">
<defs>
<rect id="ra" width="20" height="10"/> <!-- width and height set in def -->
<rect id="rb" /> <!-- width and height omitted in def -->
<rect id="rc" /> <!-- width and height omitted in def -->
<rect id="rd" /> <!-- width and height omitted in def -->
<!-- defs wrapped in symbols -->
<symbol id="re" viewBox="0 0 20 20"><rect /></symbol>
<symbol id="cdef" viewBox="0 0 20 20" preserveAspectRatio="none">
<circle r="10" cx="10" cy="10" />
</symbol>
</defs>
<!-- using a def which includes width/height attributes (works) -->
<use href="#ra" id="u1" x="10" y="10" fill="pink"/>
<!-- setting width/height on use element (fails to display anything, but should work according to spec) -->
<use href="#rb" id="u2" x="30" y="10" width="20" height="20" fill="cyan" />
<!-- setting width/height of def in css (works) -->
<use href="#rc" id="u3" x="50" y="10" fill="slategray"/>
<!-- setting width/height of use in css (does fail, according to spec)-->
<use href="#rd" id="u4" x="50" y="10" fill="orange"/>
<!-- setting width/height of use, inheriting from symbol rather than a rect directly-->
<use href="#re" id="u4" x="60" y="20" width="20" height="20" fill="lime"/>
<!-- inheriting from a circle (which has no width/height attributes) instead of a rect-->
<use href="#cdef" id="u5" x="120" y="20" width="40" height="40" fill="blue" />
<!-- finally a plain old rect (for comparison) -->
<rect id="r1" x="150" y="10" width="32" height="24" stroke="black" fill="white" />
</svg>
You'll notice that the orange element is not drawn, which is as expected: According to the spec, CSS rules can not be applied to <use>
elements, only to the elements they inherit from. This is ok.
But the cyan element is not drawn either, even though it has a width and height attribute set. The only way I can get it to appear is to add a width and height to the <def>
, which means the width and height attributes on the <use>
element will be ignored, and which defeats the object of the exercise entirely.
Maybe someone can explain how setting width
/height
on <use>
is supposed to work, or confirm that it is a bug (on all browsers!?)
Thanks for the comments. As I feared, it is apparently not possible.
Width and height attributes on <use>
elements which reference a rect are simply ignored because
The width and height attributes only have an effect if the referenced element defines a viewport
(source:https://www.w3.org/TR/SVG/struct.html#UseElement)
Update: A viable result with may be achieved by using CSS properties (also width and height) directly on elements without viewports. This will not distort stroke-width, rx, ry etc. and has excellent support across modern browsers at time of writing.