Home > Net >  Can you decide where will an svg stretch to preserve proportions of part of the image?
Can you decide where will an svg stretch to preserve proportions of part of the image?

Time:11-28

Suppose I want to make a single svg, which can be stretched to be any of these 2 boxes: enter image description here

I'm trying to use this SVG as am image background in HTML/CSS.

Notice how the bottom left corner has the same angle in both boxes, but the second one is just longer. I made this in illustrator, altering the nodes themselves. Is there any property that I can use if I make a custom SVG which will keep the bottom left corner intact while streching the other side of the file?

I achieved something similar with clip-path: polygon() and calc, which allows usage of both % and px units, which means the corner could be 30px inset, but the bottom right corner is at 100% 100%. The problem with this solution is that polygon does not allow curves, and I need to add some later.

CodePudding user response:

For the simple situation you are describing, the best solution is slicing a border image. The SVG is set via a data url here, but you can also use an external file. The image gets sliced into nine parts, the corners retaining their size, and the middle parts stretching the contained image as needed.

You say you later want to add curves. If these curves are within the middle slices that get stretched, they will distort. This solution depends on avoiding such a situation. If you can't, I am not aware of any way to solve this short of dynamically computing your path data in JS.

The div is resizable, drag the bottom right corner to move it around.

I freely admit that I find the interplay of border-width, border-image-width and the size of the image hard to understand. The values below are the result of playing around, accordingly.

div {
    width:300px;
    height:150px;
    position:relative;
    overflow: hidden;
    resize:both;
    background-color:#cef;
    background-clip: content-box;
    
    border-style: solid;
    border-width: 10px;
    border-image-source: url('data:image/svg xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"><path fill="none" stroke="black" stroke-width="2" d="M1,1V30L10,39H39V1Z" /></svg>');
    border-image-slice: 30%;
    border-image-width: 60px;
    border-image-repeat: stretch; 
}
<div>

CodePudding user response:

Here I created an SVG document that I place as a background:

<svg xmlns="http://www.w3.org/2000/svg">
  <style>
    svg {
      width: 100%;
      height: 100%;
    }
    path.tr {
      stroke: orange;
      transform: translate(calc(100% - 3px), 3px);
      stroke-width: 6px;
    }
    path.bl {
      stroke: orange;
      transform: translate(3px, calc(100% - 3px));
      stroke-width: 6px;
    }
  </style>
  <path  d="M -5000 0 H 0 V 5000" fill="none" />
  <path  d="M 0 -5000 V -40 C 0 -20 20 0 40 0 H 5000" fill="none" />
</svg>

As long as it has no viewBox and all values are added using CSS the image will scale up and down. I use a "sliding-doors" technique where the two paths are placed in top/right and bottom/left corners.

.box {
  min-height: 100px;
  padding: 10px;
  margin: 10px;
  background-size: contain;
  background-image: url('data:image/svg xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxzdHlsZT4KICAgIHN2ZyB7CiAgICAgIHdpZHRoOiAxMDAlOwogICAgICBoZWlnaHQ6IDEwMCU7CiAgICB9CiAgICBwYXRoLnRyIHsKICAgICAgc3Ryb2tlOiBvcmFuZ2U7CiAgICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlKGNhbGMoMTAwJSAtIDNweCksIDNweCk7CiAgICAgIHN0cm9rZS13aWR0aDogNnB4OwogICAgfQogICAgcGF0aC5ibCB7CiAgICAgIHN0cm9rZTogb3JhbmdlOwogICAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZSgzcHgsIGNhbGMoMTAwJSAtIDNweCkpOwogICAgICBzdHJva2Utd2lkdGg6IDZweDsKICAgIH0KICA8L3N0eWxlPgogIDxwYXRoIGNsYXNzPSJ0ciIgZD0iTSAtNTAwMCAwIEggMCBWIDUwMDAiIGZpbGw9Im5vbmUiIC8 CiAgPHBhdGggY2xhc3M9ImJsIiBkPSJNIDAgLTUwMDAgViAtNDAgQyAwIC0yMCAyMCAwIDQwIDAgSCA1MDAwIiBmaWxsPSJub25lIiAvPgo8L3N2Zz4K');
}

.small {
  width: 300px;
}

.large {
  width: 600px;
  height: 600px;
}
<div >
  <p>small</p>
  <p>small</p>
  <p>small</p>
</div>
<div >large</div>

  • Related