multiple css animations per element doesn't work in Chrome - javascript

I'm trying to animate .circle element. It should grow and then shrink after second. So I declared 2 css animations for one element. In Firefox it works great, but in Chrome it doesn't.
Can-i-use shows that animations css rule in Chrome should work too.
Codepen example
Full source code:
*,
*::before,
*::after {
box-sizing: border-box;
}
#keyframes one {
100% {
width: 5000px;
height: 5000px;
}
}
#keyframes two {
100% {
width: 0px;
height: 0px;
}
}
.container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background-color: lightsalmon;
}
.circle {
position: absolute;
height: 0px;
width: 0px;
border-radius: 50%;
background-color: lightgreen;
/** If declare only one animation, then it will work in Chrome */
animation: one ease 1s alternate 1 paused, two ease 1s alternate 1 paused;
animation-fill-mode: forwards;
}
<div class="container">
<div class="circle"></div>
</div>
<script>
var circle = document.querySelector(".circle");
circle.style.animationPlayState = "running, paused";
setTimeout(() => {
circle.style.animationPlayState = "paused, running";
}, 1000);
</script>

So as one of the comments says, you can do this with a single animation. You should always try to use semantic, meaningful names when coding so I named the animation grow-shrink rather than just one.
*,
::before,
::after {
box-sizing: border-box;
}
#keyframes grow-shrink {
50% {
width: 5000px;
height: 5000px;
}
}
.container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background-color: lightsalmon;
}
.circle {
position: absolute;
height: 0;
width: 0;
border-radius: 50%;
background-color: lightgreen;
animation: grow-shrink 2s;
}
You don't need any of the JavaScript to do this and you don't need the z-index property on .circle. I changed your animation-duration to be 2s rather than 1s since it is doing the work of both 1s animations you had initially. The animation-timing-function initial value is already ease, so I removed that because it is redundant. You also didn't need the alternate value.
If you meant the 1 after alternate in your animation value as the the value for animation-iteration-count then that can be safely removed as that property's initial value is already 1. If you meant it as a 1s delay for the grow animation to start and then another 1s delay for the shrink to start and simply forgot the units then you will have to let me know and I will show you how to modify it to do that. You can easily add the 1s delay for the animation start back in there, but delaying the shrinking would have to be done differently if you use this solution.
Here you can see the Codepen of it working.
🚧 EDIT: Solution #2 🚧
Alternately, if you want to see how to get this done using your method (though I wouldn't recommend it for this particular animation), here is the CSS code after I got your example to work in Chrome (and all other major browsers):
*,
*::before,
*::after {
box-sizing: border-box;
}
#keyframes grow {
0% {
height: 0;
width: 0;
}
100% {
height: 5000px;
width: 5000px;
}
}
#keyframes shrink {
0% {
height: 5000px;
width: 5000px;
}
100% {
height: 0;
width: 0;
}
}
.container {
align-items: center;
background-color: lightsalmon;
display: flex;
height: 100%;
justify-content: center;
left: 0;
position: fixed;
top: 0;
width: 100%;
}
.circle {
animation:
grow 1s ease-in forwards paused,
shrink 1s ease-out 1s forwards paused;
background-color: lightgreen;
border-radius: 50%;
height: 0;
position: absolute;
width: 0;
}
Go here to see the CodePen of solution #2 working.

Related

loop an image in CSS animation

I am trying to make an animation in javascript, where as the character is running, the grond should move as well. The problem that I have is that the ground image has an animation, but the image gets cut, and reapear.
I have this piece of code in css
.ground {
position: absolute;
bottom:0;
width: 100%;
height: 100px;
animation: ground-animation 20s infinite linear;
}
#keyframes ground-animation {
from {
right: -80px;
}
to {
right: 100%;
}
}
Just double the width of ground and repeat background image. No?
https://codepen.io/ildar-meyker/pen/eYrdZyw
body {
margin: 0;
padding: 0;
overflow: hidden;
}
.ground {
position: absolute;
left: 0;
bottom: 0;
width: 200%;
height: 100vh;
animation: ground-animation 20s infinite linear;
background: url(https://i.pinimg.com/originals/8f/1a/b8/8f1ab8b14a55720d6859620a6f596933.jpg) repeat-x 0 100%;
background-size: 50% auto;
}
#keyframes ground-animation {
from {
}
to {
transform: translateX(-50%);
}

How to animate image from fixed size to fullscreen?

There is a website page which height and width are equal to 100% of the browser viewport (100vw and 100vh).
There is a high quality image (3000x2857px) inside of absolutely positioned wrapper in the center of the page. Image wrapper has max-width in pixels (e.g. 300px).
Also, the image has an overlay. I add .active class to the image wrapper by clicking on overlay. This class makes max-width of image wrapper equal to 100vw.
So, I want to animate this. I added transition to max-width, top, transform properties, but it's laggy. I know that it's due to top and max-width properties because of heavy calculations of the browser. But I don't know how to do it in other ways.
Any help would be welcome!
P.S. While I wrote this question, I found that this implementation is buggy in Safari. I think transform transition doesn't work in this browser, so it will be great if you suggest code that work in it :(
Demo: https://codepen.io/ghettojezuz/pen/ExvGwJB
const imageWrapper = document.getElementById("image-wrapper");
const overlay = document.getElementById("overlay");
function toggleImageWrapper() {
if (imageWrapper.classList.contains('active')) {
imageWrapper.classList.remove('active');
} else {
imageWrapper.classList.add('active');
}
}
overlay.addEventListener("click", () => {
toggleImageWrapper();
})
body {
min-height: 100vh;
overflow-x: hidden;
}
img {
width: 100%;
height: auto;
}
.wrapper {
width: 100vw;
min-height: 100vh;
height: 100%;
}
.image-wrapper {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
max-width: 300px;
width: 100%;
transition: max-width .8s ease, top .8s ease, transform .8s ease;
}
.image-wrapper.active {
max-width: 100vw;
left: 50%;
top: 0;
transform: translate(-50%, 0);
}
.image-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: transparent;
opacity: .7;
transition: background-color .3s ease;
cursor: pointer;
}
.image-overlay:hover {
background-color: #000000;
}
<div class="wrapper">
<div class="image-wrapper" id="image-wrapper">
<img src="https://via.placeholder.com/3000x2857.webp" alt="">
<div class="image-overlay" id="overlay"></div>
</div>
</div>
One method which seems to react to transitioning well is to alter the scale rather than try to reposition and alter width etc.
This snippet keeps the image centered and calculates the scale needed to move from the initial width to 100vw.
Note: it removes margin on elements to ensure the full width of the viewport is covered.
const imageWrapper = document.querySelector('.image-wrapper');
const overlay = document.querySelector('.image-overlay');
function toggleImageWrapper() {
if (imageWrapper.classList.contains('active')) {
imageWrapper.classList.remove('active');
} else {
imageWrapper.classList.add('active');
}
}
overlay.addEventListener("click", () => {
toggleImageWrapper();
})
function init() {
const w = window.innerWidth;
const scale = w / imageWrapper.offsetWidth;
imageWrapper.style.setProperty('--scale', scale);
}
window.onload = init;
window.onresize = init;
* {
padding: 0;
margin: 0;
}
body {
min-height: 100vh;
overflow-x: hidden;
}
img {
width: 100%;
height: auto;
}
.wrapper {
width: 100vw;
min-height: 100vh;
height: 100%;
}
.image-wrapper {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
max-width: 300px;
width: 100%;
transition: .8s ease;
}
.image-wrapper.active {
transform: translate(-50%, -50%) scale(var(--scale));
}
.image-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: transparent;
opacity: .7;
transition: scale .3s ease;
cursor: pointer;
}
.image-overlay:hover {
background-color: #000000;
}
<div class="wrapper">
<div class="image-wrapper" id="image-wrapper">
<img src="https://via.placeholder.com/3000x2857.webp" alt="">
<div class="image-overlay" id="overlay"></div>
</div>
</div>
So, I tried multiple things like different css properties, #keyframes animations etc. None of them worked. But I found out that when the image format is SVG, the freezing disappears. I know, not all images can be converted to SVG, but see what you can do about it.
I change the top and transform with flex, now when you click only width changes, but i guess the lag will happen sometime in transform animation case
const imageWrapper = document.getElementById("image-wrapper");
const overlay = document.getElementById("overlay");
function toggleImageWrapper() {
if (imageWrapper.classList.contains('active')) {
imageWrapper.classList.remove('active');
} else {
imageWrapper.classList.add('active');
}
}
overlay.addEventListener("click", () => {
toggleImageWrapper();
})
body {
min-height: 100vh;
overflow-x: hidden;
}
img {
width: 100%;
height: auto;
}
.img_container {
max-width:300px;
transition: .5s;
position:relative;
}
.wrapper {
width: 100vw;
min-height: 100vh;
height: 100%;
}
.image-wrapper {
position: absolute;
left: 0;
top: 0;
bottom:0;
right:0;
display:flex;
align-items:center;
justify-content:center;
width: 100%;
transition: .5s;
}
.image-wrapper.active .img_container {
max-width: 100vw;
}
.image-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: transparent;
opacity: .7;
transition: background-color .3s ease;
cursor: pointer;
}
.image-overlay:hover {
background-color: #000000;
}
<div class="wrapper">
<div class="image-wrapper" id="image-wrapper">
<div class="img_container">
<img src="https://via.placeholder.com/3000x2857.webp" alt="">
<div class="image-overlay" id="overlay"></div>
</div>
</div>
</div>

CSS Transition on newly created psuedo element

I want to create a fade effect on a pseudo element but am having difficulty as i cannot use javascript on this element.
I have an example of something similar to what i am trying to do here but i cannot get the element to fade in as transitions do not seem to work when the element is created.
https://codepen.io/anon/pen/wrxPXJ
.hoverhere.dim::before {
content: '\A';
position: absolute;
width: 100%;
height:100%;
top:0;
left:0;
background:rgba(0,0,0,0.8);
opacity: 1;
transition: opacity 1s;
}
I am adding a class to a div so that the pseudo element is created after matching with the above css however cannot work out how to animate this.
I can probably get it to work without psuedo elements like below:
https://codepen.io/anon/pen/Oxwzvv
However was wondering if there is a way without changing my markup to include an empty div.
I guess you're saying you want this?
$('.hoverhere')
.mouseenter(function() { $(this).addClass('dim'); })
.mouseleave(function() { $(this).removeClass('dim'); });
.hoverhere {
width: 100%;
height: 40px;
background: red;
color: white;
text-align: center;
}
.hoverhere::before {
content: '\A';
position: absolute;
width: 20%;
height: 100%;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.8);
opacity: 0;
visibility: hidden;
transition: all 1s ease-out;
}
.hoverhere.dim::before {
opacity: 1;
visibility: visible;
transition: opacity 1s ease-out;
}
<script src="https://code.jquery.com/jquery-2.2.4.js"></script>
<p>RANDOM TEXT HERE</p>
<div class="hoverhere">HOVER ON ME</div>
<p>MORE RANDOM TEXT HERE</p>
What it needed was to have a starting point established for the opacity.
If this is just for hovering, you don't need the JS at all.
.hoverhere {
width: 100%;
height: 40px;
background: red;
color: white;
text-align: center;
}
.hoverhere::before {
content: '\A';
position: absolute;
width: 20%;
height: 100%;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.8);
opacity: 0;
visibility: hidden;
transition: all 1s ease-out;
}
.hoverhere:hover::before {
opacity: 1;
visibility: visible;
transition: opacity 1s ease-out;
}
<p>RANDOM TEXT HERE</p>
<div class="hoverhere">HOVER ON ME</div>
<p>MORE RANDOM TEXT HERE</p>

CSS Transition Width Right to Left

I am have made a heading (the word Welcome) that reveals itself once the page has loaded (onload="").
Fiddle in case the code below doesn't work.
function animate() {
document.getElementById("mainText").style.width = "100%";
}
#mainText {
margin: 0px;
display: inline-block;
font-size: 100px;
width: 0%;
transition: width 2s;
white-space: nowrap;
overflow: hidden;
text-overflow: clip;
}
<body onload="animate()">
<h1 id="mainText">Welcome</h1>
</body>
The CSS and Plain JS work fine but I want the word "Welcome" to be revealed right side first and then moving along, so from the e to the W, instead of how it currently is, which opens left to right.
I have tried text align: right;, but this doesn't change anything.
I preferably don't want to use any jQuery, if the solution is a JS one.
An example of what the desired look should be, half way though the transition:
You can use the clip-path property to clip parts of the element so they are not visible. This property can also be animated to reveal the element again, using the forwards keyword in the animation so it stays in it's 'revealed' end state.
The inset takes values that are in order: from-top, from-right, from-bottom, from-left.
#text {
margin: 0;
font-size: 100px;
animation: reveal 2s forwards;
}
#keyframes reveal {
from {
clip-path: inset(0 0 0 100%);
}
to {
clip-path: inset(0 0 0 0);
}
}
<h1 id="text">Welcome</h1>
Yes, it is possible using Transitions and Positions:
window.onload = function () {
document.querySelector("h1").classList.add("active");
};
h1 {
overflow: hidden;
display: inline-block;
position: relative;
}
h1 .mask {
position: absolute;
transition: all 0.5s linear;
left: 0;
top: 0;
bottom: 0;
right: 0;
background-color: #fff;
}
h1.active .mask {
right: 100%;
}
<h1><span class="mask"></span>Welcome</h1>
I just wrote an article about this - CSS Transitions & JavaScript for Animated Entry Effects. Hope it is useful... :)
One option is transform: translate with a pseudo element, and no extra element needed.
function animate() {
document.getElementById("mainText").classList.add('show');
}
#mainText {
position: relative;
margin: 0px;
display: inline-block;
font-size: 100px;
white-space: nowrap;
text-overflow: clip;
overflow: hidden;
}
#mainText::after {
content: '';
position: absolute;
left: 0; top: 0;
width: 100%; height: 100%;
background: white;
transition: transform 2s;
}
#mainText.show::after {
transform: translateX(-100%);
}
<body onload="animate()">
<h1 id="mainText">Welcome</h1>
</body>
Another option, an even better solution, using the pseudo with direction and left/width.
This one work in the same way clip-path does, completely transparent against its background, as opposite to having a mask that revels the text, and with much better browser support.
function animate() {
document.getElementById("mainText").classList.add('show');
}
body {
background: black;
}
#mainText {
position: relative;
margin: 0px;
display: inline-block;
font-size: 100px;
white-space: nowrap;
color: rgba(0, 0, 0, 0);
}
#mainText::before {
content: attr(data-text);
position: absolute;
left: 100%;
top: 0;
width: 0;
height: 100%;
color: white;
direction: rtl;
overflow: hidden;
transition: left 2s, width 2s;
}
#mainText.show::before {
left: 0;
width: 100%;
}
<body onload="animate()">
<h1 id="mainText" data-text="Welcome">Welcome</h1>
</body>
Something like this
function animate() {
document.getElementById("overlay").style.width = "0%";
}
#mainText {
margin: 0px;
display: inline-block;
font-size: 100px;
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: clip;
}
#overlay{
width: 100%;
position:absolute;
top:0;
left:0;
background:#fff;
transition: width 2s;
height:100%;
}
<body onload="animate()">
<h1 id="mainText">Welcome</h1>
<div id="overlay"></div>
</body>
This will require a pseudo-element with a background on top of your heading serving as a mask. Instead of altering the inline styles I will simply add a class is-active. So everything style related can be styled via CSS.
function animate() {
document.getElementById("mainText").className = "is-active";
}
#mainText {
margin: 0px;
display: inline-block;
position: relative;
font-size: 100px;
white-space: nowrap;
overflow: hidden;
text-overflow: clip;
}
#mainText:before {
content: '';
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 100%;
background: #FFF;
transition: width 2s;
}
#mainText.is-active:before {
width: 0%;
}
<body onload="animate()">
<h1 id="mainText">Welcome</h1>
</body>
I use Transform: translateX to achieve the desired effect.
It slides the text sideways or horizontally on the X axis.
.message {
color: darkred;
font-size: 30px;
display: inline-block;
font-weight: 100;
font-family: sans-serif;
}
.sliding-text-1,
.sliding-text-2,
.sliding-text-3 {
animation-name: slide;
animation-duration: 1s;
animation-timing-function: ease-out;
animation-iteration-count: 1;
animation-fill-mode: forwards;
opacity: 0;
}
.sliding-text-2 {
animation-delay: 2s;
color: darkblue;
}
.sliding-text-3 {
animation-delay: 4s;
color: darkgreen;
}
#keyframes slide {
from {
transform: translateX(200px);
}
to {
transform: translateX(0px);
opacity: 1;
}
}
<h1 class="message sliding-text-1">Hello!</h1>
<h1 class="message sliding-text-2">Thanks for visiting!</h1>
<h1 class="message sliding-text-3">Have a nice day!</h1>

Define area to animate on hover and move all page content

I need a "special" animation and i am not finding how i will get this sort of animation i seek for, on each triangle should make the same animation, one to the left and one to the right, i need the right way to start making this. Do i use JQuery for this ?
The animation: I want the triangles to move more or less to the middle of screen in order to show the content that is hidden, as it happens here: beepi.com/default.aspx on the circles
I currently have this:
#anim {
z-index: 1;
position: relative;
height: 100%;
min-height: 100%;
background-image: url("http://i.imgur.com/EPM2arR.jpg");
background-image: no-repeat;
background-size: 100%;
}
#anim img {
z-index: 2;
position: relative;
height: 100%;
width: 100%;
}
.arrow-left {
text-align: left;
padding: 1.5% 12px;
text-transform: uppercase;
position: absolute;
width: 13%;
left: 0;
z-index: 3;
top: 40%;
}
.arrow-right {
text-align: right;
padding: 1.5% 15px;
text-transform: uppercase;
position: absolute;
width: 13%;
right: 0;
z-index: 3;
top: 40%;
}
.arrow-right h2 {
font-size: 28px;
color: #FFF;
}
.arrow-left h2 {
font-size: 28px;
color: #FFF;
}
<section id="anim">
<img src="http://i.imgur.com/AeCYNqc.png">
<div class="arrow-right">
<h2>Scouting For Companies</h2>
</div>
<div class="arrow-left">
<h2>Seeking For Ideas</h2>
</div>
</section>
The animation should be like this:
If I understood well, you need css animation. You can use something like this:
/* For right side */
.arrow-right{
animation: aniright 3s ease;
animation-fill-mode: forwards;
}
#keyframes aniright {
from { right: 0; }
to { right: 13%; }
}
/* For left side */
.arrow-left{
animation: anileft 3s ease;
animation-fill-mode: forwards;
}
#keyframes anileft {
from { left: 0; }
to { left: 13% }
}
I believe you will need to cut and put arrows from image in .arrow-left and .arrow-right classes together will all other elements you want to slide in.. and also put some action to call animation. For e.g:
.arrow-left:hover{
animation: anileft 3s ease;
animation-fill-mode: forwards;
}
... will start animation when your cursor goes over .arrow-left element.

Categories