Animating svg fill from bottom to top - css

I have a simple layout:
split screen, one section is white, the other is black.
centered logo, half black and half white
when you hover the black section, it gets filled from bottom to top with white
Now, what I try to do:
Fill the logo from bottom to top with black when I hover the section on the right.
Fill the logo from top to bottom with white when I hover the section on the left
I tried many things... but I always failed.
I think the easiest solution would be to have a rectangle with a linear gradient as a background-image, add a mask and then move the background-position.
Here is a snippet:
$( document ).ready(function() {
$(".split-half").hover(function(){
var elem = $(this);
$(".split-half").each(function(){
$(this).removeClass('active');
setTimeout(function(){
elem.addClass('active');
}, 400);
});
});
});
body *, *:after, *:before {
box-sizing: border-box;
margin:0;
padding:0;
}
html, body {
height: 100%;
}
.split-half {
display: block;
width: 50%;
height: 100%;
position: absolute;
z-index: 1;
padding: 5%;
}
.split-half:nth-child(1) {
background: #fff;
left: 0;
}
.split-half:nth-child(1):after {
content: '';
width: 100%;
height: 0;
position: absolute;
top: 0;
left: 0;
background: #000;
transition: height .3s;
}
.split-half:nth-child(1).active:hover:after {
height: 100%;
z-index: -1;
}
.split-half:nth-child(2) {
background: #000;
right: 0;
}
.split-half:nth-child(2):after {
content: '';
width: 100%;
height: 0;
position: absolute;
bottom: 0;
left: 0;
background: #fff;
transition: height .3s;
}
.split-half:nth-child(2).active:hover:after {
height: 100%;
z-index: -1;
}
.split-half:nth-child(2).active:hover + #logo #rect {
background-position: 0% 100%;
}
#logo {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-39.8%, -50%);
max-width: 420px;
min-width: 120px;
width: 10%;
height: auto;
z-index: 10;
}
#logo #rect {
background-image: linear-gradient(to bottom, white 0%, white 50%, black 50%, black 100%);
background-position: 0% 0%;
background-size: 100% 200%;
height: 100%;
width: 100%;
transition: all .3s;
mask: url(#mhSvg);
position: absolute;
top: 0;
right: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section>
<div class="split-half"></div>
<div class="split-half">
</div>
<div id="logo">
<svg width="100%" height="100%" viewBox="0 0 187 174" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
<defs>
<g id="hSvg">
<path d="M74.624,173.782l111.609,-55.886l-24.82,-12.41l-24.82,12.41l-24.82,-12.41l24.82,-12.41l-24.82,-12.41l-111.773,55.804l24.984,12.492l61.969,-31.066l24.82,12.41l-61.969,31.066" style="fill:#fff;"/>
</g>
<mask id="mhSvg" x="0" y="0" width="100%" height="100%">
<g id="hSvg">
<path d="M74.624,173.782l111.609,-55.886l-24.82,-12.41l-24.82,12.41l-24.82,-12.41l24.82,-12.41l-24.82,-12.41l-111.773,55.804l24.984,12.492l61.969,-31.066l24.82,12.41l-61.969,31.066" style="fill:#fff;"/>
</g>
</mask>
<g id="aSvg">
<path d="M0.082,0l74.542,37.271l0,136.511l-24.82,-12.41l0,-62.05l-24.902,-12.451l0,62.05l-24.82,-12.41l0,-136.511Zm24.902,62.091l0,-24.82l24.82,12.41l0,24.821l-24.82,-12.411Z"/>
</g>
</defs>
<g>
<use xlink:href="#hSvg" x="0" y="0" />
<use xlink:href="#aSvg" x="0" y="0" />
</g>
</svg>
<div id="rect">
</div>
</div>
</section>
For now, as you can see, I fail to position the mask.
Do you know how I can position the mask ?
Or do you think of a better method to achieve the effect ?
Thank you in advance !
Edit:
Well, I found a solution with masks... but it won't be a good solution as it's not cross browsers.
$( document ).ready(function() {
$(".split-half").hover(function(){
var elem = $(this);
$(".split-half").each(function(){
$(this).removeClass('active');
setTimeout(function(){
elem.addClass('active');
}, 400);
});
});
});
/* line 3, ../sass/style.scss */
body *, *:after, *:before {
box-sizing: border-box;
}
html, body {
height: 100%;
margin:0;
padding: 0;
}
.split-half {
display: block;
width: 50%;
height: 100%;
position: absolute;
z-index: 1;
padding: 5%;
}
.split-half:nth-child(1) {
background: #fff;
left: 0;
}
.split-half:nth-child(1):after {
content: '';
width: 100%;
height: 0;
position: absolute;
top: 0;
left: 0;
background: #000;
transition: height .3s;
}
.split-half:nth-child(1).active:hover:after {
height: 100%;
z-index: -1;
}
.split-half:nth-child(1).active:hover ~ #logo #A {
background-position: 0% 0%;
}
.split-half:nth-child(2) {
background: #000;
right: 0;
}
.split-half:nth-child(2):after {
content: '';
width: 100%;
height: 0;
position: absolute;
bottom: 0;
left: 0;
background: #fff;
transition: height .3s;
}
.split-half:nth-child(2).active:hover:after {
height: 100%;
z-index: -1;
}
/* line 58, ../sass/style.scss */
.split-half:nth-child(2).active:hover + #logo #H {
background-position: 0% 100%;
}
#logo {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-38.5%, -50%);
z-index: 10;
}
#logo #H {
background-image: linear-gradient(to bottom, white 0%, white 50%, black 50%, black 100%);
background-position: 0% 0%;
background-size: 100% 200%;
height: 100%;
width: 100%;
transition: all .3s;
mask: url(#mhSvg);
position: absolute;
top: 0;
right: 0;
}
#logo #A {
background-image: linear-gradient(to bottom, white 0%, white 50%, black 50%, black 100%);
background-position: 0% 100%;
background-size: 100% 200%;
height: 100%;
width: 100%;
transition: all .3s;
mask: url(#maSvg);
position: absolute;
top: 0;
right: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section>
<div class="split-half"></div>
<div class="split-half">
</div>
<div id="logo">
<svg width="194" height="181" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
<defs>
<g id="hSvg">
<path d="M74.624,173.782l111.609,-55.886l-24.82,-12.41l-24.82,12.41l-24.82,-12.41l24.82,-12.41l-24.82,-12.41l-111.773,55.804l24.984,12.492l61.969,-31.066l24.82,12.41l-61.969,31.066" style="fill:#fff;"/>
</g>
<mask id="mhSvg" x="0" y="0" width="120" height="114">
<g id="hSvg">
<path d="M74.624,173.782l111.609,-55.886l-24.82,-12.41l-24.82,12.41l-24.82,-12.41l24.82,-12.41l-24.82,-12.41l-111.773,55.804l24.984,12.492l61.969,-31.066l24.82,12.41l-61.969,31.066" style="fill:#fff;"/>
</g>
</mask>
<mask id="maSvg" x="0" y="0" width="120" height="114">
<g id="aSvg">
<path d="M0.082,0l74.542,37.271l0,136.511l-24.82,-12.41l0,-62.05l-24.902,-12.451l0,62.05l-24.82,-12.41l0,-136.511Zm24.902,62.091l0,-24.82l24.82,12.41l0,24.821l-24.82,-12.411Z" style="fill:#fff"/>
</g>
</mask>
</defs>
<g>
</svg>
<div id="H">
</div>
<div id="A">
</div>
</div>
</section>
I may have to dig at the suggestion made by #RobertLongson that is to say animate the stops of a linear-gradient.
Edit 2:
I tried animating the linear-gradient position, thanks to kute.js.
It works in firefox, chrome, but not in IE/Edge or on the website, they do have an exemple working on IE/Edge.
Here is my pen, I'm still wondering why it doesn't work.
https://codepen.io/AmauryH/pen/brBgKo

Here's one way to do it. I'm using an animated CSS linear-gradient for the split-half <div> elements. And using mix-blend-mode: difference to ensure the logo contrasts with the animated background.
This should work on all browsers except IE/Edge.
body *, *:after, *:before {
box-sizing: border-box;
margin:0;
padding:0;
}
html, body {
height: 100%;
}
.split-half {
display: block;
width: 50%;
height: 100%;
position: absolute;
z-index: 1;
padding: 5%;
}
.split-half:nth-child(1) {
background: linear-gradient(to top, #ffffff 50%,#000000 50%);
background-size: 100% 200%;
background-position: 0 100%;
left: 0;
transition: background-position 0.5s;
}
.split-half:nth-child(1):hover {
background-position: 0 0;
}
.split-half:nth-child(2) {
background: linear-gradient(to top, #ffffff 50%,#000000 50%);
background-size: 100% 200%;
right: 0;
transition: background-position 0.5s;
}
.split-half:nth-child(2):hover {
background-position: 0 100%;
}
#logo {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-39.8%, -50%);
max-width: 420px;
min-width: 120px;
width: 10%;
height: auto;
z-index: 10;
mix-blend-mode: difference;
}
<section>
<div class="split-half"></div>
<div class="split-half"></div>
<div id="logo">
<svg width="100%" height="100%" viewBox="0 0 187 174" style="fill-rule:evenodd;">
<defs>
<linearGradient x1="0" y1="100%" x2="0" y2="0">
<stop offset="0" stop-color="white"/>
<stop offset="0" stop-color="black"/>
</linearGradient>
</defs>
<g>
<path id="hSvg" d="M74.624,173.782l111.609,-55.886l-24.82,-12.41l-24.82,12.41l-24.82,-12.41l24.82,-12.41l-24.82,-12.41l-111.773,55.804l24.984,12.492l61.969,-31.066l24.82,12.41l-61.969,31.066" style="fill:#fff;"/>
<path id="aSvg" d="M0.082,0l74.542,37.271l0,136.511l-24.82,-12.41l0,-62.05l-24.902,-12.451l0,62.05l-24.82,-12.41l0,-136.511Zm24.902,62.091l0,-24.82l24.82,12.41l0,24.821l-24.82,-12.411Z" style="fill:#fff;"/>
</g>
</svg>
</div>
</section>

I've finally decided to start from a blank page and went for a different approach.
A container with a linear-gradient background (half white/half black) and the logo as a svg background-image
Two more containers inside with height 0. One with a black background, the other with a white background
In each a fullscreen span with the logo as a background image. (one logo full black, the other full white)
Then, I just have to animate the height of the containers from 0 to 100% to get the transition I wanted.
To get the white background to fill the screen from bottom to top, I had to use a simple trick... I've rotated the container with the background from a 180deg angle, and I've rotated it's children with the same angle.
Here is a snippet:
var vHeight = $(window).height();
var vWidth = $(window).width();
var screen1 = $('#screen1');
var currentMousePos = { x: -1, y: -1 };
$(document).mousemove(function(event) {
currentMousePos.x = event.pageX;
currentMousePos.y = event.pageY;
if ( currentMousePos.y <= vHeight ){
if ( currentMousePos.x >= ((vWidth / 2) + (vWidth / 10)) ) {
$('.svgb-wrapper').css('height', '0');
$('.svgw-wrapper').css('height', '100%');
}
else if ( currentMousePos.x <= ((vWidth / 2) - (vWidth / 10)) ) {
$('.svgb-wrapper').css('height', '100%');
$('.svgw-wrapper').css('height', '0');
}
else {
$('.svgb-wrapper').css('height', '0');
$('.svgw-wrapper').css('height', '0');
}
};
});
* {
margin:0; padding:0; border:0;
}
body *, *:after, *:before {
box-sizing: border-box;
}
html, body {
height: 100%;
background: #000;
color: #fff;
}
#screen1 {
height: 100%;
background: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB2aWV3Qm94PSIwIDAgMTg3IDE3NCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW\a 5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWw6c3BhY2U9InByZXNlcnZlIiBzdHlsZT0iZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7c3Ryb2tlLWxpbmVqb2lu\aOnJvdW5kO3N0cm9rZS1taXRlcmxpbWl0OjEuNDE0MjE7Ij48cmVjdCBpZD0iUGxhbi1kZS10cmF2YWlsMSIgeD0iMCIgeT0iMCIgd2lkdGg9IjE4Ni4zNjgiIGhlaWdodD0iMTczLjc4MiIgc3R5bG\aU9ImZpbGw6bm9uZTsiLz48Y2xpcFBhdGggaWQ9Il9jbGlwMSI+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjE4Ni4zNjgiIGhlaWdodD0iMTczLjc4MiIvPjwvY2xpcFBhdGg+PGcgY2xpcC1wYXRo\aPSJ1cmwoI19jbGlwMSkiPjxwYXRoIGlkPSJoU3ZnIiBkPSJNNzQuNjI0LDE3My43ODJsMTExLjYwOSwtNTUuODg2bC0yNC44MiwtMTIuNDFsLTI0LjgyLDEyLjQxbC0yNC44MiwtMTIuNDFsMjQuOD\aIsLTEyLjQxbC0yNC44MiwtMTIuNDFsLTExMS43NzMsNTUuODA0bDI0Ljk4NCwxMi40OTJsNjEuOTY5LC0zMS4wNjZsMjQuODIsMTIuNDFsLTYxLjk2OSwzMS4wNjYiIHN0eWxlPSJmaWxsOiNmZmY7\aIi8+PHBhdGggaWQ9ImFTdmciIGQ9Ik0wLjA4MiwwbDc0LjU0MiwzNy4yNzFsMCwxMzYuNTExbC0yNC44MiwtMTIuNDFsMCwtNjIuMDVsLTI0LjkwMiwtMTIuNDUxbDAsNjIuMDVsLTI0LjgyLC0xMi\a 40MWwwLC0xMzYuNTExbDAsMFptMjQuOTAyLDYyLjA5MWwwLC0yNC44MmwyNC44MiwxMi40MWwwLDI0LjgyMWwtMjQuODIsLTEyLjQxMWwwLDBaIi8+PC9nPjwvc3ZnPg==") no-repeat left 55% center, linear-gradient(to right, #ffffff 0%, #ffffff 50%, #000000 50%, #000000 100%);
background-size: 33%, cover;
}
#screen1 .svgw-wrapper {
height: 0;
width: 100%;
overflow: hidden;
position: absolute;
top: 0;
-moz-transition: all 0.6s;
-o-transition: all 0.6s;
-webkit-transition: all 0.6s;
transition: all 0.6s;
background: #000;
}
#screen1 .svgw-wrapper .svgw {
position: absolute;
top: 0;
display: block;
height: 100vh;
width: 100%;
background: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PCF\a ET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy\a 53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj48c3ZnIHdpZHRoPSIxMDAlI\aiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxODcgMTc0IiB2ZXJzaW9uPSIxLjEiIHhtbG5z\aPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzM\aub3JnLzE5OTkveGxpbmsiIHhtbDpzcGFjZT0icHJlc2VydmUiIHN0eWxlPSJmaWxsLXJ1bGU6ZX\aZlbm9kZDtjbGlwLXJ1bGU6ZXZlbm9kZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLW1pd\aGVybGltaXQ6MS40MTQyMTsiPjxyZWN0IGlkPSJQbGFuLWRlLXRyYXZhaWwxIiB4PSIwIiB5PSIw\aIiB3aWR0aD0iMTg2LjM2OCIgaGVpZ2h0PSIxNzMuNzgyIiBzdHlsZT0iZmlsbDpub25lOyIvPjx\ajbGlwUGF0aCBpZD0iX2NsaXAxIj48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTg2LjM2OCIgaG\aVpZ2h0PSIxNzMuNzgyIi8+PC9jbGlwUGF0aD48ZyBjbGlwLXBhdGg9InVybCgjX2NsaXAxKSI+P\aHBhdGggaWQ9ImhTdmciIGQ9Ik03NC42MjQsMTczLjc4MmwxMTEuNjA5LC01NS44ODZsLTI0Ljgy\aLC0xMi40MWwtMjQuODIsMTIuNDFsLTI0LjgyLC0xMi40MWwyNC44MiwtMTIuNDFsLTI0LjgyLC0\axMi40MWwtMTExLjc3Myw1NS44MDRsMjQuOTg0LDEyLjQ5Mmw2MS45NjksLTMxLjA2NmwyNC44Mi\awxMi40MWwtNjEuOTY5LDMxLjA2NiIgc3R5bGU9ImZpbGw6I2ZmZjsiLz48cGF0aCBpZD0iYVN2Z\ayIgZD0iTTAuMDgyLDBsNzQuNTQyLDM3LjI3MWwwLDEzNi41MTFsLTI0LjgyLC0xMi40MWwwLC02\aMi4wNWwtMjQuOTAyLC0xMi40NTFsMCw2Mi4wNWwtMjQuODIsLTEyLjQxbDAsLTEzNi41MTFsMCw\awWm0yNC45MDIsNjIuMDkxbDAsLTI0LjgybDI0LjgyLDEyLjQxbDAsMjQuODIxbC0yNC44MiwtMT\aIuNDExbDAsMFoiIHN0eWxlPSJmaWxsOiNmZmY7Ii8+PC9nPjwvc3ZnPg==") no-repeat left 55% center;
background-size: 33%;
}
#screen1 .svgb-wrapper {
height: 0;
width: 100%;
overflow: hidden;
position: absolute;
bottom: 0;
background: #fff;
-moz-transition: all 0.6s;
-o-transition: all 0.6s;
-webkit-transition: all 0.6s;
transition: all 0.6s;
-moz-transform: rotateX(180deg);
-ms-transform: rotateX(180deg);
-webkit-transform: rotateX(180deg);
transform: rotateX(180deg);
}
#screen1 .svgb-wrapper .svgb {
position: absolute;
top: 0;
display: block;
height: 100vh;
width: 100%;
background: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB2aWV3Qm94PSIwIDAgMTg3IDE3NCIgdmV\ayc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW\a 5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWw6c3BhY2U9InByZXNlcnZlIiBzd\aHlsZT0iZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7c3Ryb2tlLWxpbmVqb2lu\aOnJvdW5kO3N0cm9rZS1taXRlcmxpbWl0OjEuNDE0MjE7Ij48cmVjdCBpZD0iUGxhbi1kZS10cmF\a 2YWlsMSIgeD0iMCIgeT0iMCIgd2lkdGg9IjE4Ni4zNjgiIGhlaWdodD0iMTczLjc4MiIgc3R5bG\aU9ImZpbGw6bm9uZTsiLz48Y2xpcFBhdGggaWQ9Il9jbGlwMSI+PHJlY3QgeD0iMCIgeT0iMCIgd\a 2lkdGg9IjE4Ni4zNjgiIGhlaWdodD0iMTczLjc4MiIvPjwvY2xpcFBhdGg+PGcgY2xpcC1wYXRo\aPSJ1cmwoI19jbGlwMSkiPjxwYXRoIGlkPSJoU3ZnIiBkPSJNNzQuNjI0LDE3My43ODJsMTExLjY\awOSwtNTUuODg2bC0yNC44MiwtMTIuNDFsLTI0LjgyLDEyLjQxbC0yNC44MiwtMTIuNDFsMjQuOD\aIsLTEyLjQxbC0yNC44MiwtMTIuNDFsLTExMS43NzMsNTUuODA0bDI0Ljk4NCwxMi40OTJsNjEuO\aTY5LC0zMS4wNjZsMjQuODIsMTIuNDFsLTYxLjk2OSwzMS4wNjYiLz48cGF0aCBpZD0iYVN2ZyIg\aZD0iTTAuMDgyLDBsNzQuNTQyLDM3LjI3MWwwLDEzNi41MTFsLTI0LjgyLC0xMi40MWwwLC02Mi4\awNWwtMjQuOTAyLC0xMi40NTFsMCw2Mi4wNWwtMjQuODIsLTEyLjQxbDAsLTEzNi41MTFsMCwwWm\a 0yNC45MDIsNjIuMDkxbDAsLTI0LjgybDI0LjgyLDEyLjQxbDAsMjQuODIxbC0yNC44MiwtMTIuN\a DExbDAsMFoiLz48L2c+PC9zdmc+") no-repeat left 55% center;
background-size: 33%;
-moz-transform: rotateX(180deg);
-ms-transform: rotateX(180deg);
-webkit-transform: rotateX(180deg);
transform: rotateX(180deg);
}
#screen2 {
-moz-transition: all 0.6s;
-o-transition: all 0.6s;
-webkit-transition: all 0.6s;
transition: all 0.6s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js"></script>
<section id="screen1">
<div class="svgw-wrapper">
<span class="svgw"></span>
</div>
<div class="svgb-wrapper">
<span class="svgb"></span>
</div>
</section>
It's a cross browser solution.
The only problem is the background-position and the background-size that are not working as expected in IE, but I'll probably live with that !

Related

CSS animation rendering - staggering

I have created this CodePen for a rotating border around a button and although the principle seems to be good, it is not working as it should - the rendering seems extremely slow and staggering (I have the M1 MacBook Pro).
.button {
width: 206px;
height: 70px;
line-height: 70px;
text-align: center;
position: relative;
}
.button::after {
content: "";
border-radius: 35px;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
clip-path: url(#mask);
border: 3px solid black;
}
.curve-1 {
animation: ʕ•̫͡•ʕ•̫͡•ʔ•̫͡•ʔ 20s infinite linear;
transform-origin: 35px center;
//animation-play-state: paused;
//transform: rotate(-315deg)
}
.curve-2 {
animation: ʕ•̫͡•ʕ•̫͡•ʔ•̫͡•ʔ•̫͡•ʔ•̫͡•ʔ 20s infinite linear;
transform-origin: 35px center;
translate: 136px 0;
}
.line {
animation: ʕ•̫͡•ʕ•̫͡•ʔ•̫͡•ʔ•̫͡•ʔ•̫͡•ʕ•̫͡•ʔ 20s infinite linear;
}
svg {
display: block;
}
#keyframes ʕ•̫͡•ʕ•̫͡•ʔ•̫͡•ʔ {
0% {
transform: rotate(45deg);
}
22% {
transform: rotate(-135deg);
}
27% {
transform: rotate(-180deg);
}
88% {
transform: rotate(-180deg);
}
89% {
transform: rotate(-225deg);
}
100% {
transform: rotate(-315deg);
}
}
#keyframes ʕ•̫͡•ʕ•̫͡•ʔ•̫͡•ʔ•̫͡•ʔ•̫͡•ʔ {
0% {
transform: rotate(0deg);
}
38% {
transform: rotate(0deg)
}
39% {
transform: rotate(-45deg);
}
50% {
transform: rotate(-135deg);
}
72% {
transform: rotate(-360deg);
}
100% {
transform: rotate(-360deg);
}
}
#keyframes ʕ•̫͡•ʕ•̫͡•ʔ•̫͡•ʔ•̫͡•ʔ•̫͡•ʕ•̫͡•ʔ {
0%, 100% {
width: 0;
x: 35px;
y: 35px;
}
11% {
width: 0;
x: 35px;
y: 35px;
}
22% {
width: 55px;
x: 35px;
y: 35px;
}
39% {
width: 55px;
x: 116px;
y: 35px;
}
50% {
width: 0;
x: 171px;
y: 35px;
}
61% {
width: 0;
x: 171px;
y: 0;
}
72% {
width: 55px;
x: 116px;
y: 0;
}
89% {
width: 55px;
x: 35px;
y: 0;
}
100% {
width: 0;
x: 35px;
y: 0;
}
}
<div class="button">button text</div>
<svg view-box="0 0 206 70" width="206" height="70">
<defs>
<clipPath id="mask">
<path d="M10.2513 10.1652C3.73208 16.8036 0.103643 25.7716 0.165885 35.0968C0.228128 44.422 3.97596 53.3408 10.5832 59.8905L35.1651 34.8632L10.2513 10.1652Z" fill="#000" class="curve-1"/>
<path d="M10.2513 10.1652C3.73208 16.8036 0.103643 25.7716 0.165885 35.0968C0.228128 44.422 3.97596 53.3408 10.5832 59.8905L35.1651 34.8632L10.2513 10.1652Z" fill="#000" class="curve-2"/>
<rect fill="#000" height="35" class="line">
</clipPath>
</defs>
</svg>
<svg view-box="0 0 206 70" width="206" height="70">
<path d="M10.2513 10.1652C3.73208 16.8036 0.103643 25.7716 0.165885 35.0968C0.228128 44.422 3.97596 53.3408 10.5832 59.8905L35.1651 34.8632L10.2513 10.1652Z" fill="#000" class="curve-1"/>
<path d="M10.2513 10.1652C3.73208 16.8036 0.103643 25.7716 0.165885 35.0968C0.228128 44.422 3.97596 53.3408 10.5832 59.8905L35.1651 34.8632L10.2513 10.1652Z" fill="#000" class="curve-2"/>
<rect fill="#000" height="35" class="line">
</svg>
Does anybody know anything about CSS rendering and why could this be happening?
I also created this CodePen where I just wanted to demonstrate that animating a clip-path is possible and it seems to work just fine here...
.masked {
width: 500px;
clip-path: url(#mask)
}
.mask {
width: 500px;
}
.circle {
animation: ʕ•̫͡•ʕ•̫͡•ʔ•̫͡•ʔ 2s infinite;
}
#keyframes ʕ•̫͡•ʕ•̫͡•ʔ•̫͡•ʔ {
0% {
translate: 0;
}
50% {
translate: 40px;
}
100% {
translate: 100px;
}
}
<img src="https://images.unsplash.com/photo-1542273917363-3b1817f69a2d?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Nnx8dHJlZXxlbnwwfHwwfHw%3D&auto=format&fit=crop&w=900&q=60" class="masked"/>
<svg viewport="0 0 100 60">
<circle cx="50" cy="30" r="20" class="circle">
</svg>
<svg width="0" height="0">
<defs>
<clipPath id="mask">
<circle cx="100" cy="100" r="40" class="circle" />
</clipPath>
</defs>
</svg>
I have no idea why this's happening, if anyone knows the answer, I would be glad.
Thanks
Why so complicated? The same animation can be achieved with the stroke-dasharray technique.
For me, the animation appears smooth. Whether it is the same for you depends probably on hardware, but I am far down from your computing power.
.button {
width: 206px;
height: 70px;
line-height: 70px;
text-align: center;
position: relative;
border: 3px solid transparent;
}
.button .line {
position: absolute;
overflow: visible;
top: 0;
left: 0;
width: 100%;
height: 100%;
fill: none;
stroke: black;
stroke-width: 3px;
stroke-dasharray: 10px 90px;
animation: around 20s linear infinite;
}
#keyframes around {
0% {
stroke-dashoffset: 100px;
}
100% {
stroke-dashoffset: 0px;
}
}
<div class="button">button text<svg class="line" view-box="0 0 206 70">
<path d="M35,-1.5 A 36.5 36.5 0 0 0 35,71.5 H 171 A 36.5 36.5 0 0 0 171,-1.5 Z" pathLength="100" />
</svg>

How to improve an animated tv static effect using a pure css gradient

How would I be able to improve this animated static noise effect using a css gradient?
CSS only, no javascript, no svg, no image, using only a gradient, and adjusting that.
A tv no signal noise effect is what I am looking for using a css gradient.
Does anyone know how this effect can be improved, made better?
Is there a better way it can be written?
I am looking for something that is more accurate to a tv noise effect.
I think the way this effect is written can be improved.
Are there any tweaks or adjustments that can be made to it to so that it better depicts a tv noise effect?
The gradient can be anything, as long as it is a gradient, it doesn't matter what kind.
This one uses radial gradient:
https://jsfiddle.net/xhdkza5w/
html,
body {
width: 100%;
height: 100%;
display: flex;
}
.tv-static {
width: 500px;
height: 300px;
margin: auto;
background-image: repeating-radial-gradient(circle at 17% 32%, white, black 0.00085px);
animation: back 5s linear infinite;
}
#keyframes back {
from {
background-size: 100% 100%;
}
to {
background-size: 200% 200%;
}
}
<div class="tv-static"></div>
This one uses a conic-gradient: https://jsfiddle.net/bkx50apm/
html,
body {
width: 100%;
height: 100%;
display: flex;
}
.tv-static {
width: 500px;
height: 300px;
margin: auto;
background-image: repeating-conic-gradient(white, black 0.00085%);
animation: back 25s linear infinite;
}
#keyframes back {
from {
background-size: 100% 100%;
}
to {
background-size: 200% 200%;
}
}
<div class="tv-static"></div>
Do you mean this effect?
html,
body {
width: 100%;
height: 100%;
display: flex;
}
.animation {
width: 240px;
height: 240px;
margin: auto;
background-image: repeating-radial-gradient(circle at 17% 32%, white, black 0.00085px);
animation: animation 5s linear infinite;
}
#keyframes animation {
from {
background-position: 0px 0px;
}
to {
background-position: 240px 240px;
}
}
<div class="animation"></div>
Or this effect?
html,
body {
width: 100%;
height: 100%;
display: flex;
}
.animation {
width: 240px;
height: 240px;
margin: auto;
background-image: repeating-radial-gradient(circle at 17% 32%, white, black 0.00085px);
background-position: center;
animation: back 5s linear infinite;
}
#keyframes back {
from {
background-size: 100% 100%;
}
to {
background-size: 200% 200%;
}
}
<div class="animation"></div>
Edit: Added background-position: center.
By overlaying 2 of those effect on top of each other and each div has a different animation, you can create interference between the two that removes the artifacts of only having 1 static noise made from a single div.
This might be improved as I'm not well versed in css but the proof of concept works
html,
body {
width: 100%;
height: 100%;
display: flex;
}
.container_row {
display: flex;
}
.layer1 {
width: 100%;
background-color: rgba(255, 255, 255, 0.5);
}
.layer2 {
width: 100%;
margin-left: -100%;
background-color: rgba(255, 255, 255, 0.5);
}
.tv-static {
width: 500px;
height: 300px;
margin: auto;
background-image: repeating-radial-gradient(circle at 17% 32%, white, black 0.00085px);
}
.animation1 {
animation: back1 1s linear infinite;
}
.animation2 {
animation: back2 0.1s linear infinite;
}
#keyframes back1 {
from {
background-size: 100% 100%;
}
to {
background-size: 99% 100%;
}
}
#keyframes back2 {
from {
background-size: 48.56% 50%;
}
to {
background-size: 43.9% 50.1%;
}
}
<div class="layer1">
<div class="tv-static animation1"></div>
</div>
<div class="layer2">
<div class="tv-static animation2"></div>
</div>
With smooth timing function, animations don't give that effect we need to use step timing function to give those sudden change effect.
Solution 1: I've changed animation. And tweaked your gradient a little bit. I think using gradient is not a reliable solution because browsers do calculations differently and fractions, rounding change output. You are using radial gradient it looks things are going outwards from center of the placement. You'll have to test his on every platform and browser to see if it looks same.
Solution 2: Used SVG instead of gradient. The feTurbulence filter gives the noise effect. You can use svg as background-image.
Solution 3: Used image instead of gradient with same animation. Advantage of using image is that it'll look same across all browsers and screens.
Solution 3: Simply used noise gif image. No animation is required. :)
View following in 'full page' mode:
body {
text-align: center;
}
.tv {
width: 400px;
height: 200px;
border: 6px solid black;
margin: 0 auto;
overflow: hidden;
position: relative;
border-radius: 50% / 10%;
}
.tv-static {
position: absolute;
top: -200px;
left: -200px;
margin: auto;
height: 800px;
width: 800px;
background-image: repeating-radial-gradient(circle at 17% 132%, white 0.0005px, black 0.00085px);
animation: anim 1s steps(2, jump-both) infinite both;
transform: translate3d(0, 0, 0);
}
/******************************/
.tv0 {
width: 400px;
height: 200px;
border: 6px solid black;
margin: 0 auto;
overflow: hidden;
position: relative;
border-radius: 50% / 10%;
isolation: isolate;
}
.tv-static0 {
position: absolute;
top: 0px;
left: 0px;
margin: auto;
height: 300%;
width: 300%;
animation: anim 1s steps(2, end) infinite both;
transform: translate3d(0, 0, 0);
filter: contrast(300%) brightness(50%);
}
.tv-static0 svg {
height: 200%;
width: 100%;
transform: scale(2.5);
}
/******************************/
.tv1 {
width: 400px;
height: 200px;
border: 6px solid black;
margin: 0 auto;
overflow: hidden;
position: relative;
border-radius: 50% / 10%;
}
.tv-static1 {
position: absolute;
top: -500px;
right: -500px;
bottom: -500px;
left: -500px;
margin: auto;
background-image: url(https://i.stack.imgur.com/uzEM4.png);
animation: anim 1s steps(2, end) infinite both;
transform: translate3d(0, 0, 0);
}
/******************************/
.tv2 {
width: 400px;
height: 200px;
border: 6px solid black;
margin: 0 auto;
overflow: hidden;
position: relative;
border-radius: 50% / 10%;
}
.tv-static2 {
position: absolute;
top: -500px;
right: -500px;
bottom: -500px;
left: -500px;
margin: auto;
background-image: url(https://i.stack.imgur.com/9Be02.gif);
transform: translate3d(0, 0, 0);
}
#keyframes anim {
0% {
transform: translateX(0px, 0px);
}
10% {
transform: translate(-100px, 100px);
}
20% {
transform: translate(150px, -100px);
}
30% {
transform: translate(-100px, 100px);
}
40% {
transform: translate(100px, -150px);
}
50% {
transform: translate(-100px, 200px);
}
60% {
transform: translate(-200px, -100px);
}
70% {
transform: translateY(50px, 100px);
}
80% {
transform: translate(100px, -150px);
}
90% {
transform: translate(0px, 200px);
}
100% {
transform: translate(-100px, 100px);
}
}
Your original code. modified. May not work on every browser.
<div class="tv">
<div class="tv-static"></div>
</div>
<br> Using SVG `feTurbulence` filter
<div class="tv0">
<div class="tv-static0">
<svg viewBox="0 0 200% 200%" xmlns='http://www.w3.org/2000/svg'>
<filter id='noiseFilter'>
<feTurbulence type='turbulence' result='noise' baseFrequency='0.7' numOctaves='6' seed='2'
stitchTiles='noStitch' />
</filter>
<rect width='100%' height='100%' filter='url(#noiseFilter)' />
</svg>
<div class="overlay"></div>
</div>
</div>
<br>
<br> Animating image. Color TV
<div class="tv1">
<div class="tv-static1"></div>
</div>
<br> Using gif. No animation.
<div class="tv2">
<div class="tv-static2"></div>
</div>

Editting the CSS animation

I found a css animation online, but i wanted to edit it a bit.
This is the link to the animation
Is there anyway i can make this animation run only when a certain button on the website is clicked, and is it possible that the door opens only once and it leads to a different site on the other end of the door??
Right now the door animation is running infinite times. Please help
body {
display: flex;
width: 100%;
height: 100vh;
background: #222;
perspective: 100vw;
overflow: hidden;
animation: squiggly-anim 0.4s infinite;
-webkit-animation: squiggly-anim 0.2s infinite;
}
#-webkit-keyframes squiggly-anim {
0% {
filter: url("#squiggly-0");
}
25% {
filter: url("#squiggly-1");
}
50% {
filter: url("#squiggly-2");
}
75% {
filter: url("#squiggly-3");
}
100% {
filter: url("#squiggly-4");
}
}
#keyframes squiggly-anim {
0% {
filter: url("#squiggly-0");
}
25% {
filter: url("#squiggly-1");
}
50% {
filter: url("#squiggly-2");
}
75% {
filter: url("#squiggly-3");
}
100% {
filter: url("#squiggly-4");
}
}
body .door {
position: absolute;
width: 100px;
height: 200px;
left: calc(50% - 50px);
top: calc(50% - 100px);
box-shadow: inset 0 -5px 0 0 #222, inset 0 0 0 1px #fff, 0 5px 0 0 #222, 0 0 0 100vw #222;
perspective: 500px;
transform-style: preserve-3d;
-webkit-animation: scaling 5s linear infinite;
animation: scaling 5s linear infinite;
transform: translateZ(-1px);
}
body .door:nth-of-type(3) {
-webkit-animation-delay: 1.25s;
animation-delay: 1.25s;
}
body .door:nth-of-type(3) .face {
-webkit-animation-delay: 1.25s;
animation-delay: 1.25s;
}
body .door:nth-of-type(2) {
-webkit-animation-delay: 2.5s;
animation-delay: 2.5s;
}
body .door:nth-of-type(2) .face {
-webkit-animation-delay: 2.5s;
animation-delay: 2.5s;
}
body .door:nth-of-type(1) {
-webkit-animation-delay: 3.75s;
animation-delay: 3.75s;
}
body .door:nth-of-type(1) .face {
-webkit-animation-delay: 3.75s;
animation-delay: 3.75s;
}
#-webkit-keyframes scaling {
0% {
transform: translateZ(0vw);
opacity: 1;
z-index: 0;
}
50% {
transform: translateZ(100vw);
opacity: 1;
z-index: 1;
}
95% {
transform: translateZ(200vw);
opacity: 1;
z-index: 2;
}
100% {
transform: translateZ(300vw);
opacity: 0;
z-index: 3;
}
}
#keyframes scaling {
0% {
transform: translateZ(0vw);
opacity: 1;
z-index: 0;
}
50% {
transform: translateZ(100vw);
opacity: 1;
z-index: 1;
}
95% {
transform: translateZ(200vw);
opacity: 1;
z-index: 2;
}
100% {
transform: translateZ(300vw);
opacity: 0;
z-index: 3;
}
}
#keyframes scaling {
0% {
transform: translateZ(0vw);
opacity: 1;
z-index: 0;
}
50% {
transform: translateZ(100vw);
opacity: 1;
z-index: 1;
}
95% {
transform: translateZ(200vw);
opacity: 1;
z-index: 2;
}
100% {
transform: translateZ(300vw);
opacity: 0;
z-index: 3;
}
}
#keyframes scaling {
0% {
transform: translateZ(0vw);
opacity: 1;
z-index: 0;
}
50% {
transform: translateZ(100vw);
opacity: 1;
z-index: 1;
}
95% {
transform: translateZ(200vw);
opacity: 1;
z-index: 2;
}
100% {
transform: translateZ(300vw);
opacity: 0;
z-index: 3;
}
}
#keyframes scaling {
0% {
transform: translateZ(0vw);
opacity: 1;
z-index: 0;
}
50% {
transform: translateZ(100vw);
opacity: 1;
z-index: 1;
}
95% {
transform: translateZ(200vw);
opacity: 1;
z-index: 2;
}
100% {
transform: translateZ(300vw);
opacity: 0;
z-index: 3;
}
}
#keyframes scaling {
0% {
transform: translateZ(0vw);
opacity: 1;
z-index: 0;
}
50% {
transform: translateZ(100vw);
opacity: 1;
z-index: 1;
}
95% {
transform: translateZ(200vw);
opacity: 1;
z-index: 2;
}
100% {
transform: translateZ(300vw);
opacity: 0;
z-index: 3;
}
}
#keyframes scaling {
0% {
transform: translateZ(0vw);
opacity: 1;
z-index: 0;
}
50% {
transform: translateZ(100vw);
opacity: 1;
z-index: 1;
}
95% {
transform: translateZ(200vw);
opacity: 1;
z-index: 2;
}
100% {
transform: translateZ(300vw);
opacity: 0;
z-index: 3;
}
}
body .door:after {
content: "";
position: absolute;
width: 200vw;
height: 100vw;
left: -50vw;
bottom: 5px;
box-shadow: 0 1px 0 0 #fff;
z-index: -1;
}
body .door .face {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: calc(100% - 4px);
transform-style: preserve-3d;
box-shadow: inset 0 0 0 1px #fff;
background: #222;
transform-origin: left;
-webkit-animation: swing 5s ease-in-out infinite;
animation: swing 5s ease-in-out infinite;
}
body .door .face:before {
content: "";
position: absolute;
width: 10px;
height: 10px;
box-shadow: 0 0 0 1px #fff;
border-radius: 100%;
right: 10px;
top: calc(50% - 5px);
transform-style: preserve-3d;
transform: translateZ(6px);
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
background: #222;
}
body .door .face:after {
content: "";
position: absolute;
width: 4px;
height: 2.5px;
box-shadow: 0 0 0 1px #fff;
opacity: 0.75;
border-radius: 0;
right: 10px;
top: calc(50% - 1.25px);
transform-style: preserve-3d;
transform: translateZ(2.5px) rotateY(90deg);
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
background: #222;
}
#-webkit-keyframes swing {
15% {
transform: rotateY(0deg);
}
50% {
transform: rotateY(-125deg) translateZ(-2px);
}
75% {
transform: rotateY(-125deg);
}
100% {
transform: rotateY(-125deg);
}
}
#keyframes swing {
15% {
transform: rotateY(0deg);
}
50% {
transform: rotateY(-125deg) translateZ(-2px);
}
75% {
transform: rotateY(-125deg);
}
100% {
transform: rotateY(-125deg);
}
}
body .door .face .right {
position: absolute;
width: 10%;
background: #222;
height: 100%;
top: 0;
right: -10%;
transform-origin: left;
transform: rotateY(90deg);
box-shadow: inset 0 0 0 1px #fff;
}
<div class='door'>
<div class='face'>
<div class='right'></div>
</div>
</div>
<div class='door'>
<div class='face'>
<div class='right'></div>
</div>
</div>
<div class='door'>
<div class='face'>
<div class='right'></div>
</div>
</div>
<div class='door'>
<div class='face'>
<div class='right'></div>
</div>
</div>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" style="display:none">
<defs>
<filter id="squiggly-0">
<feTurbulence id="turbulence" baseFrequency="0.01" numOctaves="3" result="noise" seed="0"/>
<feDisplacementMap id="displacement" in="SourceGraphic" in2="noise" scale="2" />
</filter>
<filter id="squiggly-1">
<feTurbulence id="turbulence" baseFrequency="0.01" numOctaves="3" result="noise" seed="1"/>
<feDisplacementMap in="SourceGraphic" in2="noise" scale="3" />
</filter>
<filter id="squiggly-2">
<feTurbulence id="turbulence" baseFrequency="0.01" numOctaves="3" result="noise" seed="2"/>
<feDisplacementMap in="SourceGraphic" in2="noise" scale="2" />
</filter>
<filter id="squiggly-3">
<feTurbulence id="turbulence" baseFrequency="0.01" numOctaves="3" result="noise" seed="3"/>
<feDisplacementMap in="SourceGraphic" in2="noise" scale="3" />
</filter>
<filter id="squiggly-4">
<feTurbulence id="turbulence" baseFrequency="0.01" numOctaves="3" result="noise" seed="4"/>
<feDisplacementMap in="SourceGraphic" in2="noise" scale="1" />
</filter>
</defs>
</svg>
There are a three main parts to this question.
First, how to have just one door in the animation. There are 4 divs with class door. If we take 3 of these out the remaining one animates, but there is a delay before the animation (needed in the original so that the 4 doors started their movements at staggered times) so we take that out. While we are at it we notice that there are several #keyframes repeated - only the last one would be used so we remove those too.
Second, the requirement is to start the door animation on clicking a button. So we add a button element and in JS attach an event listener to it. When clicked it will add the class 'open' to the door. In the CSS the animation to the door and the door face are changed so they are added when the class is open.u
Third the requirement is to go to a website when the door has opened. Ideally one would want the website gradually revealed as the door is opened. This can be achieved if the website is under our control, for example the code could be run at the start of the website and it would gradually get revealed. If not a similar effect can be achieved by putting the target website in an iframe and gradually revealing it. However, many websites do not allow this and in this snippet just for fun we have put an image behind the door and gone to the website only once it is fully open. This is just to demonstrate possibilities. There may be a better way of doing it - let's hope so.
let page = "https://stackoverflow.com";
let button = document.getElementById('opendoor');
let door = document.querySelector('.door');
let face = document.querySelector('.face');
//document.querySelector("#target").src = page;//only do this if the target website lets you have an iframe
button.addEventListener('click', function () {
door.classList.add('open');
button.style.display = 'none';
document.body.style.animation = 'none';
});
face.addEventListener('webkitAnimationEnd', gotopage);//webkit still needed for some browsers
face.addEventListener('animationEnd', gotopage);
function gotopage() {
document.getElementById('doorwrapper').style.display = 'none';
window.location= page;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #222;
width: 100%;
height: 100vh;
overflow: hidden;
perspective: 100vw;
overflow: hidden;
animation: squiggly-anim 0.4s infinite;
}
#doorwrapper {
position: absolute;
top: -10px;
left: -10px;/* attempt to stop shakiness at margin black against white */
display: flex;
width: calc(100vw + 20px);
height: calc(100vh + 20px);
background-color: transparent;
z-index: 99999;
}
#keyframes squiggly-anim {
0% {
filter: url("#squiggly-0");
}
25% {
filter: url("#squiggly-1");
}
50% {
filter: url("#squiggly-2");
}
75% {
filter: url("#squiggly-3");
}
100% {
filter: url("#squiggly-4");
}
}
#doorwrapper .door {
position: absolute;
width: 100px;
height: 200px;
left: calc(50% - 50px);
top: calc(50% - 100px);
box-shadow: inset 0 -5px 0 0 #222, inset 0 0 0 1px #fff, 0 5px 0 0 #222, 0 0 0 100vw #222;
perspective: 500px;
transform-style: preserve-3d;
animation-fill-mode: forwards;
transform: translateZ(-1px);
}
#doorwrapper .door.open {
animation: scaling 5s linear 1;
}
#keyframes scaling {
0% {
transform: translateZ(0vw);
opacity: 1;
}
50% {
transform: translateZ(100vw);
opacity: 1;
}
95% {
transform: translateZ(200vw);
opacity: 1;
}
100% {
transform: translateZ(300vw);
opacity: 0;
}
}
#doorwrapper .door:after {
content: "";
position: absolute;
width: 200vw;
height: 100vw;
left: -50vw;
bottom: 5px;
box-shadow: 0 1px 0 0 #fff;
z-index: -1;
}
#doorwrapper .door .face {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: calc(100% - 4px);
transform-style: preserve-3d;
box-shadow: inset 0 0 0 1px #fff;
background: #222;
transform-origin: left;
animation-fill-mode: forwards;
}
#doorwrapper .door.open .face {
animation: swing 5s ease-in-out 1;
}
#doorwrapper .door .face:before {
content: "";
position: absolute;
width: 10px;
height: 10px;
box-shadow: 0 0 0 1px #fff;
border-radius: 100%;
right: 10px;
top: calc(50% - 5px);
transform-style: preserve-3d;
transform: translateZ(6px);
backface-visibility: hidden;
background: #222;
}
#doorwrapper .door .face:after {
content: "";
position: absolute;
width: 4px;
height: 2.5px;
box-shadow: 0 0 0 1px #fff;
opacity: 0.75;
border-radius: 0;
right: 10px;
top: calc(50% - 1.25px);
transform-style: preserve-3d;
transform: translateZ(2.5px) rotateY(90deg);
backface-visibility: hidden;
background: #222;
}
#keyframes swing {
15% {
transform: rotateY(0deg);
}
50% {
transform: rotateY(-125deg) translateZ(-2px);
}
75% {
transform: rotateY(-125deg);
}
100% {
transform: rotateY(-125deg);
}
}
#doorwrapper .door .face .right {
position: absolute;
width: 10%;
background: #222;
height: 100%;
top: 0;
right: -10%;
transform-origin: left;
transform: rotateY(90deg);
box-shadow: inset 0 0 0 1px #fff;
}
<div id="doorwrapper">
<div class='door'>
<div class='face'>
<div class='right'></div>
</div>
</div>
</div>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" style="display:none">
<defs>
<filter id="squiggly-0">
<feTurbulence id="turbulence" baseFrequency="0.01" numOctaves="3" result="noise" seed="0"/>
<feDisplacementMap id="displacement" in="SourceGraphic" in2="noise" scale="2" />
</filter>
<filter id="squiggly-1">
<feTurbulence id="turbulence" baseFrequency="0.01" numOctaves="3" result="noise" seed="1"/>
<feDisplacementMap in="SourceGraphic" in2="noise" scale="3" />
</filter>
<filter id="squiggly-2">
<feTurbulence id="turbulence" baseFrequency="0.01" numOctaves="3" result="noise" seed="2"/>
<feDisplacementMap in="SourceGraphic" in2="noise" scale="2" />
</filter>
<filter id="squiggly-3">
<feTurbulence id="turbulence" baseFrequency="0.01" numOctaves="3" result="noise" seed="3"/>
<feDisplacementMap in="SourceGraphic" in2="noise" scale="3" />
</filter>
<filter id="squiggly-4">
<feTurbulence id="turbulence" baseFrequency="0.01" numOctaves="3" result="noise" seed="4"/>
<feDisplacementMap in="SourceGraphic" in2="noise" scale="1" />
</filter>
</defs>
</svg>
<button id="opendoor" style="position: absolute; top: 10px; left: 10px; color: white; background-color: red; z-index: 99999;">Open the door</button>
<!-- YOUR WEBSITE - OR IFRAME WITH THE TARGET WEBSITE IN IT (OR WILL GO TO WEBSITE ON END OF ANIMATION IF IFRAME NOT ALLOWED -->
<!-- <iframe id="target" width=100% height=100% src=""></iframe> -->
<img id="mywebsite" src="https://i.stack.imgur.com/qsQbR.jpg" style="position: relative; top: 0; left: 0; z-index: 0; width: 100vw; height: auto;"/>

How to animate concave rectangle to convex

I have created a rectangle of the following shape using sketch.
When I hover it I need to animate and rest as the below shape.
Is there a way I can animate it using css only from concave to convex.
Any help would be appreciated. I am fine with svg solution as well.
Here is the link to the fiddle for svg.
<svg width="641px" height="313px" viewBox="0 0 641 313" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 52.5 (67469) - http://www.bohemiancoding.com/sketch -->
<title>Concave</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M0,252.683363 C104.477953,274.894454 210.133596,286 316.966929,286 C423.800262,286 531.811286,274.894454 641,252.683363 L641,565 L0,565 L0,252.683363 Z" id="path-1"></path>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="iteration-3" transform="translate(-752.000000, -3299.000000)">
<g id="case--study" transform="translate(0.000000, 2766.000000)">
<g transform="translate(50.000000, 100.000000)" id="case--study--1-copy">
<g transform="translate(702.000000, 181.000000)">
<use id="bottom" fill="#000000" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</g>
</g>
</g>
</g>
</svg>
For a CSS only solution I would consider a radial-gradient and some background animation:
.box {
height:50px;
width:600px;
padding-top:50px;
background:
/*concave*/
radial-gradient(410px 50px at 50% 0,transparent, 80%, #000 80.5%) center,
/*convexe*/
radial-gradient(410px 50px at 50% 50px,#000, 80%, transparent 80.5%)center,
linear-gradient(#000,#000) content-box;
background-size:100% 100%,100% 0px,auto;
background-repeat:no-repeat;
transition:1s all;
}
.box:hover {
background-size:100% 0,100% 100%,auto;
}
<div class="box"></div>
You can also have it for a full width rectangle:
.box {
height:50px;
padding-top:50px;
background:
/*concave*/
radial-gradient(70% 50px at 50% 0,transparent, 80%, #000 80.5%) center,
/*convexe*/
radial-gradient(70% 50px at 50% 50px,#000, 80%, transparent 80.5%)center,
linear-gradient(#000,#000) content-box;
background-size:100% 100%,100% 0px,auto;
background-repeat:no-repeat;
transition:1s all;
}
.box:hover {
background-size:100% 0,100% 100%,auto;
}
<div class="box"></div>
In case you will have a bigger height or dynamic height better consider a pseudo element so the effect won't get affected by height changing:
.box {
height: 80vh;
position: relative;
padding-top: 50px;
background: #000 content-box;
}
.box::before {
content: "";
position: absolute;
top: 1px;
left: 0;
right: 0;
padding: inherit;
background:
/*concave*/
radial-gradient(70% 50px at 50% 0, transparent, 80%, #000 80.5%) bottom,
/*convexe*/
radial-gradient(70% 50px at 50% 50px, #000, 80%, transparent 80.5%)bottom;
background-size: 100% 100%, 100% 0px;
background-repeat: no-repeat;
transition: 1s all;
}
.box:hover::before {
background-size: 100% 0, 100% 100%;
}
<div class="box"></div>
Update
You can also adjust the effect like below:
.box {
height: 80vh;
position: relative;
padding-top: 100px;
background: #000 content-box;
}
/*concave*/
.box::before {
content: "";
position: absolute;
top: 50px;
left: 0;
right: 0;
height: 51px;
background:
radial-gradient(70% 50px at 50% 0, transparent, 80%, #000 80.5%) top center;
background-size: 100% 200%;
background-repeat: no-repeat;
transition: 0.5s all 0.4s ease-out;
}
/*convexe*/
.box::after {
content: "";
position: absolute;
top: 1px;
left: 0;
right: 0;
height: 51px;
background:
radial-gradient(70% 50px at 50% 50px, #000, 80%, transparent 80.5%)bottom center;
background-size: 200% 0%;
background-repeat: no-repeat;
transition: 0.5s all ease-in;
}
.box:hover::before {
background-position: bottom center;
background-size: 200% 200%;
transition: 0.5s all ease-in;
}
.box:hover::after {
background-size: 100% 100%;
transition: 0.5s all 0.4s ease-out;
}
<div class="box"></div>
One solution could be to create the shape with SVG and then transition the path via CSS:
body {
width: 40vw;
display: block;
margin: 0 auto;
}
.path {
transition: d 2s ease-in-out;
}
.path:hover{
d: path('M0 20 Q 50 0 100 20 L100 60 L0 60 Z');
}
<svg viewBox="0 0 100 60" xmlns="http://www.w3.org/2000/svg">
<path class="path" d="M0 20 Q 50 40 100 20 L100 60 L0 60 Z" fill="black"/>
</svg>
<p>hover over the shape</p>

CSS Only Marker Shape

I want to create a CSS only shape that looks like a marker or guitar pick.
My Codepen demo I've been working from: http://codepen.io/Vestride/pen/otcem
// CSS Marker
// I was attempting to make this shape in CSS. The marker on the far right is an image. Next to it is SVG. The rest are my attempts :|
// stackoverflow question: http://stackoverflow.com/questions/11982066/css-only-marker-shape
// Top part is a perfect circle
// Bottom half is edges that curve out!
body {
margin: 40px 20px;
background: url(http://subtlepatterns.com/patterns/furley_bg_#2X.png) ;
background-size: 600px 600px;
}
figure {
position: relative;
float: left;
margin-left: 60px;
width: 80px;
height: 80px;
}
figure:first-child {
margin-left: 0;
}
.one {
border-radius: 50% 50% 0 50%;
background: hotpink;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
}
.two {
background: skyblue;
border-top-left-radius: 50%;
border-top-right-radius: 50% 100%;
border-bottom-left-radius: 100% 50%;
border-bottom-right-radius: 0%;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
}
.three {
border-radius: 50%;
background: lightgreen;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
}
.three::before {
content: '';
position: absolute;
width: 106%;
height: 106%;
background: lightgreen;
border-top-left-radius: 60%;
border-top-right-radius: 50% 100%;
border-bottom-left-radius: 100% 50%;
border-bottom-right-radius: 0%;
}
.four {
border-radius: 50% 50% 0 50%;
background: seagreen;
overflow-x: visible;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
}
.four::before {
content: '';
position: absolute;
width: 100%;
height: 100%;
background: red;
border-top-left-radius: 50%;
border-top-right-radius: 50% 100%;
border-bottom-left-radius: 100% 50%;
border-bottom-right-radius: 0%;
}
.five {
width: 80px;
height: 102px;
background-image: url(http://i.imgur.com/t80ZS.png);
/* Overlay the objective */
/*margin-left: -80px;
opacity: 0.6;*/
}
.svg {
position: relative;
float: left;
margin-left: 60px;
}
<figure class="one"></figure>
<figure class="two"></figure>
<figure class="three"></figure>
<figure class="four"></figure>
<figure class="svg">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="81px" height="104px" viewBox="0 0 81 104">
<g transform="translate(1, 1)"><path fill="#FFFFFF" stroke="#CCCCCC" stroke-width="2" d="M78.399,39.2c0,36.998-39.199,62.599-39.199,62.599S0,76.198,0,39.2C0,17.55,17.551,0,39.2,0 C60.848,0,78.399,17.55,78.399,39.2z"/></g>
</svg>
</figure>
<!-- Image -->
<figure class="five"></figure>
I've been unsuccessful in replicating the curvy edges by the point. Ideally I'd like to accomplish this with one element (+pseudo elements).
Take a look at this one, i changed their css abit:
http://codepen.io/anon/pen/HLJlu
With SVG
You can achieve the marker shape with an inline svg. The following example uses a path element with 2 cubic bezier curve commands:
svg{width:80px;height:100px;}
<svg viewbox="0 0 80 100">
<path d="M40 99.5 C-22.5 57.5 0 0 40 0.5 C80 0 102.5 57.5 40 99.5z" stroke-width="1" stroke="grey" fill="transparent"/>
</svg>
With CSS
You can also make the marker shape with CSS only using border radius, absolute positioning and 2 pseudo elements. Note that this example uses only one div element
div{
position:relative;
width:80px;
height:102px;
overflow:hidden;
border-radius:40px;
}
div:before, div:after{
content:'';
position:absolute;
top:0px;
width:240px;
height:150px;
border:1px solid green;
}
div:before{
left:0;
border-top-left-radius:40px;
border-bottom-left-radius:240px 110px;
}
div:after{
right:0;
border-top-right-radius:40px;
border-bottom-right-radius:240px 110px;
}
<div></div>
<svg x="0px" y="0px" width="32px" height="45px"
viewBox="38 12 128 180" style="cursor:help;" >
<style type="text/css">
.st0{ fill:#FFF;stroke:#000;stroke-width:6;stroke-miterlimit:10;}
.st1{fill:#FFFFFF;}
.st2{fill:#1309FF;}
.st3{fill:#1309FF;}
.st4{fill:#1309FF;}
.st6{font-size:57.2285px;}
</style>
<path class="st0" d="M158.5,73.8c0-32.3-26.2-58.4-58.4-58.4c-32.3,0-58.4,26.2-58.4,58.4c0,16.6,6.9,31.5,18,42.1
c7.2,7.2,16.7,17.2,20.1,22.5c7,10.9,20,47.9,20,47.9s13.3-37,20.4-47.9c3.3-5.1,12.2-14.4,19.3-21.6
C151.2,106.1,158.5,90.9,158.5,73.8z"/>
<circle class="st4" cx="100.1" cy="74.7" r="44.1"/>
<text x="100" y="90" class="st1 st5 st6" text-anchor="middle" >12</text>
</svg>
This will be better OR This
<svg width="32px" height="45px" viewBox="38 12 128 180" >
<path style="fill:#FFFFFF;stroke:#020202;stroke-width:4;stroke-miterlimit:10;" d="M158.5,73.8c0-32.3-26.2-58.4-58.4-58.4c-32.3,0-58.4,26.2-58.4,58.4c0,16.6,6.9,31.5,18,42.1c7.2,7.2,16.7,17.2,20.1,22.5c7,10.9,20,47.9,20,47.9s13.3-37,20.4-47.9c3.3-5.1,12.2-14.4,19.3-21.6C151.2,106.1,158.5,90.9,158.5,73.8z"/>
<circle style="fill:' + color + ';" cx="100.1" cy="74.7" r="44.1"/>
<text x="100" y="90" text-anchor="middle" style="font-size:57.2285px;fill:#FFFFFF;">12</text>
</svg>

Resources