Reputation: 53
I have a DIV utilizing a css background, animation, and clip-path. The svg won't scale responsively whether I'm using vh/vw or percent. It'll scale properly when you change the window's height, but not when you change the window's width. Can you help me figure out which SVG implementation to use to get it to scale 1:1 responsively? I'd like to accomplish this without js but I'm open to it.
HTML
.imageHero {
max-width: 100%;
max-height: 100%;
width: 65vh;
height: 65vh;
margin: 40px;
clip-path: url('#my-clip-path');
animation: clipRotateAnim 6s linear infinite;
position: relative;
overflow: hidden;
}
.imageHero::before {
content: "";
position: absolute;
top: -10%;
bottom: -10%;
left: -10%;
right: -10%;
background: var(--i) center;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
animation: inherit;
animation-direction: reverse;
}
@keyframes clipRotateAnim {
to {
transform: rotate(360deg);
}
}
.r0tate {
display: inline-block;
position: relative;
width: 100%;
padding-bottom: 100%;
vertical-align: middle;
overflow: hidden;
}
.svg-content {
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<center>
<div class="r0tate">
<div class="imageHero" style="--i:url(https://source.unsplash.com/600x600?summer)" width="100%" height="100%">
</div>
<svg class="svg-content" viewBox="0 0 616.8 599" preserveAspectRatio="xMinYMin meet" height="0" width="0">
<clipPath id="my-clip-path" clipPathUnits="objectBoundingBox"><path d="M0.5,0.768 L0.366,1 L0.366,0.732,0.134,0.866 L0.268,0.634 L0,0.634 L0.232,0.5,0,0.366 L0.268,0.366,0.134,0.134 L0.366,0.268 L0.366,0 L0.5,0.232,0.634,0 L0.634,0.268,0.866,0.134 L0.732,0.366 L1,0.366 L0.768,0.5 L1,0.634,0.732,0.634,0.866,0.866 L0.634,0.732 L0.634,1"></path></clipPath>
</svg>
</div>
</center>
fiddle here
Upvotes: 2
Views: 339
Reputation: 17165
Part of the problem are your width and max-width definitions.
Essentially you have to ensure your clipped image keeps its aspect ratio.
You might actually use the css aspect-ratio
property – but browser support is still not perfect. Thus we take the old-school aspect-ratio hack.
.imageHero::before {
content: "";
padding-bottom: 100%;
width: 100%;
display: block;
}
.imageHero {
max-width: 65vh;
margin: 0 auto;
clip-path: url('#my-clip-path');
animation: clipRotateAnim 6s linear infinite;
position: relative;
overflow: hidden;
}
/* force aspect ratio 1:1 */
.imageHero::before {
content: "";
padding-bottom: 100%;
width: 100%;
display: block;
}
/* image */
.imageHero::after {
content: "";
position: absolute;
top: -10%;
bottom: -10%;
left: -10%;
right: -10%;
background: var(--i) center;
background-size: cover;
animation: inherit;
animation-direction: reverse;
}
@keyframes clipRotateAnim {
to {
transform: rotate(360deg);
}
}
.imageHero-wrp {
position: relative;
overflow: hidden;
padding: 40px;
background: #eee;
}
.svg-content {
position: absolute;
top: 0;
left: 0;
width: 0;
height: 0;
}
<main>
<div class="imageHero-wrp">
<div class="imageHero" style="--i:url(https://source.unsplash.com/600x600?summer)" width="100%" height="100%">
</div>
<svg class="svg-content" viewBox="0 0 1 1">
<clipPath id="my-clip-path" clipPathUnits="objectBoundingBox">
<path
d="M0.5,0.768 L0.366,1 L0.366,0.732,0.134,0.866 L0.268,0.634 L0,0.634 L0.232,0.5,0,0.366 L0.268,0.366,0.134,0.134 L0.366,0.268 L0.366,0 L0.5,0.232,0.634,0 L0.634,0.268,0.866,0.134 L0.732,0.366 L1,0.366 L0.768,0.5 L1,0.634,0.732,0.634,0.866,0.866 L0.634,0.732 L0.634,1z">
</path>
</clipPath>
</svg>
</div>
</main>
As an alternative you might also animate the clip-path itself via <animateTransform>
.imageHero {
max-width: 65vh;
margin: 40px auto;
clip-path: url('#my-clip-path');
position: relative;
overflow: hidden;
}
/* force aspect ratio 1:1 */
.imageHero::before {
content: "";
padding-bottom: 100%;
width: 100%;
display: block;
}
/* image element */
.imageHero::after {
content: "";
position: absolute;
top: 0%;
bottom: 0%;
left: 0%;
right: 0%;
background: var(--i) center;
background-size: cover;
}
.r0tate {
position: relative;
width: 100%;
padding-bottom: 100%;
overflow: hidden;
}
.svg-content {
position: absolute;
top: 0;
left: 0;
width: 0;
height: 0;
}
<main>
<div class="r0tate">
<div class="imageHero" style="--i:url(https://source.unsplash.com/600x600?summer)" width="100%" height="100%">
</div>
<svg class="svg-content" viewBox="0 0 1 1" aria-hidden="true">
<clipPath id="my-clip-path" clipPathUnits="objectBoundingBox">
<path
d="M0.5 0.755l-0.127 0.22l0-0.254l-0.221 0.127l0.128-0.22l-0.255 0l0.22-0.128l-0.22-0.127l0.255 0l-0.128-0.22l0.221 0.127l0-0.255l0.127 0.221l0.127-0.221l0 0.255l0.221-0.127l-0.128 0.22l0.255 0l-0.22 0.127l0.22 0.128l-0.255 0l0.128 0.22l-0.221-0.127l0 0.254z">
<animateTransform attributeName="transform"
type="rotate"
from="0 0.5 0.5"
to="360 0.5 0.5"
dur="6s"
repeatCount="indefinite"/>
</path>
</clipPath>
</svg>
</div>
</main>
This might actually be more performant since you're just rotating the the clip-path and not both image and parent element.
Upvotes: 3
Reputation: 159
I've prepared a solution, if that's what you mean. .imageHero{position: absolute;}
That's all I've set it to, plus r0tate{display: flex; justify-content: center;}
if you want to center it.
.imageHero {
max-width: 60%;
max-height: 60%;
width: 65vh;
height: 65vh;
margin: 40px;
clip-path: url("#my-clip-path");
animation: clipRotateAnim 6s linear infinite;
position: absolute;
overflow: hidden;
}
.imageHero::before {
content: "";
position: absolute;
top: -10%;
bottom: -10%;
left: -10%;
right: -10%;
background: var(--i) center;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
animation: inherit;
animation-direction: reverse;
}
@keyframes clipRotateAnim {
to {
transform: rotate(360deg);
}
}
.r0tate {
display: flex;
justify-content: center;
position: relative;
width: 100%;
padding-bottom: 100%;
vertical-align: middle;
overflow: hidden;
}
.svg-content {
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="style.css" />
<title>Document</title>
</head>
<body>
<center>
<div class="r0tate">
<div
class="imageHero"
style="--i: url(https://source.unsplash.com/600x600?summer)"
width="100%"
height="100%"
></div>
<svg
class="svg-content"
viewBox="0 0 616.8 599"
preserveAspectRatio="xMinYMin meet"
height="0"
width="0"
>
<clipPath id="my-clip-path" clipPathUnits="objectBoundingBox">
<path
d="M0.5,0.768 L0.366,1 L0.366,0.732,0.134,0.866 L0.268,0.634 L0,0.634 L0.232,0.5,0,0.366 L0.268,0.366,0.134,0.134 L0.366,0.268 L0.366,0 L0.5,0.232,0.634,0 L0.634,0.268,0.866,0.134 L0.732,0.366 L1,0.366 L0.768,0.5 L1,0.634,0.732,0.634,0.866,0.866 L0.634,0.732 L0.634,1"
></path>
</clipPath>
</svg>
</div>
</center>
</body>
</html>
jsfiddle: https://jsfiddle.net/rmcnt9a1/
Upvotes: 1