Disable css animation on orientation change - css

So I made two animations for tablet using css animation and media query.
The main thing animation does is animate the div from top to center in tablet portrait and from left to center in tablet landscape.
When the page loads in portrait it animates correctly from top to center. But when the orientation is changed to landscape it starts the second animation from left to center. The same if it is in landscape first.
What I want is to animation to run only once on page load, and not trigger every time orientation changes.
Preferably without javascript, only css.
Here is a bit of code of how it works:
#keyframes leftToCenter {
from {
margin-left: -100vw;
}
to {
margin-left: 0;
}
}
#keyframes topToCenter {
from {
margin-top: -100vh;
}
to {
margin-top: 0;
}
}
#media only screen and (orientation: portrait) {
.div {
animation-name: topToCenter;
animation-duration: 1s;
}
}
#media only screen and (orientation: landscape) {
.div {
animation-name: leftToCenter;
animation-duration: 1s;
}
}
Edit:
The animation must not be done with jQuery, it should be done only with css animation. This is the requirement.
Also, the animation is a bit more complicated, I just put the simplest version of it here.
The main thing is that it runs only on page load, and not on orientation change.

The only way that I can think of to do that in pure CSS involves the use of a single animation.
This way the browser asumes the animation has finished, and won't trigger it again.
In one orientation, we will use half of the animation, beginning at the middle, and ending at the end.
In the other orientation, we will begin also at the middle, but we will execute it in reverse and end at he beginning
#keyframes dual {
from {
margin-left: 0;
}
49.9% {
margin-left: -100vw;
margin-top: 0;
}
50% {
margin-left: 0;
margin-top: -100vh;
}
to {
margin-top: 0;
}
}
#media only screen and (orientation: portrait) {
.element {
animation-name: dual;
animation-duration: 2s;
animation-delay: -1s;
}
}
#media only screen and (orientation: landscape) {
.element {
animation-name: dual;
animation-duration: 2s;
animation-delay: -1s;
animation-direction: reverse;
}
}
.element {
width: 100px;
height: 100px;
background-color: lightblue;
}
<div class="element"></div>

In case anyone's interested, I found another solution to this problem.
You have to move the keyframes declaration inside the media query and give them the same name. That way the right animation still gets triggered when needed, and as they have the same name animation count will increese to 1 after first animation and won't trigger again after orientation change.
#media only screen and (orientation: portrait) {
#keyframes animation{
from {
margin-top: -100vh;
}
to {
margin-top: 0;
}
}
.div {
animation-name: animation;
animation-duration: 1s;
}
}
#media only screen and (orientation: landscape) {
#keyframes animation{
from {
margin-left: -100vw;
}
to {
margin-left: 0;
}
}
.div {
animation-name: animation;
animation-duration: 1s;
}
}

There is probably a CSS way to do it but it is very easy to create your effect using jQuery:
$(document).ready( function(){
$('#yourdiv').show().animate({top:'50%'},1000);
});
Just set #yourdiv's style this way in order to center it when position is absolute:
display: none;
position: absolute;
z-index: 100000; /* on top of all others element */
top: -50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
The effect will occur only when thee page is refreshed.
You can even add an other div called shadow to make it even better looking :)

Related

CSS media query not working properly using elementor

I'm having an issue while coding an animation for an element on an Elementor website.
I created an animation on mobile and one for desktop/tablet.
However only one of the animation works depending on which one is placed at the top.
/* for tablet*/
#media (min-width: 415px) and (max-width: 800px){
.text-aboutus {
background-color: #F1E3D6;
border-radius: 10px
}
}
/* for mobile*/
#media (max-width: 414px){
.text-aboutus-mobile {
background-color: #F1E3D6;
border-radius: 10px;
margin-left: 5% ;
margin-top: 60%;
}
/* animation for mobile */
#media (max-width:414px) {
.text-aboutus-mobile {
background-color: #F1E3D6;
border-radius: 10px;
margin-left: 5% ;
margin-top: 60%;
animation: fade-in-about-us-mobile 1.5s ease-in forwards;
opacity: 0;
transform: translateX(100%);
}
#keyframes fade-in-about-us-mobile {
from {
opacity: 0;
transform: translateX(100%);
}
to {
opacity: 1;
transform: translateX(0%);
}
}
/* animation for desktop/tablet */
#media (min-width:415px) {
.text-aboutus {
animation: fade-in-about-us 2s ease-in forwards;
opacity: 0;
}
#keyframes fade-in-about-us {
from { opacity:0; }
to {opacity: 1; }
}
It can't be a class issue since if I swap the two animation the code works fine for the one been read at the top.
It's probably a media query but I don't know how to fix it.
Any idea on how I should do it?
Thank in advance.
Whenever I run into an unexpected problem with my code, the first thing I do is make sure that all required semicolons and brackets are in place. Media queries are especially tricky because you need 2 curly brackets at the end instead of just one and that's easily overlooked. :)
It should look something like this:
#media only screen and (max-width: 600px) {
.class-name {
color: #fff;
font-size: 12px;
text-decoration: underline;
}
}
I also noticed that you use #media without the "only screen" prefix, which is not an issue per se but you might want to have a look at this thread that explains the difference and when to use what: What is the difference between "screen" and "only screen" in media queries?
Hope this helps!

How to implement CSS animations based on media-query breakpoints being hit?

As part of making our websystem responsive to mobile devices, I'm using CSS media queries to alternate between having a header bar and a hamburger menu.
Now I thought it'd be a nice gimmick if it animated between the two layouts when desktop users adjusted the size of their browser window beyond the bounds defined by the media queries. As a proof-of-concept test I've been experimenting with the transition between our large logo and the small one.
My animations.scss file contains these two animations:
#mixin ToSmallLogo() {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 1s;
animation-name: SwapToSmallLogo;
#keyframes SwapToSmallLogo {
0% {
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
100% {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
}
}
}
#mixin SwapToBigLogo() {
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 1s;
animation-name: SwapToBigLogo;
#keyframes SwapToBigLogo {
0% {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
100% {
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
}
}
Then I've got a SCSS file specifically for the media queries, containing:
#import '../../Variables/Sizes.scss';
#import '../Animations/animations.scss';
#media screen and (max-width: $bigToSmallFISLogo) {
#franklin {
#include ToSmallLogo();
}
}
#media screen and (min-width: $bigToSmallFISLogo){
#franklin{
#include SwapToBigLogo();
}
}
While the CSS before application of the media queries is this:
#franklin {
display: block;
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
background-repeat: no-repeat;
background-size: 100%;
height: 72px;
}
My issue is, while shrinking the screen past the defined size works perfectly, going back up just snaps to the larger image with no animation. I'd thought that the culprit was that I had the image defined in the CSS before application of the media queries, so I removed that part of it; but that just resulted in having no image.
Then while typing this question I had the idea use a media query to determine the direction of the animation, like so:
#mixin SwapLogo() {
/* background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;*/
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 1s;
animation-name: SwapLogo;
#media screen and (max-width: $bigToSmallFISLogo) {
animation-direction: normal;
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
}
#media screen and (min-width: $bigToSmallFISLogo) {
animation-direction: reverse;
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
#keyframes SwapLogo {
0% {
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
100% {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
}
}
}
That resulted in the animation being ran on page load, but not at the resize.
Is there any way to do what I'm looking for?
Option 1 contains some faulty css
You've set the starting to width: 100%; on your SwapToBigLogo
#keyframes SwapToBigLogo {
0% {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
width: 100%; <---- culprit
background-image: url('../../../PageAssets/Fis.png');
}
Essentially, you're animation from width: 100% to width:100%. If you remove that line, it will probably work.
Option 2 tricky with reversing
When you reverse an animation, it will not reset iteration count and progress of the animation.
IE if you 'reverse' an animation at 100% finished. it will just apply the 100% finished of the 'reverse' state. not start from 0% reverse and animate to 100% reversed
see my answer to this question if you want to circumvent that
Alternative, use Transitions instead
If you have no need for complex animations and just want to smoothly transition from one state to another.
I would prefer to use css transitions.
#franklin {
display: block;
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
background-repeat: no-repeat;
background-size: 100%;
height: 72px;
transition: width 2s ease-in; // <--- this will animate when the media query kicks in.
}
#media screen and (max-width: $bigToSmallFISLogo) {
#franklin {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
}
}
#media screen and (min-width: $bigToSmallFISLogo){
#franklin{
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
}
Bonus
You can apply transitions to a * selector. (I would not recommend that for production grade websites, but it's fun to toy with.) It will cause everything to smoothly transition when your media query changes widths/layouts.
* {
transition: all 2s;
}
body {
background-color: red;
color: black;
font-size: 30px;
}
.logo {
width: 200px;
border: 5px solid black;
border-radius: 30px;
padding:20px;
}
/* On screens that are 992px wide or less, the background color is blue */
#media screen and (max-width: 630px) {
body {
background-color: blue;
color: white;
font-size: 20px;
}
.logo {
width: 100px;
border: 3px solid orange;
border-radius: 10px;
padding:10px;
}
}
/* On screens that are 600px wide or less, the background color is olive */
#media screen and (max-width: 400px) {
body {
background-color: lime;
color: white;
font-size: 12px;
}
.logo {
width: 50px;
border: 1px solid indigo;
border-radius: 5px;
padding:2px;
}
}
<h1>Resize window</h1>
<p>
<img class="logo" src="http://placekitten.com/200/300" alt="logo">
</p>
After a lot of experimentation, I've finally sussed it out. Essentially, as Lars pointed out, I'd forgotten to delete a couple of bits; but the solution I ended up with (which seems a bit smoother, as it fades one image into the other) is to have the base CSS as:
#franklin {
display: block;
background-repeat: no-repeat;
background-size: 100%;
height: 72px;
}
Then the mixin to apply the animation as follows:
#mixin SwapLogo($img, $width, $startIMG, $startWidth, $animationName) {
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 1s;
animation-name: $animationName;
background-image: $img;
width: $width;
#keyframes #{$animationName} {
0% {
width: $startWidth;
background-image: $startIMG;
}
100% {
background-image: $img;
width: $width;
}
}
}
With the media queries being:
#media screen and (max-width: calc($bigToSmallFISLogo + 10px)) { //This overlap of 10px basically allows for the animation to take effect as the other animation is removed.
#franklin {
#include SwapLogo(url('../../../../PageAssets/fissmall.png'), 7%, url('../../../../PageAssets/Fis.png'), 100%, LogoGoSmall);
margin-top: 13px;
}
}
#media screen and (min-width: $bigToSmallFISLogo) {
#franklin {
#include SwapLogo(url('../../../../PageAssets/Fis.png'), 100%, url('../../../../PageAssets/fissmall.png'), 7%, LogoGoBig);
}
}
#media screen and (max-width: $minSizeForDesktopMenu) and (min-width: $bigToSmallFISLogo) {
#franklin {
margin-top: 26px;
}
}
#media screen and (min-width: $minSizeForDesktopMenu) {
#franklin {
margin-top: 13px;
}
}

Disable hover in mobile

I have these class, so hen I hover an item it do a transition, the problem is when I´m in mobile view, it exit of browse
.ftContainerOut {
padding-right:10px;
padding-bottom:20px;
transition: all 0.5s ease-in-out;
position: relative;
cursor:pointer;
z-index:1;
}
.ftContainerOut:hover {
transform: scale(1.5);
z-index:10;
}
I'm trying this to disable it on mobile, but it doesn´t work, only in normal view the transition gets stuck
#media screen and (min-width: 600px){
.ftContainerOut:hover {
display: none;
}
}
Help is very appreciated. Regards
First change your media query to max-width and then reset the properties that you want to reset for mobile.
#media screen and (max-width: 600px){
.ftContainerOut:hover {
transform: scale(1);
z-index:1;
}
}
Also if you want to remove transition in mobile you can also add
#media screen and (max-width: 600px){
.ftContainerOut {
transition: none;
}
}
You don't want to use display:none on the :hover, as this will make the div hide on hover, which wont work. Instead I suggest making it do nothing.
On desktop, you transform: scale the item by 1.5, so on mobile transform: scale it by 1, which as it is already 1, it will not change.
Same principle for z-index, on desktop :hover changes it to 10, so on mobile make it "change" to 1, but as it is already 1, again there is no change.
So the CSS would be:
#media screen and (max-width: 600px) {
.ftContainerOut:hover {
transform: scale(1);
z-index: 1;
}
}
Here's a snippet to try it out.
.ftContainerOut {
padding-right: 10px;
padding-bottom: 20px;
transition: all 0.5s ease-in-out;
position: relative;
cursor: pointer;
z-index: 1;
}
.ftContainerOut:hover {
transform: scale(1.5);
z-index: 10;
}
#media screen and (max-width: 600px) {
.ftContainerOut:hover {
transform: scale(1);
z-index: 1;
}
}
<div class="ftContainerOut" style="width: 100px; height: 100px; background: green;"></div>

Defining keyframe animations inside media queries

I'm trying to get objects to "slide in" from the bottom of the screen, but since I can't get the screen height as a unit in CSS, I'm trying to do this with media queries, like so:
#media(max-height:500px) {
#keyframe slideUp {
0% { transform: translate3d(0,500px,0); }
100% { transform: translate3d(0,0,0); }
}
}
#media(max-height:750px) {
#keyframe slideUp {
0% { transform: translate3d(0,750px,0); }
100% { transform: translate3d(0,0,0); }
}
}
/* etc. */
This doesn't work (it uses the first version of slideUp regardless of height), so I assume keyframes, once defined, cannot be overwritten or reassigned based on media queries? Is there any way to achieve this effect (short of having many different keyframe setups and using a media query to assign the appropriate one to the class)?
I don't know why no one else has suggested this, but instead of setting the keyframes in the media query you can set the animation in the media query.
#media(max-height:500px)
{
#selectorGroup {
animation: slideUp500 1s forwards;
}
}
#media(max-height:750px)
{
#selectorGroup {
animation: slideUp750 1s forwards;
}
}
#keyframes slideUp500 {
0% { transform: translate3d(0,500px,0); }
100% { transform: translate3d(0,0,0); }
}
#keyframes slideUp750 {
0% { transform: translate3d(0,750px,0); }
100% { transform: translate3d(0,0,0); }
}
Nowadays you can solve this using native CSS variables.
In your case:
#media(max-height:500px) {
:root {
--slide-up-y: 500px
}
}
#media(max-height:750px) {
:root {
--slide-up-y: 750px
}
}
#keyframes slideUp {
0% { transform: translate3d(0,var(--slide-up-y),0); }
100% { transform: translate3d(0,0,0); }
}
}
A way of doing a slide up animation regardless of screen or element height is to use position: fixed:
.box {
position: fixed;
animation: slideUp 1s forwards;
}
#keyframes slideUp {
from { top: 100%; }
to { top: 0; }
}
Demo: http://jsfiddle.net/myajouri/Kvtd2/
If you want to slide relative to a parent element and not the viewport, use position: absolute instead.
Long time since this question was asked. But I'm seeing that nobody has answered the solution that I'll give you, and this one, in my opinion, is easier than creating different media-queries for different screen sizes.
#myajouri proposed you to use a fixed position and you discarded this solution because you need to use 3d transforms to get hardware acceleration. But you can still use 3d transforms with a fixed position. With CSS transformations, if you use percentages, they will be relative to the size of the element itself. This will allow you to move the element from outside the screen no matter what size it has, so, only one keyframe animation is needed. Check the next snippet:
body {
margin: 0;
padding: 0;
}
.element {
animation: slideUp 1s ease-in-out infinite alternate;
background: #CCC;
border: 5px solid gray;
box-sizing: border-box;
height: 100%;
position: fixed;
width: 100%;
}
#keyframes slideUp {
from {
transform: translate3d(0, 100%, 0);
}
to {
transform: translate3d(0, 0, 0);
}
}
<div class="element" />
If you have to use translate3d to get hardware acceleration on mobile devices (as you mentioned), and given that you can't use at-rules inside #media:
You could define one #keyframes with large translateX (say 5000px) and change the animation-duration based on the screen height to ensure the speed is more or less the same across the different heights.
I would also define height ranges (max-height and min-height) as opposed to upper limits (max-height only) to prevent unwanted style overrides.
#keyframes slideUp {
from { transform: translate3d(0,5000px,0); }
to { transform: translate3d(0,0,0); }
}
.box { animation: slideUp 5s forwards; }
#media (min-height: 0) and (max-height: 500px) {
.box { animation-duration: 0.5s; }
}
#media (min-height: 501px) and (max-height: 750px) {
.box { animation-duration: 0.75s; }
}
#media (min-height: 751px) and (max-height: 1000px) {
.box { animation-duration: 1s; }
}
DEMO: http://jsfiddle.net/myajouri/9xLyf/

Combining semi transparency of background image with keyframe animation

I would like to add a continuous fading effect in the background image of my wrapper. I know you can use keyframe animation to make a background image move arround, however, i was wondering if there is a fade effect possible using this technique.
http://css-tricks.com/snippets/css/webkit-keyframe-animation-syntax/
For example:
#-webkit-keyframes fontbulger {
0% {
font-size: 10px;
}
30% {
font-size: 15px;
}
100% {
font-size: 12px;
}
Would be in my perfect situation something like...
#-webkit-keyframes fontbulger {
0% {
background: url(image.png, 1);
}
30% {
background: url(image.png, 0.5);
}
100% {
background: url(image.png, 1);
}
...for which 0.5 would be a visibility of 50%. Ofcourse, this suggestion does not work. Any way to accomplish this? I know you can apply transparency to RGB value's, but I would like to apply it to an image.
I am not aware of any way currently to directly affect the opacity of the background image as you seek. Two possible workarounds are:
1. Pure CSS3 way (not well supported yet)
Using a pseudo-element to supply the background-image allowed opacity to be used and keep the whole thing as pure css, but it did not work on webkit (which apparently does not support animation on pseudo-elements), only on the moz extension (I could not test IE10... feedback on that would be helpful). Compare Firefox with Chrome for this fiddle, which used this code:
HTML
<div class="bkgAnimate">Foreground text</div>
CSS
.bkgAnimate {
width: 300px; /*only for demo*/
height: 200px; /*only for demo*/
position: relative;
z-index: 1; /* make a local stacking context */
}
.bkgAnimate:after {
content: '';
position: absolute;
top:0;
right: 0;
bottom: 0;
left: 0;
background: url(src="your/image/path/file.png") no-repeat;
z-index: -1;
-webkit-animation: fontbulger 3s infinite;
-moz-animation: fontbulger 3s infinite;
-ms-animation: fontbulger 3s infinite;
}
#-webkit-keyframes fontbulger {
0% { opacity: 1; }
30% { opacity: 0.5; }
100% { opacity: 1; }
}
#-moz-keyframes fontbulger {
0% { opacity: 1; }
30% { opacity: 0.5; }
100% { opacity: 1; }
}
#-ms-keyframes fontbulger {
0% { opacity: 1; }
30% { opacity: 0.5; }
100% { opacity: 1; }
}
2. Cluttered HMTL solution (more cross browser friendly)
Changing to put an actual img tag in as the background seemed to be the only way to get webkit to behave, as this fiddle shows. But that may not be desirable for you. Code similar to above except:
HTML
<div class="bkgAnimate">Foreground text
<img class="bkg" src="your/image/path/file.png"/>
</div>
CSS change from above
Change the :after selector to .bkgAnimate .bkg and remove the content and background property from that code.

Resources