flexbox animation keyframes on Safari - css

Why flex keyframes doesn't work in Safari? In other browsers, all works fine.
<div class="a">
<div class="b"></div>
</div>
.a {
height: 200px;
display: flex;
}
.b {
flex:0 1 50%;
border: 20px solid red;
animation: anim-b 1s infinite;
}
#keyframes anim-b {
0% { flex:0 1 0%; }
100% { flex:0 1 100%; }
}

Animations can be picky (buggy) when one mix longhand and shorthand properties.
In this case Safari also has a bug when animating flex-basis, which I just noticed is still not fixed in ver. 11.
https://github.com/DrummerHead/safari-flex-basis-animation-bug
In this case, for the default row direction, you need to use width instead.
Stack snippet
.a {
height: 200px;
display: flex;
}
.b {
flex:0 1 auto;
width: 50%;
border: 20px solid red;
animation: anim-b 1s infinite;
}
#keyframes anim-b {
0% { width: 0%; }
100% { width: 100%; }
}
<div class="a">
<div class="b"></div>
</div>

Related

Growing "blast" of light animation from center of page

Using CSS I'd like to animate a radial-gradient circle to expand the full length and width of the page (to fully white) and then reverse this animation (return to original state). This should look like a gradual "blast" of white from the center and fade to fully white once reaching full width/height, however my white background starts transitioning too early. How do I achieve this?
scss
.container {
display: flex;
justify-content: center;
flex-direction: column;
text-align: center;
background: black;
height: 100vh;
}
.flash-container {
animation: grow 5s 2s linear forwards;
width: 20px;
height: 20px;
z-index: 4;
#flash {
background: radial-gradient(circle, white, transparent 10%);
width: 100%;
height: 100%;
position: absolute;
border-radius: 100%;
}
}
#keyframes grow {
to {
transform: scale(1000);
background: white;
}
}
html
<div class="container">
<div class="flash-container">
<div class="flash"></div>
</div>
</div>
Jsfiddle: https://jsfiddle.net/zv3bmw8j/2/
I updated your CSS to use the box-shadow method as I quoted above. This would need more tweaks to do as it was being built on a hover method. Just change the percentage value from 0% - 100% and you should be solid. I also made a change to the HTML format and removed the inner flash div.
https://jsfiddle.net/q9n6adLp/
.flash-container {
animation: grow 5s 2s linear forwards;
width: 20px;
height: 20px;
z-index: 4;
margin: 0 auto;
box-shadow: 0 0 30vw 40vw rgba(241,244,0,1);
.flash {
background: radial-gradient(circle, white, transparent 10%);
width: 100%;
height: 100%;
position: absolute;
border-radius: 100%;
}
}

CSS animation of object-position in Safari 12

Displaying image with object-fit and object-position works in browsers that support them, but in Safari 12, animating the object-position property to create a moving effect doesn't appear to do anything (same with using CSS transitions).
Is this a bug? or am I missing something?
I made a simple box and image to demo: https://codepen.io/Taruckus/pen/zyoGNX
<html>
<head>
</head>
<body>
<div class="wrap"><img src="https://via.placeholder.com/500x2000" alt=""></div>
</body>
</html>
<style>
.wrap {
width: 400px;
height: 400px;
position: relative;
}
.wrap img {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
object-position: 50% 0%;
animation: move 5s ease 1 normal forwards;
animation-delay: 0.2s;
}
#keyframes move {
0% {
object-position: 50% 30%;
}
100% {
object-position: 50% 60%;
}
}
</style>
Consider animating transform property. It would be more performant and cross-browser.
Run the snippet below:
.wrap {
width: 400px;
height: 400px;
overflow: hidden;
}
.wrap img {
width: 100%;
transform: translateY(-20%);
animation: move 5s forwards .2s;
}
#keyframes move {
100% {
transform: translateY(-45%);
}
}
<div class="wrap">
<img src="https://via.placeholder.com/500x2000" alt="">
</div>

CSS - How to reverse the Animation on removal

I have a page in my website where I display to panels, side by side. I'm displaying these 2 panels in 2 views: Horizontal and Vertical. I have a button that switches between these 2 views. I'm trying to add some CSS animation on the transition between the two views. However my animation work only in one direction (from Vertical to Horizontal), the reverse animation appear in the wrong order.
var isVertical = false;
var boxes = $(".box");
function toggleViews()
{
isVertical = !isVertical;
if (isVertical)
{
boxes.addClass("vertical-box");
}
else
{
boxes.removeClass("vertical-box");
}
}
.container
{
display: block;
width: 400px;
height: 150px;
border: 2px solid black;
overflow: hidden;
}
.box
{
-webkit-transition-property: width, height;
-webkit-transition-duration: 2s, 2s;
-webkit-transition-delay: 0s, 2s;
-webkit-transition-timing-function: ease;
display: inline-block;
width: 50%;
height: 100%;
}
.vertical-box
{
width: 100%;
height: 50%;
}
.a { background-color: darkred; }
.b { background-color: darkorchid; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
<button onclick="toggleViews()">toggle</button>
<div class="container">
<div class="a box">A</div><div class="b box">B</div>
</div>
</body>
</html>
var isVertical = false;
var boxes = $(".box");
function toggleViews()
{
isVertical = !isVertical;
if (isVertical)
{
boxes.addClass("vertical-box");
}
else
{
boxes.removeClass("vertical-box");
}
}
.container
{
display: block;
width: 400px;
height: 150px;
border: 2px solid black;
overflow: hidden;
}
.box
{
-webkit-transition-property: height, width; /* swapped */
-webkit-transition-duration: 0.5s, 0.5s;
-webkit-transition-delay: 0s, 0.5s;
-webkit-transition-timing-function: ease;
display: block; /* TRY THIS */
float: left; /* AND THIS */
width: 50%;
height: 100%;
}
.vertical-box
{
-webkit-transition-property: width, height; /* added */
width: 100%;
height: 50%;
}
.a { background-color: darkred; }
.b { background-color: darkorchid; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
<button onclick="toggleViews()">toggle</button>
<div class="container">
<div class="a box">A</div><div class="b box">B</div>
</div>
</body>
</html>
Explained
Added transition-property: width, height; to .vertical-box
Desired behavior: expand width, shink height; expand height shrink width.
.box has transition-property first height then width
.vertical-box overwrites and flippes transition-property: first width, then height
You might think this is the wrong order, but as soon as you click the class is applied immideately, but the transition takes time. So you transition from .box to .vertical-box with the transition-property of .vertical-box and vise versa.
EDIT Answer using animation (little hacky, since i found no way to reset current keyframe)
var isVertical = false;
var boxes = $(".box");
function toggleViews()
{
isVertical = !isVertical;
if (isVertical)
{
boxes.removeClass("vertical-box-reverse");
window.requestAnimationFrame(function() { // apply to forget animation state
window.requestAnimationFrame(function() { // re-apply animation
boxes.addClass("vertical-box");
});
});
}
else
{
boxes.removeClass("vertical-box");
window.requestAnimationFrame(function() { // apply to forget animation state
boxes.addClass("vertical-box-before-reverse"); // apply to set animation end-like state
window.requestAnimationFrame(function() { // re-apply animation
boxes.removeClass("vertical-box-before-reverse");
boxes.addClass("vertical-box-reverse");
});
});
}
}
.container
{
display: block;
width: 400px;
height: 150px;
border: 2px solid black;
overflow: hidden;
}
.box
{
display: block;
float: left;
width: 50%;
height: 100%;
}
.a.vertical-box { animation: boxAnimationA 1s normal forwards; }
.b.vertical-box { animation: boxAnimationB 1s normal forwards; }
.a.vertical-box-reverse { animation: boxAnimationA 1s ease-in reverse forwards; }
.b.vertical-box-reverse { animation: boxAnimationB 1s ease-in reverse forwards; }
.vertical-box-before-reverse { width: 100%; height: 50%; }
.a { background-color: darkred; }
.b { background-color: darkorchid; }
/* Keyframes */
#keyframes boxAnimationA {
0% { width: 50%; }
50% { width: 100%; height: 100%; }
100% { width: 100%; height: 50%; }
}
#keyframes boxAnimationB {
0% { width: 50%; }
50% { width: 0%; height: 100%; }
51% { width: 100%; height: 100%; }
100% { width: 100%; height: 50%; }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
<button onclick="toggleViews()">toggle</button>
<div class="container">
<div class="a box">A</div><div class="b box">B</div>
</div>
</body>
</html>

Fullscreen infinite scrolling background

I'm trying to implement a full-screen infinite scrolling background effect, which must extend on the entire height and width of the viewport.
Here's the demo.
The solution I've tried was to take a wrapper element that has 100vh and 100vw of the viewport, then place 2 divs inside it, 100% of its height, that have the same background-image and background-size: cover property. The size of the image I've used is: 1,920px × 808px.
Then I've applied the following animation on the wrapper element:
#keyframes infiniteScrollBg {
0% {
transform: translateY(0%);
}
100%{
transform: translateY(-100%);
}
}
But the problem is that on some viewport sizes, the images are not repeating correctly (because of background-size: cover property):
.
Here's the full code I've tried:
<div class="animated-scene">
<div class="animated-scene__frame animated-scene__frame-1"></div>
<div class="animated-scene__frame animated-scene__frame-2"></div>
</div>
And the css:
.animated-scene {
width: 100vw;
height: 100vh;
position: fixed;
min-height: 400px;
animation: infiniteScrollBg 50s linear infinite;
}
.animated-scene__frame {
width: 100%;
height: 100%;
background-size: cover;
background-color: #4277a3;
background-image: url('https://andreivictor.ro/codepen/fullscreen-infinite-scroll-bg/fullscreen-bg');
}
Do you have any idea on how could I implement this effect?
Thanks for your help.
For scrolling background, I used background-position instead of using additional element and animate it using transform css properties.
Why you might asked?
Pattern will be seamlessly stitched by the browsers
cleaner HTML code. We just need one element to do this.
The only const doing this method is you need to know the dimension of image you are using.
Example :
/*
specify the scroll x (or y) with the width (or height) of the images
In this case, the image dimension is :
width: 1920px;
height: 808px;
*/
#keyframes bgScroll {
0% {
background-position : 0px 0px
}
100% {
background-position : 0px -808px
}
}
.scrollingBG {
display:block;
width:100vw;
height:100vh;
background-image:url("https://andreivictor.ro/codepen/fullscreen-infinite-scroll-bg/fullscreen-bg.jpg");
animation: bgScroll 20s linear infinite;
}
<div class='scrollingBG'></div>
I have used an image element just to use the auto height of it.
Then I use a backgroiund on a pseudo that gives the ability to repeat itself as many times as needed
I have set 2 different containers with different aspect ratios to more easily check the result on different screens
.container {
border: solid 1px black;
overflow: hidden;
position: absolute;
}
#ctn1 {
width: 300px;
height: 150px;
}
#ctn2 {
width: 200px;
height: 350px;
left: 320px;
}
.inner {
width: 100%;
position: relative;
animation: scroll 5s infinite linear;
}
.inner:after {
content: "";
height: 500%;
width: 100%;
position: absolute;
background-image: url(https://i.stack.imgur.com/FlK9o.jpg);
background-size: 100% 20%;
}
.img {
width: 100%;
}
#keyframes scroll {
from {transform: translateY(-100%);}
to {transform: translateY(-200%);}
}
<div class="container" id="ctn1">
<div class="inner">
<img class="img" src="https://i.stack.imgur.com/FlK9o.jpg">
</div>
</div>
<div class="container" id="ctn2">
<div class="inner">
<img class="img" src="https://i.stack.imgur.com/FlK9o.jpg">
</div>
</div>
A better solution with media query used to change the way the image is used.
Notice that background-size: cover is needed when both the aspect ratio of the image and the window is unknown. Since you know the aspect ratio of your image, you can control the display with a media query based on it.
Now, when it's needed, the image will adapt not to the width of the container, but to the height of it
#media screen and (max-aspect-ratio: 4/3) {
.inner {
height: 100%;
width: auto !important;
}
.img {
height: 100%;
width: auto !important;
}
}
.container {
border: solid 1px black;
display: inline-block;
overflow: hidden;
}
#ctn1 {
width: 300px;
height: 150px;
}
#ctn2 {
width: 200px;
height: 350px;
}
.inner {
width: 100%;
position: relative;
animation: scroll 5s infinite linear;
display: inline-block;
}
.inner:after {
content: "";
height: 500%;
width: 100%;
left: 0px;
position: absolute;
background-image: url(https://i.stack.imgur.com/FlK9o.jpg);
background-size: 100% 20%;
}
.img {
width: 100%;
}
#keyframes scroll {
from {transform: translateY(-100%);}
to {transform: translateY(-200%);}
}
<div class="container" id="ctn1">
<div class="inner">
<img class="img" src="https://i.stack.imgur.com/FlK9o.jpg">
</div>
</div>
<div class="container" id="ctn2">
<div class="inner">
<img class="img" src="https://i.stack.imgur.com/FlK9o.jpg">
</div>
</div>
The issue is with aspect ratio. You're setting the aspect ratio to the view window, and not the image size. So your image ends up getting cut off at the view window aspect.
I worked around in your codepen by changing .animated-scene__frame to this:
.animated-scene__frame {
width: 100%;
height:200vh; //easy way - increase height in animated div to prevent image cutoff. Ideally should be done through javascript using like a 3x multiple of the height of the image. Then just rely on background-repeat during the animation :)
background-size:contain;
background-color: #4277a3;
background-image: url('https://andreivictor.ro/codepen/fullscreen-infinite-scroll-bg/fullscreen-bg-slide1.jpg');
}
I would recommend to just extend the picture 3 times, with:
#keyframes infiniteScrollBg {
0% {
transform: translateY(0%);
}
100%{
transform: translateY(-66.66%);
}
}
Use some image editor and create a large image with the same pattern, take a look of this site that I made site, there you will find some infinite background pattern
You must use background-position property.
Here's fixed example http://codepen.io/azamat7g/pen/BRwRVV
Full code:
#keyframes infiniteScrollBg {
0% {
transform: translateY(0%);
}
100%{
transform: translateY(-100%);
}
}
.animated-scene {
width: 100vw;
height: 100vh;
position: fixed;
min-height: 400px;
animation: infiniteScrollBg 50s linear infinite;
}
.animated-scene__frame {
width: 100%;
height: 100%;
background-size: cover;
background-position: bottom left;
background-color: #4277a3;
background-image: url('https://andreivictor.ro/codepen/fullscreen-infinite-scroll-bg/fullscreen-bg-slide1.jpg');
}
.bottom{
background-position: top left;
}
<div class="animated-scene">
<div class="animated-scene__frame animated-scene__frame-1"></div>
<div class="animated-scene__frame animated-scene__frame-2 bottom"></div>
</div>

CSS Animation: how to trigger the reverse animation?

I'm trying to create a simple reusable CSS class so I can have this animation everywhere.
Everything works fine except that I can't find any example/documentation on how to trigger the reverse animation.
Here is my HTML:
<div class="cards">
<div class="card">
<div class="frontpage">
<img src="http://lorempixel.com/400/200/"/>
</div>
<div class="rearpage">
<img src="http://lorempixel.com/g/400/200/"/>
</div>
</div>
<div class="card">
<div class="frontpage">
<img src="http://lorempixel.com/400/200/"/>
</div>
<div class="rearpage">
<img src="http://lorempixel.com/g/400/200/"/>
</div>
</div>
</div>
My animation is a "card-flip"-like animation using a simple toggleClass in Javascript to trigger the animation:
$('.card').click(function(){
$(this).toggleClass('opened');
});
And here is my CSS:
.cards {
width: 800px;
margin: auto;
}
.card {
width: 200px;
height: 100px;
position: relative;
display: inline-block;
margin: 10px;
}
.card .frontpage, .card .rearpage {
width: 100%;
height: 100%;
overflow: hidden;
position: absolute;
}
.card .rearpage {
width: 0%;
}
.card .frontpage img, .card .rearpage img {
width: 100%;
height: 100%;
}
/***** ANIMATIONS *****/
/* ANIMATION 1 */
.card .frontpage {
-webkit-animation-duration: 1s;
-webkit-animation-direction: alternate;
-webkit-animation-timing-function: ease-in;
-webkit-animation-fill-mode: forwards;
}
.card.opened .frontpage {
-webkit-animation-name: frontToRear;
}
#-webkit-keyframes frontToRear {
0% { width: 100%; }
50% { width: 0%; margin-left: 50%; }
100% { width: 0%; }
}
/* ANIMATION 2 */
.card .rearpage {
-webkit-animation-duration: 1s;
-webkit-animation-direction: alternate;
-webkit-animation-timing-function: ease-in;
-webkit-animation-fill-mode: forwards;
}
.card.opened .rearpage {
-webkit-animation-name: rearToFront;
}
#-webkit-keyframes rearToFront {
0% { width: 0%; }
50% { width: 0%; margin-left: 50%; }
100% { width: 100%; }
}
What is the smart way of doing this? I wish I could just put some trigger on my .rearcard to trigger the reversed animation but I can't find any way of doing this.
I know I could just write 2 other "reversed" animations and apply them but it seems so dumb that I can't try to do better.
I set up a jsfiddle to help you analyze and test out: http://jsfiddle.net/9yp3U/
Your approach with margin and width to fake a rotation is very interesting, but you can do this much more simply with rotateY
.cards {
width: 800px;
margin:auto;
-webkit-perspective:1000;
}
.card {
width: 200px;
height: 100px;
position: relative;
display: inline-block;
margin: 10px;
-webkit-transition: 1s ease-in;
-webkit-transform-style: preserve-3d;
-webkit-transform:translateZ(1px);
}
.card .frontpage, .card .rearpage, img {
width: 100%;
height: 100%;
position: absolute;
top:0;
left:0;
-webkit-transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
}
.card img {
width: 100%;
height: 100%;
}
.card .rearpage,
.card.opened {
-webkit-transform:rotateY(180deg);
}
Demo
As for the question you asked, you can play animations backwards by using the animation-direction:backwards property, though with CSS toggling animations is hard. Thus, I'd recommend you use a transition instead since it's only a change between two states.
And FYI just in case, CSS selector don't always have to be in the parent child format. In your case applying just .child will do the same. The parent child selector is only necessary when needing to a higher selector specificity than existing properties.
Oh, and also FYI, jQuery isn't needed for this. I included an (untested) javascript equivalent if you want. If this is the only place where you're using jQuery on your page I'd recommend not using it because loading the whole jQuery library takes some time and data.

Resources