1

The following code shows an SVG whose height depends on the height of another element:

https://codepen.io/HermanBovens/pen/aLjBGE

HTML

<div class="root">
  <div >
    <div>This</div>
    <div>content</div>
    <div>determines</div>
    <div>the</div>
    <div>height</div>
    <div>of</div>
    <div>the</div>
    <div>SVG</div>
  </div>
  <svg width="50px" viewBox="0 0 20 20" preserveAspectRatio = "none slice">
    <!-- I want do draw a down arrow here that spans the whole height, but only the length of the line should be variable, the arrow should not scale -->
    <line x1="10" y1="0" x2="10" y2="20" stroke="black" stroke-width="2"/>
    <line x1="0" y1="15" x2="10" y2="20" stroke="black" stroke-width="1"/>
    <line x1="20" y1="15" x2="10" y2="20" stroke="black" stroke-width="1"/>
  </svg>
</div>

CSS

.root {
  display: flex;
  align-items: stretch;
}


svg {
  background: lightblue;
}

How can the code be adapted so that the line of the arrow gets longer as the content on the left gets longer, but without the head being stretched?

herman
  • 11,740
  • 5
  • 47
  • 58
  • You can do this with CSS only. Why you need SVG for this? – Mohammad Usman Oct 12 '17 at 13:34
  • @MohammadUsman In this example it's an arrow which I guess can be accomplished without SVG somehow, but in reality the shape can be more complex. – herman Oct 12 '17 at 13:36
  • You mean that line will be there always with `lightblue` background but arrow can be replaced with some other shape? – Mohammad Usman Oct 12 '17 at 13:40
  • @MohammadUsman yes, or the line may be a dashed line instead (and the dashes should not stretch either) – herman Oct 12 '17 at 13:48
  • Does this [Fiddle](https://jsfiddle.net/wm9qgtsa/) fits your needs? – Mohammad Usman Oct 12 '17 at 14:00
  • @MohammadUsman I guess these are useful tricks, but was hoping there would be a way to just let the height of the SVG be dynamic and specify coordinates relative to the bottom, or something like that. I think instead of trying to draw using CSS I'd rather measure the DOM element and calculate the coordinates in javascript. – herman Oct 12 '17 at 14:14
  • 1
    See answers here: https://stackoverflow.com/questions/41258693/resizing-single-shapes-dynamically-without-scaling-the-whole-svg/41278867#41278867 – Holger Will Oct 12 '17 at 14:18
  • @HolgerWill that answer might fix the issue for the arrow head that shouldn't scale. But for that purpose, I think I'd rather just overlay two SVGs inside a container div and position the arrowhead SVG at the bottom, since that's simpler. – herman Oct 12 '17 at 14:53

2 Answers2

2

You can use the SVG <use> trick.

You define an arrowhead that is positioned with its point at y=0. Then reference it with a <use> width y="100%" so it gets repositioned at the maximum Y (bottom) of the SVG.

.root {
  display: flex;
}


svg {
  background: lightblue;
}
<div class="root">
  <div >
    <div>This</div>
    <div>content</div>
    <div>determines</div>
    <div>the</div>
    <div>height</div>
    <div>of</div>
    <div>the</div>
    <div>SVG</div>
    <div>SVG</div>
    <div>SVG</div>
    <div>SVG</div>
    <div>SVG</div>
  </div>
  <svg width="50px">
    <defs>
      <polyline id="arrow-head"
                points="3,-15, 25,-2.5 47,-15"
                fill="none" stroke="black" stroke-width="5"/>
    </defs>
    <line x1="50%" y1="0" x2="50%" y2="100%"
          stroke="black" stroke-width="5" stroke-dasharray="10 5"/>
    <use y="100%" xlink:href="#arrow-head"/>
  </svg>
</div>
Paul LeBeau
  • 97,474
  • 9
  • 154
  • 181
0

I guess the simplest way, following the principle of least surprise, would be to put the vertical line and the arrow head in separate SVG elements and overlay them.

To allow usage of a dashed stroke without scaling the dashes, I can use

vector-effect="non-scaling-stroke"

on the <line/> element.

Keeping the question open for potentially better suggestions.

herman
  • 11,740
  • 5
  • 47
  • 58