Animated div with SVG clip-path not responsive? - html
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
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>
Smil animated clip-path
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.
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/
Related
SVG fill transparent
I'm trying to use wave SVG and I have a background image at the body but I want the SVG to be filled with transparent so it shows the body background-image but when I try to make it fill: transparent or fill-opacity: 0 it just hides all the wave shapes. So is there is a way to replace #000000 with something transparent that shows body background-image? Here is an example code https://jsfiddle.net/nLt2vu4k/ * { margin: 0; padding: 0; } body { background-image: url("https://wallpaperaccess.com/full/5131560.jpg"); } header { min-height: 20rem; background-color: cyan; position: relative; } .shape { position: absolute; bottom: 0; left: 0; width: 100%; overflow: hidden; line-height: 0; transform: rotate(180deg); } .shape svg { position: relative; display: block; width: calc(128% + 1.3px); height: 163px; } .shape .shape-fill { fill: #000000; } <html> <body> <header> <div class="shape"> <svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 120" preserveAspectRatio="none"> <path d="M321.39,56.44c58-10.79,114.16-30.13,172-41.86,82.39-16.72,168.19-17.73,250.45-.39C823.78,31,906.67,72,985.66,92.83c70.05,18.48,146.53,26.09,214.34,3V0H0V27.35A600.21,600.21,0,0,0,321.39,56.44Z" class="shape-fill"></path> </svg> </div> </header> </body> </html> Thank you for helping, Best regards.
For transparent you can define "fill-opacity" to 0 in path: <html> <body> <header> <div class="shape"> <svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 120" preserveAspectRatio="none"> <path d="M321.39,56.44c58-10.79,114.16-30.13,172-41.86,82.39-16.72,168.19-17.73,250.45-.39C823.78,31,906.67,72,985.66,92.83c70.05,18.48,146.53,26.09,214.34,3V0H0V27.35A600.21,600.21,0,0,0,321.39,56.44Z" class="shape-fill" fill-opacity="0"></path> </svg> </div> </header> </body> </html>
You can use clipPath with your svg To have a nice result you might have to edit your SVG * { margin: 0; padding: 0; } body { background-image: url("https://wallpaperaccess.com/full/5131560.jpg"); } header { min-height: 20rem; background-color: cyan; position: relative; clip-path: url(#myClip); } .shape { position: absolute; bottom: 0; left: 0; width: 100%; overflow: hidden; line-height: 0; transform: rotate(180deg); } .shape svg { position: relative; display: block; width: calc(128% + 1.3px); height: 163px; } .shape .shape-fill { fill: #000000; } <html> <body> <header> <div class="shape"> <svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 120" preserveAspectRatio="none"> <clipPath id="myClip"> <path d="M321.39,56.44c58-10.79,114.16-30.13,172-41.86,82.39-16.72,168.19-17.73,250.45-.39C823.78,31,906.67,72,985.66,92.83c70.05,18.48,146.53,26.09,214.34,3V0H0V27.35A600.21,600.21,0,0,0,321.39,56.44Z" class="shape-fill"></path> </clipPath> </svg> </div> </header> </body> </html>
Try creating a new svg to cover the header background, and remove the header background-color. * { margin: 0; padding: 0; } body { background-image: url("https://wallpaperaccess.com/full/5131560.jpg"); } header { min-height: 20rem; position: relative; } .shape { position: absolute; top: 0; left: 0; width: 100%; overflow: hidden; line-height: 0; } .shape svg { position: relative; display: block; width: 100%; height: auto; } <header> <div class="shape"> <svg width="671" height="221" viewBox="0 0 671 221" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M0 0H671V195C375 304 282 14 0 195V0Z" fill="#0ff"/> </svg> </div> </header> https://jsfiddle.net/afelixj/7z1L5xdo/3/
fixed div wrapper on bottom right with a circlecss animation and text centered inside
I have a circle animation with a centered text inside. Everything is wrapped into a div. I'm trying to put this wrapper div on the bottom right of the page. Any tips about how to archive this without let centered text going outside the circle? here the code example https://codepen.io/D_s/pen/oNzQdJy thank you! html, body { height: 100%; background: lightgrey; } .wrapper { max-width: 50px; max-height: 50px; position: absolute; bottom: 0; right: 0; } .centered { position: absolute; color: white; font: 3vw/3vw times; height: 50px; text-align: center; } svg { animation: rotate 10s linear infinite; width: 25vw; height: 25vw; position: absolute; top: calc(50% - 15vw); left: calc(50% - 15vw); overflow: hidden; } .circle-text { font: 50px/50px times; letter-spacing: 22.5px; fill: white; } #keyframes rotate { to { transform: rotate(360deg); } } <div class="wrapper"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="10cm" height="10cm" viewBox="0 0 1000 1000" preserveAspectRatio="xMinYMin"> <defs> <path id="textPath" d="M 250 500 A 250,250 0 1 1 250 500.0001"/> </defs> <text class="circle-text" x="0" y="0" text-anchor="middle"><textPath xlink:href="#textPath" startOffset="50%" >SOLIDARITY 🌃 CHATBOT 🌈 </textPath></text> </svg> <h1 class="centered">centered</h1> </div>
update the code like below: .wrapper { position: fixed; bottom: 0; right: 0; overflow: hidden; } svg { animation: rotate 10s linear infinite; width: 25vw; height: 25vw; } .circle-text { font: 50px/50px times; letter-spacing: 22.5px; fill: white; } #keyframes rotate { to { transform: rotate(360deg); } } .centered { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: white; font: 3vw/3vw times; margin: 0; } body { background:grey; } <div class="wrapper"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="10cm" height="10cm" viewBox="0 0 1000 1000" preserveAspectRatio="xMinYMin"> <defs> <path id="textPath" d="M 250 500 A 250,250 0 1 1 250 500.0001"></path> </defs> <text class="circle-text" x="0" y="0" text-anchor="middle"><textPath xlink:href="#textPath" startOffset="50%">SOLIDARITY 🌃 CHATBOT 🌈 </textPath></text> </svg> <h1 class="centered">centered</h1> </div>
How to get this using css?
How can I draw this using css ? I tried using border css and rotate the DIV, but didn't find out exact answer for this.
You need to use clippath here is the example link Codepen html: <div class="tag-blue" style="-webkit-clip-path: url(#clip1);clip-path: url(#clip1);">gadgets 3</div> <svg width="0" height="0"> <defs> <clipPath id="clip1" clipPathUnits="objectBoundingBox"> <polygon points="0 0, 1 0, .82 1, 0 1"> </polygon> </clipPath> </defs> </svg> css: .tag-blue{ background-color: red; height: 300px; width: 300px; } change path according to your need
You could use pseudo elements, :before : after for this, and transform property: transform-origin: right bottom; transform: skewY(-3deg); transform-origin - set position of transform animation. and transform itself set which type and value of animation you want to have Here is code for your example: https://jsfiddle.net/2zbqgzcq/ And here you could read more about transform
div { height: 120px; width: 200px; background: blue; position: relative; } div:after { content: ""; position: absolute; background: blue; height: 90%; width: 100%; transform: skewY(-15deg); bottom: -25%; } <div></div>
You can achieve this by using transform property in css, try this <!DOCTYPE html> <html> <head> <style> .header{ background-color: #000; position: relative; height: 150px; width: 100%; } .header:after{ content: ''; transform-origin: right bottom; transform: skewY(-4deg); width: 100%; height: 100%; position: absolute; background: inherit; bottom: 0; } </style> </head> <body> <div class="header"></div> </body> </html>
how to cut out a shape from an html element
I've been searching for 2 days now, reading up on clip, clip-path, masking and everything there is to know about this css-subject. But I can't figure out how to achieve the following: I have a red body background color. on top of this is a full-width, full height div, that's white. (red body isn't showing). I want to cut out a shape out of the white div, to show a bit of red background. Does anyone know how this can be done? Much appreciated! Thanks Mario. fiddle: https://jsfiddle.net/ecaw94vw/ HTML <!DOCTYPE html> <html lang="en"> <head> </head> <body> <div class="container"> <!--<div class="svgMask" width="0" height="0"> <svg> <defs> <mask id="svgmask2"> <image width="100%" height="100%" xlink:href="assets/images/masks/triangle-1-mask.svg"/> </mask> </defs> <image mask="url(#svgmask2)" width="100%" height="100%" y="0" x="0" xlink:href="https://dl.dropboxusercontent.com/u/32494584/backdrop.jpg"/> </svg> </div>--> <div class="mask"> </div> </div> </body> </html> The css body{ background:red; } .mask{ position: absolute; left:0; right:0; top:0; bottom:0; background: white; -webkit-clip-path: polygon(100px 100px, 200px 0px, 500px 500px); } thanks
Okay, I think I've found a solution here that suits your needs! .clip-text { font-size: 6em; font-weight: bold; line-height: 1; position: relative; display: inline-block; margin: .25em; padding: .5em .75em; text-align: center; /* Color fallback */ color: #fff; -webkit-background-clip: text; -webkit-text-fill-color: transparent; } .clip-text:before, .clip-text:after { position: absolute; content: ''; } .clip-text:before { z-index: -2; top: 0; right: 0; bottom: 0; left: 0; background-image: inherit; } .clip-text:after { position: absolute; z-index: -1; top: .125em; right: .125em; bottom: .125em; left: .125em; background-color: #000; } .clip-text--no-textzone:before { background-position: -.65em 0; } .clip-text--no-textzone:after { content: none; } .clip-text--cover, .clip-text--cover:before { background-repeat: no-repeat; -webkit-background-size: cover; background-size: cover; } .clip-text_one { background-image: url(http://lorempixel.com/480/200/abstract/7); } <div class="clip-text clip-text_one">THIS IS CUT OUT</div>
Centered image over split color background in CSS
I've found how to make an image over color background but not when you have two of them. I'd like to center only one image in the middle of the screen/page and I want it to shrink with the window size. Image example: body { font-family: 'Titillium Web', sans-serif; } #top, #bottom { background: url('http://uxrepo.com/static/icon-sets/zocial/svg/chrome.svg') no-repeat center center; background-size: cover; position: absolute; left: 0; right: 0; height: 50%; } #top { top: 0; background-color: #ff0000; } #bottom { bottom: 0; background-color: #fff38f; } .header-container { height: 130px; width: 100%; margin: 0 auto; position: absolute; top: 130px; } .header { text-align: center; line-height: 16px; font-size: 48px; font-weight: 400; color: #ffffff; } .footer-container { height: 130px; width: 99%; margin: 0 auto; position: absolute; bottom: 0; } .footer { text-align: center; line-height: 16px; } .img { position: absolute; width: 100%; } <body> <div id="top"> <div class="header-container"> <div class="header"> SOME TITLE </div> </div> </div> <div id="bottom"> <div class="footer-container"> <div class="footer"> some text <br> <br>some text <br>some text <br>some text </div> </div> </div> </body> Does anyone know how to make this result simple?
CSS Gradient My approach, with a gradient background: JSFiddle <div class="background"> <img src="source"/> </div> .background{ background: linear-gradient(to bottom, #db6062 0%,#db6062 50%,#db6062 50%,#dae27a 50%,#dae27a 100%); position: absolute; top: 0; right: 0; bottom: 0; left: 0; } .background img{ position: absolute; top: 0; right: 0; bottom: 0; left: 0; height: 200px; width: 200px; margin: auto; }
Svg Since you are using an svg you can simply use that inline. And if you put it inline like i have done here in the example below. You can change all colors in the svg with css. svg { height: 100vh; } #rect1 { fill: firebrick; } #rect2 { fill: #229; } <div> <svg viewBox="0 0 500 400"> <rect id="rect1" x="0" y="0" width="1000" height="200" /> <rect id="rect2" x="0" y="200" width="1000" height="200" /> <g transform="translate(150,100) scale(0.2)"> <path d="M0 523q0-75 23-155.5t62-144.5q62-104 182.5-163.5t248.5-59.5q130 0 249.5 81.5t182.5 201.5q50 86 50 214 0 150-71 266t-192 177-270 60q20-36 61-109.5t73.5-130.5 64.5-108l1-2q3-5 12-18.5t12.5-19.5 9.5-17 9.5-21 5.5-21q6-24 6-48 0-80-48-142l275-81q-285 0-428 1-7-1-22-1-99 0-165.5 74t-55.5 173q-2-9-2-28 0-44 15-77l-204-201 198 341q19 72 79.5 117.5t134.5 45.5q17 0 33-3l-66 276q-115 0-223-71t-175-176q-66-102-66-230zm312-19q0 77 54.5 131.5t130.5 54.5 130.5-54.5 54.5-131.5q0-76-54-130.5t-131-54.5-131 54.5-54 130.5z" /> </g> </svg> </div>