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!
Related
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;
}
}
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>
I've got a CSS keyframe animation set up to happen on :hover of a specific icon that is used as a favorite button. It works just fine on desktop, but the animation keyframe that's set up for the :hover state won't stop on mobile device touch. How do I get it to stop for mobile or not engage in mobile?
Here's a link to the codepen:
http://codepen.io/mapk/pen/ZOQqaQ
HTML:
<div class="fav-btn">
<span href="" class="favme dashicons dashicons-heart"></span>
</div>
CSS:
.fav-btn {
display:flex;
height: 100%;
justify-content: center;
align-items: center;
}
#keyframes favme-anime {
0% {
opacity: 1;
font-size: ms(0);
-webkit-text-stroke-color: transparent;
}
25% {
opacity:.6;
color: #FFF;
font-size: ms(-2);
-webkit-text-stroke-width: 1px;
-webkit-text-stroke-color: #DC3232;
}
75% {
opacity:.6;
color: #FFF;
font-size: ms(3);
-webkit-text-stroke-width: 1px;
-webkit-text-stroke-color: #DC3232;
}
100% {
opacity: 1;
font-size: ms(2);
-webkit-text-stroke-color: transparent;
}
}
#keyframes favme-hover {
from {
font-size: ms(3);
}
80% {
font-size: ms(2);
}
}
.favme {
display:block;
font-size: ms(2);
width: auto;
height: auto;
cursor: pointer;
box-shadow: none;
transition: all .2s ease;
color: #CBCDCE;
margin: 0;
&.active {
color: #DC3232;
}
&:hover {
animation: favme-hover .3s infinite alternate;
}
&.is_animating {
animation: favme-anime .3s;
}
}
jQuery:
// Favorite Button - Heart
$('.favme').click(function() {
$(this).toggleClass('active');
});
/* when a user clicks, toggle the 'is-animating' class */
$(".favme").on('click touchstart', function(){
$(this).toggleClass('is_animating');
});
/*when the animation is over, remove the class*/
$(".favme").on('animationend', function(){
$(this).toggleClass('is_animating');
});
If yout touch the button on a touch screen, it will stay in a hover state untill you touch anywhere else, therefore the animation will not end.
You can try detecting mobile devices with javascript and for example set a no-hover class to the button and in css put :not('no-hover') before :hover:
&:not('no-hover'):hover {
animation: favme-hover .3s infinite alternate;
}
I don't use javascript phone detection so try asking google, there are many possibilities like http://detectmobilebrowsers.com/, https://www.abeautifulsite.net/detecting-mobile-devices-with-javascript/ or many others.
Or use media queries to detect smaller devices and wrapp the &:hover{some_style}:
#media (min-width: 600px) {
&:hover {
animation: favme-hover .3s infinite alternate;
}
}
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 :)
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/