I have an arrow as a SVG which's length I want to alter in response to the width of a wrapping DIV (for example).
All my previous attempts have led into this behavior (scaling the whole SVG):
Rather than this, I want to achieve this behavior:
Is it possible to just alter single shapes inside of a SVG by simply adding percentual values to the code? If not, how could I perform this?
SVG as code:
<svg width="35px" viewBox="0 0 35 985" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Group" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(0.000000, 0.000000)">
<rect id="Rectangle-2" fill="#5FDCC7" x="12" y="19.7987928" width="11" height="100%"></rect>
<polygon id="Triangle" fill="#5FDBC6" points="17.5 0 35 20.7887324 0 20.7887324"></polygon>
<rect id="Rectangle-3" fill="#5FDBC6" x="0" y="973.110664" width="35" height="11"></rect>
</g>
</svg>
As a general rule, there is no way to create a scalable SVG where parts of it don't scale. If an SVG has a viewBox, and you scale it, then all the contents will scale. There is no way to mark some of the contents as immune to the scaling.
The nearest you can get is to restrict scaling to the X axis. However the arrowhead will still stretch.
<svg width="35px" height="150px" viewBox="0 0 35 985" preserveAspectRatio="none">
<g id="Group" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(0.000000, 0.000000)">
<rect id="Rectangle-2" fill="#5FDCC7" x="12" y="19.7987928" width="11" height="100%"></rect>
<polygon id="Triangle" fill="#5FDBC6" points="17.5 0 35 20.7887324 0 20.7887324"></polygon>
<rect id="Rectangle-3" fill="#5FDBC6" x="0" y="973.110664" width="35" height="11"></rect>
</g>
</svg>
<svg width="35px" height="300px" viewBox="0 0 35 985" preserveAspectRatio="none">
<g id="Group" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(0.000000, 0.000000)">
<rect id="Rectangle-2" fill="#5FDCC7" x="12" y="19.7987928" width="11" height="100%"></rect>
<polygon id="Triangle" fill="#5FDBC6" points="17.5 0 35 20.7887324 0 20.7887324"></polygon>
<rect id="Rectangle-3" fill="#5FDBC6" x="0" y="973.110664" width="35" height="11"></rect>
</g>
</svg>
If you want a generalised solution, then you have to monitor resize events and update the SVG dynamically.
The limited sneaky clever solution...
Having said all that, there is a clever technique that works in a limited set of circumstances. The limitations are:
Here is a demo of your shape implemented using this technique. If you resize the window horizontally, you'll see it stretches appropriately.:
<svg width="100%" height="35px">
<svg viewBox="0 0 1 1" preserveAspectRatio="none">
<rect x="0" y="0" width="1" height="1" fill="white"/>
<rect x="0" y="0.4" width="1" height="0.2" fill="#5FDBC6"/>
</svg>
<svg viewBox="0 0 0.2 1" preserveAspectRatio="xMinYMid">
<rect x="0" y="0" width="0.2" height="1" fill="#5FDBC6"/>
</svg>
<svg viewBox="0 0 0.8 1" preserveAspectRatio="xMaxYMid">
<rect x="0" y="0" width="0.8" height="1" fill="white"/>
<polygon points="0,0 0.8,0.5 0,1" fill="#5FDBC6"/>
</svg>
</svg>
Yes, you can use percentages in svg.
for basic shapes its quite simple. You can write your main rect as
<rect x="0" y="5" width="100%" height="10"/>
your second rect is even simpler, as it sits at 0,0 all the time
<rect x="0" y="0" width="10" height="20"/>
but with the arrow there is a problem in pathes and polygon you can not use percentages. To work around this problem there is a two step solution.
first put the path in a symbol element:
<symbol id="arrow" viewBox="0 0 20 20" width="20" height="20">
<path d="M0,0L20 10L0 20z" />
</symbol>
now you can position this symbol like you would position a rect... easy...
<use xlink:href="#arrow" x="100%" y="0" width="20" height="20"/>
but now your arrow starts a 100% and is completely outside of your viewport. you could just set overflow: visible on your svg and be done with it, but that is not what we want... we want the arrow to end at 100%. But that easy as well, we know that the arrow is 20px wide. So just translate the use back 20px:
<use xlink:href="#arrow" x="100%" y="0" width="20" height="20" transform="translate(-20 0)"/>
using this approach, you can position any shape at any position base on percentages...
to warp it all up, your complete svg now looks like this:
<svg id="svg" height="20px" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="arrow" viewBox="0 0 20 20" width="20" height="20">
<path d="M0,0L20 10L0 20z" />
</symbol>
<g id="Group" fill="#5FDCC7">
<rect x="0" y="5" width="100%" height="10" transform="translate(-20 0)" />
<rect x="0" y="0" width="10" height="20" />
<use xlink:href="#arrow" width="20" height="20" x="100%" y="0" transform="translate(-20 0)" />
</g>
</svg>
and here is a snippet using this svg with 3 different widths:
svg:nth-of-type(1) {
width: 100px
}
svg:nth-of-type(2) {
width: 200px
}
svg:nth-of-type(3) {
width: 300px
}
<svg height="20px" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="arrow" viewBox="0 0 20 20" width="20" height="20">
<path d="M0,0L20 10L0 20z" />
</symbol>
<g id="Group" fill="#5FDCC7">
<rect x="0" y="5" width="100%" height="10" transform="translate(-20 0)" />
<rect x="0" y="0" width="10" height="20" />
<use xlink:href="#arrow" width="20" height="20" x="100%" y="0" transform="translate(-20 0)" />
</g>
</svg>
<br/>
<svg height="20px" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="arrow" viewBox="0 0 20 20" width="20" height="20">
<path d="M0,0L20 10L0 20z" />
</symbol>
<g id="Group" fill="#5FDCC7">
<rect x="0" y="5" width="100%" height="10" transform="translate(-20 0)" />
<rect x="0" y="0" width="10" height="20" />
<use xlink:href="#arrow" width="20" height="20" x="100%" y="0" transform="translate(-20 0)" />
</g>
</svg>
<br/>
<svg height="20px" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="arrow" viewBox="0 0 20 20" width="20" height="20">
<path d="M0,0L20 10L0 20z" />
</symbol>
<g id="Group" fill="#5FDCC7">
<rect x="0" y="5" width="100%" height="10" transform="translate(-20 0)" />
<rect x="0" y="0" width="10" height="20" />
<use xlink:href="#arrow" width="20" height="20" x="100%" y="0" transform="translate(-20 0)" />
</g>
</svg>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With