Animate growing div then animate child element - css

I'm currently trying to animate a growing <div> but I don't want the content to look like it is growing along with it. The content should remain invisible while the <div> is animating and once it's fully grown I'd like for the content to become visible (by changing the opacity of the <a> in that <div>).
This is the code for the <div> animation:
#keyframes menu {
0% {
background-color: white;
right: -25px;
top: -25px;
border-radius: 100px;
width: 0px;
height: 0px;
}
25%{
right: -50px;
top: -50px;
border-radius: 100px;
width: 60px;
height: 60px;
}
50% {
right: -50px;
top: -50px;
width: 80px;
height: 80px;
border-radius: 100px;
}
75%{
right:-50px;
top:-50px;
width: 150px;
height: 150px;
border-radius: 100px;
}
80%{
right:-50px;
top:-50px;
width: 300px;
height: 300px;
border-radius: 300px;
}
100%{
right:-150px;
top:-150px;
width: 450px;
height: 450px;
border-radius: 600px;
}
}
It's basically a menu that starts in the corner and grows until the full screen is covered (mobile). I've tried adding a{ opacity: 1 }; but I guess it doesn't work like that.

If you want the anchor text (within the div) to be visible only after the animation on the parent div is fully complete then add another animation to the a, animate the opacity from 0 to 1 after a delay which is equal to the animation-duration of the parent.
div {
background-color: black;
line-height: 450px;
text-align: center;
animation: menu 4s linear forwards;
}
a {
color: white;
text-decoration: none;
animation: display 1s linear 4s backwards;
}
#keyframes menu {
0% {
background-color: white;
right: -25px;
top: -25px;
border-radius: 100px;
width: 0px;
height: 0px;
}
25% {
right: -50px;
top: -50px;
border-radius: 100px;
width: 60px;
height: 60px;
}
50% {
right: -50px;
top: -50px;
width: 80px;
height: 80px;
border-radius: 100px;
}
75% {
right: -50px;
top: -50px;
width: 150px;
height: 150px;
border-radius: 100px;
}
80% {
right: -50px;
top: -50px;
width: 300px;
height: 300px;
border-radius: 300px;
}
100% {
right: -150px;
top: -150px;
width: 450px;
height: 450px;
border-radius: 600px;
}
}
#keyframes display {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
<div>
<a href='#'>Some Menu Link</a>
</div>

I would use a little jQuery to do that. Using a callback you can call opacity 1 on a after the div is complete grown.
$( ".yourdiv" ).animate({
width: "450"
height: "450"
}, 5000, function() {
//callback will cause the a to change its opacity only when the above function is complete
$('.yourdiv a').css('opacity') = '1';
});

Related

Two animations in CSS not working at the same time

I've created two animations with CSS a clock and a bouncing ball. Separately they both work as intended, but once I put them in the same file the bouncing ball disappeared.
If I delete #keyframes rotation the clock stops working but the bouncing ball appears. Is there any way how to make both animations work?
.clock {
position: relative;
width: 400px;
height: 400px;
border: 10px solid;
border-radius: 50%;
}
#second {
position: absolute;
background: black;
width: 2px;
height: 180px;
margin: 20px 199px;
animation: rotation 60s infinite linear;
transform-origin: bottom left;
}
#minute {
position: absolute;
background: black;
width: 6px;
height: 140px;
margin: 60px 197px;
animation: rotation 3600s infinite linear;
transform-origin: bottom right;
}
#hour {
position: absolute;
background: black;
width: 10px;
height: 120px;
margin: 80px 195px;
animation: rotation 43200s infinite linear;
transform-origin: bottom left;
}
#keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
.box {
position: relative;
}
.ball {
position: absolute;
height: 100px;
width: 100px;
border: 3px solid pink;
border-radius: 50%;
animation: bounce 2s infinite;
background: pink;
}
.step1 {
position: absolute;
top: 150px;
height: 10px;
width: 220px;
background: cyan;
}
.step2 {
position: absolute;
top: 150px;
left: 220px;
margin-top: 20px;
height: 10px;
width: 220px;
background: cyan;
}
.step3 {
margin-top: 40px;
position: absolute;
left: 440px;
top: 150px;
height: 10px;
width: 220px;
background: cyan;
}
#keyframes bounce {
from {margin: 100pxz 0px;}
to{margin: 50px 500px;}
0% {
transform: translateY(-30%);
}
12% {
transform: translateY(33%);
}
24% {
transform: translateY(-66%);
}
36% {
transform: translateY(33%);
}
48% {
transform: translateY(-20%);
}
100% {
transform: translateY(33%);
}
<div class="clock">
<div id="hour"></div>
<div id="minute"></div>
<div id="second"></div>
</div>
<div class="box">
<div class="step1"></div>
<div class="step2"></div>
<div class="step3"></div>
<div class="ball"></div>
</div>
It works fine, you're/were missing the closing brackets on your keyframes
.clock {
position: relative;
width: 400px;
height: 400px;
border: 10px solid;
border-radius: 50%;
}
#second {
position: absolute;
background: black;
width: 2px;
height: 180px;
margin: 20px 199px;
animation: rotation 60s infinite linear;
transform-origin: bottom left;
}
#minute {
position: absolute;
background: black;
width: 6px;
height: 140px;
margin: 60px 197px;
animation: rotation 3600s infinite linear;
transform-origin: bottom right;
}
#hour {
position: absolute;
background: black;
width: 10px;
height: 120px;
margin: 80px 195px;
animation: rotation 43200s infinite linear;
transform-origin: bottom left;
}
#keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
.box {
position: relative;
}
.ball {
position: absolute;
height: 100px;
width: 100px;
border: 3px solid pink;
border-radius: 50%;
animation: bounce 2s infinite;
background: pink;
}
.step1 {
position: absolute;
top: 150px;
height: 10px;
width: 220px;
background: cyan;
}
.step2 {
position: absolute;
top: 150px;
left: 220px;
margin-top: 20px;
height: 10px;
width: 220px;
background: cyan;
}
.step3 {
margin-top: 40px;
position: absolute;
left: 440px;
top: 150px;
height: 10px;
width: 220px;
background: cyan;
}
#keyframes bounce {
from {
margin: 100pxz 0px;
}
to {
margin: 50px 500px;
}
0% {
transform: translateY(-30%);
}
12% {
transform: translateY(33%);
}
24% {
transform: translateY(-66%);
}
36% {
transform: translateY(33%);
}
48% {
transform: translateY(-20%);
}
100% {
transform: translateY(33%);
}
}
<div class="clock">
<div id="hour"></div>
<div id="minute"></div>
<div id="second"></div>
</div>
<div class="box">
<div class="step1"></div>
<div class="step2"></div>
<div class="step3"></div>
<div class="ball"></div>
</div>

Border-radius not working during CSS transform

Trying to make a rounded menu background. But the border-radius is not working while closing
var menuButton = document.querySelector('.btn-menu');
menuButton.addEventListener('click', function(e){
e.preventDefault();
document.body.classList.toggle('menu-open');
});
.btn-menu{
width: 30px;
height: 30px;
border: 2px solid red;
position: relative;
z-index: 5;
float: right;
}
.menu-bg {
position: fixed;
left: 0;
top: 0;
bottom: 0;
width: 100%;
z-index: 40;
pointer-events: none;
z-index: 1;
}
.menu-bg:before {
content: '';
height: 1px;
width: 1px;
background: #000;
position: fixed;
right: 30px;
top: 30px;
transition: all ease .8s;
border-radius: 50%;
transform: scale(1);
overflow:hidden;
}
.menu-open .menu-bg:before {
transform: scale(500);
}
<div class="btn-menu"><span>Menu</span></div>
<div class="menu-bg"></div>
JSFiddle - https://jsfiddle.net/afelixj/ew7b065h/
1px as width/height is not a good idea, I would do it differently and start at scale(0):
var menuButton = document.querySelector('.btn-menu');
menuButton.addEventListener('click', function(e) {
e.preventDefault();
document.body.classList.toggle('menu-open');
});
.btn-menu {
width: 30px;
height: 30px;
border: 2px solid red;
position: relative;
z-index: 5;
float: right;
}
.menu-bg {
position: fixed;
left: 0;
top: 0;
bottom: 0;
width: 100%;
z-index: 40;
pointer-events: none;
z-index: 1;
}
.menu-bg:before {
content: '';
height: 100px;
width: 100px;
background: #000;
position: fixed;
right: -20px;
top: -20px;
transition: all ease .8s;
border-radius: 50%;
transform: scale(0);
overflow: hidden;
}
.menu-open .menu-bg:before {
transform: scale(5);
}
<div class="btn-menu"><span>Menu</span></div>
<div class="menu-bg"></div>
It's a browser bug. Sometimes it works fine and then, if you change window width, it will start messing up (I saw the problem sometimes opening the menu up).
There's a known problem using transform on fixed elements: link You should try to avoid it.
In your case, insteed of transform you could just change your width, height and position to make it work as you may desire.
As an example:
var menuButton = document.querySelector('.btn-menu');
menuButton.addEventListener('click', function(e){
e.preventDefault();
document.body.classList.toggle('menu-open');
});
.btn-menu{
width: 30px;
height: 30px;
border: 2px solid red;
position: relative;
z-index: 5;
float: right;
}
.menu-bg {
position: fixed;
left: 0;
top: 0;
bottom: 0;
width: 100%;
z-index: 40;
pointer-events: none;
z-index: 1;
}
.menu-bg:before {
content: '';
height: 1px;
width: 1px;
background: #000;
position: fixed;
right: 30px;
top: 30px;
transition: all ease .3s;
transform: scale(1);
border-radius: 50%;
}
.menu-open .menu-bg:before {
transition: all ease .6s;
height: 400px;
width: 400px;
right: -90px;
top: -90px;
border-radius: 50%;
}
<div class="btn-menu"><span></span></div>
<div class="menu-bg"></div>

Smooth CSS Transform Scale on rectangle, keeping an even border

I have an absolutely positioned div that I want to have slowly increase in size (5s transition) on hover, to become a "border" for a relative-positioned div on top of it:
<div class="rectangle">
<div class="background"></div>
<div class="content">blah</div>
</div>
Styles (vendor prefixes removed for readability):
.rectangle {
position: relative;
}
.background {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.content {
height: 800px;
width: 200px;
}
Transitioning the overall .background size results in choppy animation but an even border:
.rectangle:hover .background {
width: calc(100% + 40px);
height: calc(100% + 40px);
top: -20px;
left: -20px;
right: -20px;
bottom: -20px;
transition: 5s linear all;
}
Transitioning a border is choppy animation, but (obviously) an even border
.rectangle:hover .content {
border: 20px solid red;
transition: 5s linear all;
}
Transitioning a transform-scale is smooth, but results in a larger top and bottom "border" because it is a rectangle:
.rectangle:hover .background {
transition: 5s transform;
transform: scale(1.1);
}
Any way to either get transform-scale to keep even dimensions, or any other way to create this effect?
You can try using box shadow as a border to achieve smooth transitions.
.rectangle {
position: relative;
width: 300px;
height: 300px;
top: 100px;
left: 30%;
}
.background {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.background::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
box-shadow: 0 0 0 0px #000;
transition: 5s linear box-shadow;
}
.content {
height: 300px;
width: 200px;
}
.rectangle:hover .background::before {
box-shadow: 0 0 0 20px #000;
transition: 5s linear box-shadow;
}
<div class="rectangle">
<div class="background"></div>
<div class="content">blah</div>
</div>

Why translateZ working not working on hover?

When I hover over the image, the transition works fine except for the fact that the front image (that of a rotating lock) only translates 20px in Z direction when the mouse is removed from that image. I want the rotating lock image to be 20px in front always.
Also, why does the rotating lock image becomes slightly smaller just after I hover the image?
body {
margin:0;
width: 100%;
height: 100%;
}
.maincircle {
width: 200px;
height: 200px;
position: relative;
margin-left: 200px;
margin-top: 10px;
border-radius: 50%;
border: 1px solid black;
perspective: 600px;
transform-style: preserve-3d;
}
.door {
background-color: gray;
border-radius: 100%;
height: 200px;
margin: 0;
position: relative;
width: 200px;
transition: .5s linear;
transform-style: preserve-3d;
transform-origin: 0 50%;
transition: transform 2s 0.5s;
}
.door:before {
background-color: gray;
background-image: linear-gradient(hsla(0,0%,100%,.25), hsla(0,0%,0%,.25));
border-radius: 100%;
content: '';
height: 200px;
left: 0;
position: absolute;
top: 0;
width: 200px;
transform: translateZ(-5px);
}
.door:after {
background-color: gray;
background-image: linear-gradient(hsla(0,0%,100%,.25), hsla(0,0%,0%,.25));
bottom: 0;
content: '';
left: 100px;
position: absolute;
top: 0;
width: 5px;
z-index: -10;
transform: rotateY(-90deg);
transform-origin: 100% 50%;
}
.maincircle:hover .door {
transform: rotateY(-110deg);
}
.maincircle:hover .locker {
transform: rotate(90deg);
}
.locker {
background-image: url("https://irp-cdn.multiscreensite.com/806e9122/dms3rep/multi/tablet/CombinationLock-1000x1000.png");
position: absolute;
top: 25px;
left: 25px;
background-size: 100% 100%;
border-radius: 100%;
width: 150px;
height: 150px;
transform: translateZ(20px);
transition: transform 0.5s;
}
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="maincircle">
<div class="door">
<div class="locker"></div>
</div>
</div>
</body>
</html>
Question 1: (I want the rotating lock image to be 20px in front always)
It is because transform settings are not additive in nature. When you specify the transform during the :hover as give below,
.maincircle:hover .locker {
transform: rotate(90deg);
}
it overwrites the transform: translateZ(20px) that is specified within the default state (which is the setting under .locker selector) and so the translation in Z-axis is lost whenever the element is being hovered. It gets applied back only when the :hover is off (that is, the element returns to default state as specified in .locker selector).
In order to always have the translation in Z-axis, translateZ(20px) should be added to the transform stack within :hover selector also like below:
.maincircle:hover .locker {
transform: rotate(90deg) translateZ(20px);
}
body {
margin:0;
width: 100%;
height: 100%;
}
.maincircle {
width: 200px;
height: 200px;
position: relative;
margin-left: 200px;
margin-top: 10px;
border-radius: 50%;
border: 1px solid black;
perspective: 600px;
transform-style: preserve-3d;
}
.door {
background-color: gray;
border-radius: 100%;
height: 200px;
margin: 0;
position: relative;
width: 200px;
transition: .5s linear;
transform-style: preserve-3d;
transform-origin: 0 50%;
transition: transform 2s 0.5s;
}
.door:before {
background-color: gray;
background-image: linear-gradient(hsla(0,0%,100%,.25), hsla(0,0%,0%,.25));
border-radius: 100%;
content: '';
height: 200px;
left: 0;
position: absolute;
top: 0;
width: 200px;
transform: translateZ(-5px);
}
.door:after {
background-color: gray;
background-image: linear-gradient(hsla(0,0%,100%,.25), hsla(0,0%,0%,.25));
bottom: 0;
content: '';
left: 100px;
position: absolute;
top: 0;
width: 5px;
z-index: -10;
transform: rotateY(-90deg);
transform-origin: 100% 50%;
}
.maincircle:hover .door {
transform: rotateY(-110deg);
}
.maincircle:hover .locker {
transform: rotate(90deg) translateZ(20px);
}
.locker {
background-image: url("https://irp-cdn.multiscreensite.com/806e9122/dms3rep/multi/tablet/CombinationLock-1000x1000.png");
position: absolute;
top: 25px;
left: 25px;
background-size: 100% 100%;
border-radius: 100%;
width: 150px;
height: 150px;
transform: translateZ(20px);
transition: transform 0.5s;
}
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="maincircle">
<div class="door">
<div class="locker"></div>
</div>
</div>
</body>
</html>
Question 2: (Why does the rotating lock image becomes slightly smaller just after I hover the image?)
I am putting this at the last (even below the code) because I know by now you'd have guessed why it became smaller. It becomes smaller because the element is losing the translateZ(20px) and so it is going farther away from your eye. Any object that goes farther away from the eye will look smaller.

How do I make a opaque shape always hide everything staying behind it?

#circle { width: 100px; height: 100px;
position: relative;
background: gray; opacity: .6;
margin: 0 auto;
border-radius: 50%;
z-index: 2;}
#line { display: block; position: relative;
width: 100%; height: 5px;
background: red; top: -50px;
z-index: 1;}
<div id="circle"></div>
<div id="line"></div>
How to make parts of the red line that stay behind the circle invisible? Without changing the opacity of the circle to 1.
You don't need a separate "line" div for this.
body {
overflow: hidden;
background:grey;
}
#circle {
width: 100px;
height: 100px;
position: relative;
background: rgba(0,255,0,0.5); /* semi-transparent green */
opacity: .6;
margin: 0 auto;
border-radius: 50%;
z-index: 2;
}
#circle:before,
#circle:after {
content: '';
position: absolute;
width: 50vw;
top:50%;
height: 5px;
}
#circle:before {
left:0;
transform:translate(-100%,-50%);
background:red;
}
#circle:after {
left:100%;
transform:translate(0,-50%);
background:blue;
}
<div id="circle"></div>
Put a your circle inside a white circle see fiddle https://jsfiddle.net/v61bguns/
HTML
<div id="circle2"><div id="circle"></div></div>
<div id="line"></div>
CSS
#circle2 { width: 100px; height: 100px;
position: relative;
background: white;
margin: 0 auto;
border-radius: 50%;
z-index: 2;}
#circle { width: 100px; height: 100px;
position: relative;
background: gray; opacity: .6;
margin: 0 auto;
border-radius: 50%;
z-index: 3;}
#line { display: block; position: relative;
width: 100%; height: 5px;
background: red; top: -50px;
z-index: 1;}

Resources