Home > Mobile >  Is it possible to change svg path height with css transform? (not scale, not whole svg, only one pat
Is it possible to change svg path height with css transform? (not scale, not whole svg, only one pat

Time:10-22

I'm trying to increase the height of an SVG path (the border) and I'm getting the problem that the border gets hidden, only grows to down direction (not up) and the rounded corners get stretched. If I do the scale with the whole SVG also the icon inside get stretched and I want a uniform grow for that icon. I think using a div for that box is not a solution either because I would like the whole composition get resized to fill the space responsively.

Any solution?

#box{
  position:absolute;
  left: 80px;
}
#t-shirt{
  position: absolute;
  left:0;
  top: 25%;
}
#t-shirt:hover {
  transform: scale(1,1.2);
}
#pants{
  position: absolute;
  left: 160px;
  top: 25%;
}
#pants:hover #pants-border{
  transform: scale(1,1.2);
}
<svg id="box" width="315" height="341" viewBox="0 0 315 341" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="10.5" y="9.5" width="304" height="331" rx="19.5" fill="#242420" stroke="#242420"/>
<rect x="0.5" y="0.5" width="304" height="331" rx="19.5" fill="#D9D9D9" stroke="#242420"/>
<circle cx="23" cy="20" r="6.5" fill="#C9C9C9" stroke="#242420"/>
<circle cx="47" cy="20" r="6.5" fill="#C9C9C9" stroke="#242420"/>
<circle cx="71" cy="20" r="6.5" fill="#C9C9C9" stroke="#242420"/>
</svg>

<svg id="t-shirt" width="147" height="147" viewBox="0 0 147 147" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path height="200" d="M19.3522 0.706462H126.757C137.178 0.706462 145.626 9.15414 145.626 19.5749V126.98C145.626 137.4 137.178 145.848 126.757 145.848H19.3522C8.93148 145.848 0.483806 137.4 0.483806 126.98V19.5749C0.483806 9.15414 8.93149 0.706462 19.3522 0.706462Z" fill="#EBEBEB" stroke="#242420" stroke-width="0.967611"/>
  <path d="M112.243 116.336H34.834L35.0547 113.12L35.2341 110.749L35.441 107.977L35.6066 105.579L35.8135 102.806L35.9928 100.408L36.1998 97.6353L36.3653 95.2648L41.1525 29.251H53.8172C53.9529 34.4014 56.0844 39.295 59.7577 42.8896C63.431 46.4841 68.3559 48.4956 73.4833 48.4956C78.6106 48.4956 83.5354 46.4841 87.2087 42.8896C90.882 39.295 93.0136 34.4014 93.1493 29.251H105.869L110.643 95.2648L110.822 97.6353L111.029 100.408L111.194 102.806L111.401 105.579L111.581 107.977L111.788 110.749L111.953 113.12L112.243 116.336Z" fill="#D9D9D9"/>
  <path d="M37.7369 29.251L13.5466 58.7078L34.2872 75.6963L37.7369 29.251Z" fill="#d9d9d9"/>
  <path d="M109.34 29.251L133.53 58.7078L112.776 75.6963L109.34 29.251Z" fill="#D9D9D9"/>
</svg>

<svg id="pants" width="148" height="147" viewBox="0 0 148 147" fill="none" xmlns="http://www.w3.org/2000/svg">
<path id="pants-border" d="M19.8137 0.706462H128.186C138.607 0.706462 147.055 9.15414 147.055 19.5749V126.98C147.055 137.4 138.607 145.848 128.186 145.848H19.8136C9.39288 145.848 0.945231 137.4 0.945231 126.98V19.5749C0.945231 9.15414 9.39291 0.706462 19.8137 0.706462Z" fill="#EBEBEB" stroke="#242420" stroke-width="0.967611"/>
<path d="M103.028 12.8018V19.575L74 19.5611V19.575H44.9717V12.8018H103.028Z" fill="#DADADA"/>
<path d="M94.3198 24.4131H103.028V33.1216C94.465 32.713 94.3198 24.4131 94.3198 24.4131Z" fill="#DADADA"/>
<path d="M103.028 38.4122V132.786H80.6181L74.021 45.4874L67.382 132.786H44.9717V38.4122C48.7254 37.779 57.6755 35.1361 57.6755 24.4131H71.5839C71.5839 31.7636 71.3738 38.1781 73.993 38.2607C76.6262 38.2607 76.4161 31.7636 76.4161 24.4131H90.3385C90.3245 35.1361 99.2746 37.779 103.028 38.4122Z" fill="#DADADA"/>
<path d="M44.9717 33.1216V24.4131H53.6802C53.6802 24.4131 53.5205 32.713 44.9717 33.1216Z" fill="#DADADA"/>
</svg>

CodePudding user response:

As suggested by @n-- you need to scale your elements separately on hover:

  • rectangle background
  • icon

To avoid distortions, you could use a <rect> element with rx ry attributes (for rounded borders) and change the height and y values on hover.

We can avoid clipping by applying a overflow:visible property to the svgs.

svg {
  overflow: visible;
}

svg * {
  transform-origin: center;
  transition: 0.3s;
}

#box {
  position: absolute;
  left: 80px;
}

#t-shirt {
  position: absolute;
  left: 0;
  top: 25%;
}

#pants {
  position: absolute;
  left: 160px;
  top: 25%;
}


/* scale rect by changing height */

#t-shirt:hover .rect-shirt {
  height: 180px;
  y: -14px;
}


/* scale icons */

svg:hover .g-icon {
  transform: scale(1.2);
}


/* scale rect by changing d */

#pants:hover .rect-pants {
  d: path("M0 4.8 a 19.5 19.5 0 0 1 19.5-19.5 h 107 a 19.5 19.5 0 0 1 19.5 19.5 v 140 a19.5 19.5 0 0 1-19.5 19.5 h -107 a19.5 19.5 0 0 1-19.5-19.5 z");
}
<svg id="box" width="315" height="341" viewBox="0 0 315 341" fill="none" xmlns="http://www.w3.org/2000/svg">
  <rect x="10.5" y="9.5" width="304" height="331" rx="19.5" fill="#242420" stroke="#242420" />
  <rect x="0.5" y="0.5" width="304" height="331" rx="19.5" fill="#D9D9D9" stroke="#242420" />
  <circle cx="23" cy="20" r="6.5" fill="#C9C9C9" stroke="#242420" />
  <circle cx="47" cy="20" r="6.5" fill="#C9C9C9" stroke="#242420" />
  <circle cx="71" cy="20" r="6.5" fill="#C9C9C9" stroke="#242420" />
</svg>

<svg id="t-shirt" width="147" height="147" viewBox="0 0 147 147" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect  x="0.5" y="0.5" width="146" height="146" rx="19.5" fill="#EBEBEB" stroke="#242420" stroke-width="1" ></rect>
  
  <g >
  <path d="M112.243 116.336H34.834L35.0547 113.12L35.2341 110.749L35.441 107.977L35.6066 105.579L35.8135 102.806L35.9928 100.408L36.1998 97.6353L36.3653 95.2648L41.1525 29.251H53.8172C53.9529 34.4014 56.0844 39.295 59.7577 42.8896C63.431 46.4841 68.3559 48.4956 73.4833 48.4956C78.6106 48.4956 83.5354 46.4841 87.2087 42.8896C90.882 39.295 93.0136 34.4014 93.1493 29.251H105.869L110.643 95.2648L110.822 97.6353L111.029 100.408L111.194 102.806L111.401 105.579L111.581 107.977L111.788 110.749L111.953 113.12L112.243 116.336Z" fill="#D9D9D9" />
  <path d="M37.7369 29.251L13.5466 58.7078L34.2872 75.6963L37.7369 29.251Z" fill="#d9d9d9" />
  <path d="M109.34 29.251L133.53 58.7078L112.776 75.6963L109.34 29.251Z" fill="#D9D9D9" />
    </g>
</svg>

<svg id="pants" width="148" height="147" viewBox="0 0 148 147" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path  fill="#EBEBEB" stroke="#242420" stroke-width="1" d="
M0 19.5
a19.5 19.5 0 0 1 19.5-19.5
h107
a19.5 19.5 0 0 1 19.5 19.5
v107a19.5 19.5 0 0 1-19.5 19.5
h-107
a19.5 19.5 0 0 1-19.5-19.5
z"/>
  
  <g >
  <path d="M103.028 12.8018V19.575L74 19.5611V19.575H44.9717V12.8018H103.028Z" fill="#DADADA" />
  <path d="M94.3198 24.4131H103.028V33.1216C94.465 32.713 94.3198 24.4131 94.3198 24.4131Z" fill="#DADADA" />
  <path d="M103.028 38.4122V132.786H80.6181L74.021 45.4874L67.382 132.786H44.9717V38.4122C48.7254 37.779 57.6755 35.1361 57.6755 24.4131H71.5839C71.5839 31.7636 71.3738 38.1781 73.993 38.2607C76.6262 38.2607 76.4161 31.7636 76.4161 24.4131H90.3385C90.3245 35.1361 99.2746 37.779 103.028 38.4122Z" fill="#DADADA" />
  <path d="M44.9717 33.1216V24.4131H53.6802C53.6802 24.4131 53.5205 32.713 44.9717 33.1216Z" fill="#DADADA" />
    </g>
</svg>

Alternative: transition the d (path data) attribute

The pants rectangle is drawn as a path using relative commands

M 0 19.5
a 19.5 19.5 0 0 1 19.5-19.5
h 107
a 19.5 19.5 0 0 1 19.5 19.5
v 107
a 19.5 19.5 0 0 1-19.5 19.5
h -107
a 19.5 19.5 0 0 1-19.5-19.5
z

The hovered d can be created by just changing the M y value and the v (vertical line to) like so

M 0 4.8 // rectangle's x/y position 
a 19.5 19.5 0 0 1 19.5-19.5 
h 107 
a 19.5 19.5 0 0 1 19.5 19.5 
v 140 // rectangle's height
a 19.5 19.5 0 0 1-19.5 19.5 
h -107 
a 19.5 19.5 0 0 1-19.5-19.5 
z

We can change the paths geometry using the css path() method:

/* scale rect by changing d */
#pants:hover .rect-pants{
  d:path("M0 4.8 a 19.5 19.5 0 0 1 19.5-19.5 h 107 a 19.5 19.5 0 0 1 19.5 19.5 v 140 a19.5 19.5 0 0 1-19.5 19.5 h -107 a19.5 19.5 0 0 1-19.5-19.5 z");
}

CodePudding user response:

If I understood the desired result, then this can be done by using a grouping element for certain paths, then apply a transform-origin with the center origin to it:

#box {
  position:absolute;
  left: 80px;
}
#t-shirt, #pants {
  position: absolute;
  left:0;
  top: 25%;
}
#pants{
  left: 160px;
}
#t-shirt:hover,
#pants:hover {
  transform: scale(1,1.2);
}
#t-shirt:hover g,
#pants:hover g {
  transform: scale(1.2,1.2);
  transform-origin: center;
}
<svg id="box" width="315" height="341" viewBox="0 0 315 341" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="10.5" y="9.5" width="304" height="331" rx="19.5" fill="#242420" stroke="#242420"/>
<rect x="0.5" y="0.5" width="304" height="331" rx="19.5" fill="#D9D9D9" stroke="#242420"/>
<circle cx="23" cy="20" r="6.5" fill="#C9C9C9" stroke="#242420"/>
<circle cx="47" cy="20" r="6.5" fill="#C9C9C9" stroke="#242420"/>
<circle cx="71" cy="20" r="6.5" fill="#C9C9C9" stroke="#242420"/>
</svg>

<svg id="t-shirt" width="147" height="147" viewBox="0 0 147 147" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path height="200" d="M19.3522 0.706462H126.757C137.178 0.706462 145.626 9.15414 145.626 19.5749V126.98C145.626 137.4 137.178 145.848 126.757 145.848H19.3522C8.93148 145.848 0.483806 137.4 0.483806 126.98V19.5749C0.483806 9.15414 8.93149 0.706462 19.3522 0.706462Z" fill="#EBEBEB" stroke="#242420" stroke-width="0.967611"/>
  <g>
    <path d="M112.243 116.336H34.834L35.0547 113.12L35.2341 110.749L35.441 107.977L35.6066 105.579L35.8135 102.806L35.9928 100.408L36.1998 97.6353L36.3653 95.2648L41.1525 29.251H53.8172C53.9529 34.4014 56.0844 39.295 59.7577 42.8896C63.431 46.4841 68.3559 48.4956 73.4833 48.4956C78.6106 48.4956 83.5354 46.4841 87.2087 42.8896C90.882 39.295 93.0136 34.4014 93.1493 29.251H105.869L110.643 95.2648L110.822 97.6353L111.029 100.408L111.194 102.806L111.401 105.579L111.581 107.977L111.788 110.749L111.953 113.12L112.243 116.336Z" fill="#D9D9D9"/>
    <path d="M37.7369 29.251L13.5466 58.7078L34.2872 75.6963L37.7369 29.251Z" fill="#d9d9d9"/>
    <path d="M109.34 29.251L133.53 58.7078L112.776 75.6963L109.34 29.251Z" fill="#D9D9D9"/>
  </g>
</svg>

<svg id="pants" width="148" height="147" viewBox="0 0 148 147" fill="none" xmlns="http://www.w3.org/2000/svg">
<path id="pants-border" d="M19.8137 0.706462H128.186C138.607 0.706462 147.055 9.15414 147.055 19.5749V126.98C147.055 137.4 138.607 145.848 128.186 145.848H19.8136C9.39288 145.848 0.945231 137.4 0.945231 126.98V19.5749C0.945231 9.15414 9.39291 0.706462 19.8137 0.706462Z" fill="#EBEBEB" stroke="#242420" stroke-width="0.967611"/>
  <g>
    <path d="M103.028 12.8018V19.575L74 19.5611V19.575H44.9717V12.8018H103.028Z" fill="#DADADA"/>
    <path d="M94.3198 24.4131H103.028V33.1216C94.465 32.713 94.3198 24.4131 94.3198 24.4131Z" fill="#DADADA"/>
    <path d="M103.028 38.4122V132.786H80.6181L74.021 45.4874L67.382 132.786H44.9717V38.4122C48.7254 37.779 57.6755 35.1361 57.6755 24.4131H71.5839C71.5839 31.7636 71.3738 38.1781 73.993 38.2607C76.6262 38.2607 76.4161 31.7636 76.4161 24.4131H90.3385C90.3245 35.1361 99.2746 37.779 103.028 38.4122Z" fill="#DADADA"/>
    <path d="M44.9717 33.1216V24.4131H53.6802C53.6802 24.4131 53.5205 32.713 44.9717 33.1216Z" fill="#DADADA"/>
  </g>
</svg>

CodePudding user response:

SVG patterns (and filters) don't work like CSS's background-repeat, so what you want to do is not possible using SVG. You can't have an implicitly sized viewBox and SVG element AND have fixed size pattern elements: pattern elements will be sized in viewBox units by default.

That said, there are hacky ways to get what you want to do if you're not doing something complex. For example, you can set background-repeat: repeat on the entire SVG element, and then use a filter to paint over the area outside your shape so it looks like its filled. But yeeesh...

CodePudding user response:

SVG images, in contrast, can be drawn at any pixel size, so they don’t need a clearly defined height or width. And they won’t always have a clearly defined aspect ratio. You’re going to need to explicitly provide this information (and more) if you want the SVG to scale to fit the dimensions you give it.

If you don’t, SVG won’t scale at all. The following example uses inline SVG, adjusting the dimensions of the element (dotted line), without ever altering the size of the drawn graphic

  • Related