jkjustjoshing
jkjustjoshing

Reputation: 3630

SVG scale by (100% - 60px)

I'm trying to build an SVG image with content that is 100% the width of the container, minus 60px for some text.

If I was using HTML, or SVG with javascript, I would have no problem doing this. But I feel like there should be a way to do this using SVG (and CSS if needed).

I want the equivalent of this (Codepen here):

<svg width="100%" height="100%">
  <rect fill="#ccc" x="0" y="0" width="100%" height="100%"></rect>

  <text x="100%" y="50%" stroke="black" text-anchor="end">Y-axis</text>

  <svg width="100%" height="100%">
    <!-- This rect represents the entirety of the contents of the graph -->
    <rect x="0" y="0" style="width: calc(100% - 60px)" height="100%" fill="#c88"></rect>
  </svg>
</svg>

In the above snippet, the inner <rect> resizes to be 100% - 60px the width of the container element. However, this trick only works for a single element - if you replace that <rect> with a complex SVG structure it no longer works.

enter image description here

Things I've tried:

  1. Doing a transform: scale() via CSS on the <rect> - I can't figure out what to put into the scale() to make it behave like 100% - 60px.
  2. Changing the width of the nested <svg> element
    • <svg width="calc(100% - 60px)"> doesn't work - can't do calc() inside the width attribute
    • <svg width="100%" style="width: calc(100% - 60px);"> (with or without the width attribute) - doesn't work - the CSS "width" property is ignored whether or not the width attribute is present.

I'm starting to think what I want to do isn't possible right now with SVG, but it doesn't seem like an uncommon use case. Is there any way to do this?

Upvotes: 0

Views: 1132

Answers (1)

chriskirknielsen
chriskirknielsen

Reputation: 2929

As discussed in the comments, you might have some luck achieving the same by making your graph area 100% of the viewBox, but place the SVG in a container with 60px of padding on the right to account for the text space.

Moving your text (and background rect) to x="100%" with its text-anchor="start", in addition to letting the SVG overflow, you can get a pretty close result without needing to transform your graphic, since you have a fixed 60px value you can consistently rely on:

div {
  padding-right: 60px;
}
svg {
  overflow: visible;
}
<div>
  <svg width="100%" height="100%">
    <rect fill="#ccc" x="100%" y="0" width="60px" height="100%"></rect>

    <text x="100%" y="50%" stroke="black" text-anchor="start">Y-axis</text>

    <rect x="0" y="0" width="100%" height="100%" fill="#c88"></rect>
  </svg>
</div>

PS: Maybe you would prefer your text to have text-anchor="middle", and transform it in CSS with transform: translateX(30px) to place it in the centre of the "text" area — might look cleaner that way:

div {
  padding-right: 60px;
}
svg {
  overflow: visible;
}
text {
  transform: translateX(30px);
}
<div>
  <svg width="100%" height="100%">
    <rect fill="#ccc" x="100%" y="0" width="60px" height="100%"></rect>

    <text x="100%" y="50%" stroke="black" text-anchor="middle">Y-axis</text>

    <rect x="0" y="0" width="100%" height="100%" fill="#c88"></rect>
  </svg>
</div>

Upvotes: 2

Related Questions