Im trying to animate a button up to the center of it's parent element on hover using translateY and CSS3 animations, this seems to work fine (although any advice improvements would be great) but the problem is as soon as I hover off the button doesn't reverse the animation instead just resetting back to -50px. Was wondering how I can achieve this?
CSS (Using SCSS + Compass)
#include keyframe(slideIn) {
0%{
//opacity:0;
-webkit-transform:translateY(-50px);
}
60%{
//opacity:1;
//-webkit-transform:translateY(-195px);
}
80%{
-webkit-transform:translateY(-188px);
}
100%{
-webkit-transform:translateY(-175px);
}
}
.box {
width: 300px;
height: 300px;
background: navy;
position: relative;
-webkit-transform: translate3d(0, 0, 0);
overflow: hidden;
&:hover {
.btn {
#include animation(slideIn .45s ease-in-out alternate forwards);
}
}
}
.btn {
width: 50px;
height: 50px;
position: absolute;
bottom: -50px;
}
Codepen - http://codepen.io/styler/pen/fpFlL
You can define 3 css classes:
.box{
//base css here
}
.box.out{
animation-name: out;
animation-duration:.45s;
}
.box.over{
animation-name: in;
animation-duration:.45s;
}
#keyframe in {
//your keyframe animation here
}
#keyframe out {
//reverse animation here
}
Then some javascript to detect hovers:
$(".box").hover(
function () {
$(this).removeClass('out').addClass('over');
},
function () {
$(this).removeClass('over').addClass('out');
}
);
You should put the css animation on the button and not on the hover.
.box {
width: 300px;
height: 300px;
background: navy;
position: relative;
-webkit-transform: translate3d(0, 0, 0);
&:hover {
.btn {
bottom: 150px;
}
}
}
.btn {
width: 50px;
height: 50px;
position: absolute;
bottom: -50px;
-webkit-transition-duration: 0.3s;
-moz-transition-duration: 0.3s;
-o-transition-duration: 0.3s;
transition-duration: 0.3s;
}
http://codepen.io/anon/pen/qGxBh
Related
i would like to play this hover animation on component load, because I wrote a JS function that checks if the component is in the viewport and reloads it (changes its class).
You can use Sass (scss) or regular css.
.module .active {
display: inline-block;
position: relative;
color: var(--text-color-dark);
animation: loadInAnimation ease 3s;
animation-iteration-count: 1;
animation-fill-mode: forwards;
}
#keyframes loadInAnimation { // add :hover and :hover:after event
0% {
// start of animation
}
100% {
// end ofanimation
}
}
.module .active:after { // transform into keyframe animation
content: '';
position: absolute;
width: 100%;
transform: scaleX(0);
height: 2px;
bottom: 0;
left: 0;
background-color: var(--primary-color);
transform-origin: bottom right;
transition: transform 0.25s ease-out;
}
.module .active:hover:after { // transform into keyframe animation
transform: scaleX(1);
transform-origin: bottom left;
}
Thank you for your help!
JS (irrelevant):
<script>
function reveal() {
var reveals = document.querySelectorAll(".reveal");
console.log(reveals);
for (var i = 0; i < reveals.length; i++) {
var windowHeight = window.innerHeight;
var elementTop = reveals[i].getBoundingClientRect().top;
var elementVisible = 150;
if (elementTop < windowHeight - elementVisible) {
reveals[i].classList.add("active");
} else {
reveals[i].classList.remove("active");
}
}
}
window.addEventListener("scroll", reveal);
window.addEventListener("load", reveal);
</script>
HTML (also irrelevant):
<h2 className='heading reveal'>Tennisakademie Vasquez</h2>
I've fixed the animation with an additional element providing the :after feature:
.module .heading {
font-size: 2.75rem;
font-weight: 700;
margin-bottom: 2rem;
font-family: 'Oswald', sans-serif;
font-weight: 200;
color: var(--text-color-dark);
}
.module .active {
display: inline-block;
position: relative;
color: var(--text-color-dark);
animation-iteration-count: 1;
animation-fill-mode: forwards;
.reveal-line {
transform: scaleX(1);
transform-origin: bottom left;
content: '';
position: absolute;
width: 100%;
height: 2px;
bottom: 0;
left: 0;
background-color: var(--primary-color);
transform-origin: bottom right;
transition: transform 0.6s ease-out;
animation: loadInAnimation ease 1.5s;
}
}
#keyframes loadInAnimation {
0% {
width: 0%;
}
100% {
width: 100%;
}
}
<h3 className='heading reveal'>Unsere Angebote<div className='reveal-line' /></h3>
I want to applay a flicker animation to one button when the page is loaded (after a small delay) AND the same animation when the button is hovered. However, only one of the animations works. When both animations are not commented out, the animation when the page is loaded works. When I comment out this animation, the hover animation works. I don't understand, why it's like that.
HTML Code:
<div class="container">
Hello
</div>
CSS Code:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
height: 100vh;
background-image: linear-gradient(
to right bottom,
rgba(72, 80, 92, 0.444),
rgba(43, 43, 46, 0.757)
);
}
.btn:link,
.btn:visited {
text-decoration: none;
background-color: #fff;
color: rgb(70, 70, 70);
padding: 15px 40px;
display: inline-block;
border-radius: 100px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.btn::after {
content: "";
display: inline-block;
height: 100%;
width: 100%;
border-radius: 100px;
position: absolute;
top: 0;
left: 0;
z-index: -1;
background-color: #fff;
animation: flickerButton 0.4s 1s;
}
.btn:hover::after {
animation: flickerButton 0.4s;
}
#keyframes flickerButton {
0% {
transform: scaleX(1) scaleY(1);
opacity: 1;
}
100% {
transform: scaleX(1.4) scaleY(1.6);
opacity: 0;
}
}
Thank you very much for your support.
The problem is that the same animation keyframes are set on the actual pseudo element and when the element is hovered.
CSS reckons that once it's run the animation it doesn't need to do it again.
Assuming a CSS-only solution is required, this snippet has two copies of the keyframes, one for the non hovered condition, which runs the once, and one for when it is hovered when it runs once but then when unhovered the pseudo element doesn't have the animation set any more etc.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
height: 100vh;
background-image: linear-gradient( to right bottom, rgba(72, 80, 92, 0.444), rgba(43, 43, 46, 0.757));
}
.btn:link,
.btn:visited {
text-decoration: none;
background-color: #fff;
color: rgb(70, 70, 70);
padding: 15px 40px;
display: inline-block;
border-radius: 100px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.btn::after {
content: "";
display: inline-block;
height: 100%;
width: 100%;
border-radius: 100px;
position: absolute;
top: 0;
left: 0;
z-index: -1;
background-color: #fff;
animation: flickerButton 0.4s 1s;
}
.btn:hover::after {
animation: flickerButton1 0.4s;
}
#keyframes flickerButton {
0% {
transform: scaleX(1) scaleY(1);
opacity: 1;
}
100% {
transform: scaleX(1.4) scaleY(1.6);
opacity: 0;
}
}
#keyframes flickerButton1 {
0% {
transform: scaleX(1) scaleY(1);
opacity: 1;
}
100% {
transform: scaleX(1.4) scaleY(1.6);
opacity: 0;
}
}
<div class="container">
Hello
</div>
You need to define the animation-iteration-count on the pseudo element. It's inheriting the default of running once (which happens on page load).
You can share the key-frames of flickerButton, but need to define infinite on the pseudo element so that it will loop forever on hover. You can do it shorthand on the single animation property, as follows:
.btn:hover::after {
animation: flickerButton 0.4s infinite;
}
I have made a little animation that add a line under the box from the left to the right when it's hovered and the line go back from the left to the right when the mouse isn't hovering the box, but the issue is that the line goes back from the left to the right when I refresh the page. Is there a solution to disable the animation when I open the page or when I refresh it (if possible without JavaScript)
body {
background-color: black;
}
.box {
width: 100px;
height: 100px;
margin: 40px auto;
background-color: #f44336;
position: relative;
}
.box::after {
content: '';
position: absolute;
bottom: -7px;
width: 100%;
height: 3px;
background-color: #fff;
animation: out 400ms linear forwards;
transform-origin: right center;
}
.box:hover::after {
animation: in 400ms linear;
transform-origin: left center;
}
#keyframes in {
from {
transform: scaleX(0);
}
to {
transform: scaleX(1);
}
}
#keyframes out {
from {
transform: scaleX(1);
}
to {
transform: scaleX(0);
}
}
<div class="box"></div>
I changed your animation to a transition instead. Is this what you're after?
body {
background-color: black;
}
.box {
width: 100px;
height: 100px;
margin: 40px auto;
background-color: #f44336;
position: relative;
}
.box::after {
content: '';
position: absolute;
bottom: -7px;
width: 100%;
height: 3px;
background-color: #fff;
transform: scaleX(0);
transform-origin: right center;
transition: transform 400ms linear;
}
.box:hover::after {
transform: scaleX(1);
transform-origin: left center;
}
<div class="box"></div>
I don't believe this is possible using only css - you can use a css declaration when a mouse-over ends, however it will always trigger upon load.
You can however use simple JS using classes "on" and "off" to differentiate 'page load' and 'hover off'.
The code in this instance would be:
demo
$(".box").hover(
function () {
$(this).removeClass('off').addClass('on');
},
function () {
$(this).removeClass('on').addClass('off');
}
);
body {
background-color: black;
}
.box {
width: 200px;
height: 200px;
margin: 40px auto;
background-color: #f44336;
position: relative;
}
.box::after {
content: '';
position: absolute;
bottom: -7px;
height: 3px;
background-color: #fff;
}
.box.off::after {
width: 100%;
animation: out 400ms linear forwards;
transform-origin: right center;
}
.box.on::after {
width: 100%;
animation: in 400ms linear;
transform-origin: left center;
}
#keyframes in {
from {
transform: scaleX(0);
}
to {
transform: scaleX(1);
}
}
#keyframes out {
from {
transform: scaleX(1);
}
to {
transform: scaleX(0);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="box"></div>
I am hoping some of you might have some ideas regarding using Bulma Tiles (https://bulma.io/documentation/layout/tiles/). I am partially successful with getting the flip functionality to work using the input checkbox, but the content inside the tile is flipping, not the entire tile.
/* ==========================================
reference --> https://codepen.io/amazingrando/pen/yjbAh
========================================== */
.tile input[type="checkbox"] {
/*Hiding the checkbox. We never want to see it.*/
position: absolute;
left: -9999em;
}
.flip-tile {
cursor: pointer;
/*Animation elements*/
display: block;
perspective: 600px;
position: relative;
transition: all 0.1s;
&:hover {
transform: scale(1.02, 1.02);
}
}
.flip-tile-front, .flip-tile-back{
//position: absolute; top: 0; left: 0;
//width: inherit; height: inherit; /*Size of the card is set by the container*/
backface-visibility: hidden; /*Makes a card invisible from behind.*/
transform-style: preserve-3d;
transition: all 0.4s ease-in-out;
}
.flip-tile-front {
/*Default rotation values*/
transform: rotateX(0deg) rotateY(0deg);
}
.flip-tile-back {
background: MediumPurple;
visibility: hidden;
/*Default rotation value*/
transform: rotateY(-180deg);
}
/*When the container is clicked the checkbox is marked as checked. This activates the CSS below. */
.tile input[type="checkbox"]:checked {
~ .flip-tile {
//animation: lift 0.4s linear;
.flip-tile-back {
visibility: visible;
transform: rotateX(0deg) rotateY(0deg);
}
.flip-tile-front {
transform: rotateY(180deg);
}
}
}
https://codepen.io/lostcook/pen/QWyvBey
Any ideas or help would greatly be appreciated.
Thanks
I try to animate two blocks with css animation. Its have the same transform animation but one of it has background-color animation also. This animations splitted to two #keyframes.
See code (https://codepen.io/mctep/pen/Rgyaep):
<style>
.a {
position: absolute;
left: 0;
top: 0;
width: 100px;
height: 100px;
background-color: red;
animation: a 1s infinite;
}
.b {
position: absolute;
left: 0;
top: 0;
width: 100px;
height: 100px;
background-color: gray;
animation: b 1s infinite;
}
#keyframes a {
0% {
background-color: red;
transform: translateX(0);
}
50% {
background-color: green;
transform: translateX(100px);
}
100% {
background: red;
}
}
#keyframes b {
0% {
transform: translateX(0);
}
50% {
transform: translateX(100px);
}
}
</style>
<div class="a"></div>
<div class="b"></div>
Animation of colored block is lag from gray block In Google Chrome. In Safary and FF it works perfectly.
I can to make one #keyframes for background and other for transform and it solves problem. But I want to use single value of animation property for single element. If there are no any ways to fix it I'll separate moving and coloring animations.
Why this happens? Is it Google Chrome bug?
Couldn't give you a concrete reason why this happens, but we can un-confuse Chrome by simply specifying a background-color in animation B as well.
#keyframes b {
0% {
background-color: gray; /* add this */
transform: translateX(0);
}
}
.a {
position: absolute;
left: 0;
top: 0;
width: 100px;
height: 100px;
background-color: red;
animation: a 1s infinite;
}
.b {
position: absolute;
left: 0;
top: 0;
width: 100px;
height: 100px;
background-color: gray;
animation: b 1s infinite;
}
#keyframes a {
0% {
background-color: red;
transform: translateX(0);
}
50% {
background-color: green;
transform: translateX(100px);
}
100% {
background: red;
}
}
#keyframes b {
0% {
background-color: gray;
transform: translateX(0);
}
50% {
transform: translateX(100px);
}
}
<div class="a"></div>
<div class="b"></div>