A guide on incorporating CSS animations triggered by reaching specific media-query breakpoints

In order to make our website responsive to mobile devices, I am utilizing CSS media queries to switch between a header bar and a hamburger menu.

I had the idea of adding a subtle animation when desktop users resize their browser window beyond the defined media query bounds. As a trial run, I have been testing the transition between our large logo and the smaller version.

Within my animations.scss file, you will find 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');
        }
    }
}

Furthermore, I have a specific SCSS file 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();
    }
}

Before applying the media queries, the CSS code is as follows:

#franklin {
    display: block;
    width: 100%;
    background-image: url('../../../PageAssets/Fis.png');
    background-repeat: no-repeat;
    background-size: 100%;
    height: 72px;
}

The issue I'm facing is that while shrinking the screen works smoothly, going back up snaps to the larger image without any animation. I initially thought the problem lay in having the image defined in the CSS before the media queries were applied, so I removed it; however, this resulted in no image being displayed.

During the process of writing this question, I came up with an idea to use a media query to control the direction of the animation:

@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%;
        }
    }
}

While this method resulted in the animation running on page load, it did not function during resizing. Is there a way to achieve what I'm aiming for?

Answer №1

Issue with Option 1's CSS

The problem lies in setting the initial width to width: 100%; for your SwapToBigLogo

@keyframes SwapToBigLogo {
    0% {
        background-image: url('../../../../PageAssets/fissmall.png');
        width: 7%;
        width: 100%; <---- problematic line
        background-image: url('../../../PageAssets/Fis.png');
    }

Essentially, you're transitioning from width: 100% to width:100%. Removing that line should resolve the issue.

Cautions When Reversing in Option 2

Reversing an animation won't reset the iteration count and progress of the animation.
For instance, 'reversing' an animation at 100% completion will simply apply the finished state of the 'reverse' state without starting from 0%. Check out the answer to this question if you need a workaround.

Consider Using Transitions Instead

If you don't require complex animations and prefer smooth transitions between states,
using CSS transitions would be a better choice.

#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; // <--- animates when media query triggers.
}

@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');
    }
}

Extra Tip

You can apply transitions to a * selector. This may not be recommended for production websites, but it can be interesting to experiment with. It will smoothly transition everything when your media query alters 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;
}


/* Background turns blue on screens ≤992px wide */

@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;
  }
}


/* Background changes to olive on screens ≤600px wide */

@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>

Answer №2

Through extensive trial and error, I have finally figured it out. It turns out that, as Lars pointed out, I had overlooked deleting a few components. However, the solution I came up with (which creates a smoother transition by fading one image into another) involves setting the base CSS as:

#franklin {
    display: block;
    background-repeat: no-repeat;
    background-size: 100%;
    height: 72px;
}

The mixin to implement the animation is 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;
        }
    }
}

The media queries are set up like this:

@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;
    }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

jQuery not displaying Div elements as expected

After experimenting with the Coverflow technique and adapting it to work with a div, I have encountered a slight issue. Below is the HTML code I am using: <html> <head> <meta http-equiv="Content-type" content="text/html; ...

Creating a web page with CSS that completely fills the screen and includes a lengthy list within the design

I am looking to create a webpage that takes up the entire browser window. However, I also need to display a long list on this page that requires a scrollbar for navigation. Currently, with my existing HTML code, the list is causing the page to stretch in ...

Tips on adjusting text size based on the browser window dimensions

There seems to be an issue with the text when the window size is decreased. It overlaps with the image instead of resizing accordingly. I have tried using media queries, VW, and VH units to adjust the text size based on the window size but it's not wo ...

Retrieve the current width and height of an image after the maximum width and height constraints have been applied

Check out this example The HTML: <div class="container"> <img src="http://placehold.it/500x500" alt="500x500" /> </div> <div class="container"> <img src="http://placehold.it/100x500" alt="100x500" /> </div> < ...

Tips for implementing `overflow-x: hidden` on a `ValueContainer` when using `isMulti` in react-select V2

I'm currently grappling with finding a solution to have a react-select V2 component, configured as isMulti, hide selected values that exceed the width of the ValueContainer rather than breaking to a new line and expanding the component's height. ...

Can an element in React be styled using the ID alone, without relying on className?

I'm in the process of transitioning an outdated website to React, and I'd prefer not to overhaul all the existing CSS files that have already been written. Many elements currently have their styles defined using an id. Is there a workaround to ma ...

Is Chrome not correctly using 100% viewport width (vw)?

I've been attempting to recreate the functionality of this codepen, and I've encountered an issue with the vw declaration in Chrome. Despite setting GalleryGrid to 100vw, it doesn't display correctly in Chrome, while Firefox and Safari work ...

"Concealing a section of my website with PHP: A step-by-step guide

On our website, there is a member database with access levels assigned to each member. We are looking to create a functionality where if the member's access level is greater than or equal to 10, a specific CSS class will become visible. Conversely, if ...

JavaScript code for displaying div elements

How can I use script code to show different divs when a button is clicked? This is my current progress: ''' <head> <style> #div-1, #div-2, #div-3{ display: none; width: 100%; padding: ...

Bootstrap 4 fails to adapt on mobile devices, causing columns to pile on top of each other

My website is optimized for desktop viewing, but I'm struggling to make it responsive on mobile using bootstrap 4. Even though my custom columns have always worked in the past, they are now overlapping on top of each other instead of stacking correct ...

Avoid having the content below become pushed down by a collapsed navbar

I am utilizing Bootstrap 4.1 My current structure is as follows: <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhkt ...

Rearrange element's placement using Jquery Drag & Drop

I am experiencing difficulties in positioning my elements after a drop event. Within my "list" of divs... In order to keep the divs together and update the list, I utilize jQuery's append function to move the element from the list to its designated ...

Detecting a click outside of a div or its opening button and closing the element using Vanilla JS

When dealing with two buttons, one opens a form, and the other a dropdown. The goal is to have both elements close when clicking outside. The dropdown functionality already works as expected because it closes whenever the user clicks outside the opening b ...

What could be causing my grid to malfunction once the media query is triggered?

I am in the process of creating a straightforward navigation bar. My goal is to have the <nav> content, which includes the navigation links, positioned inside the header along with the logo (a random image from unsplash.it). To achieve this layout, I ...

Embed a unique custom design sheet within a Facebook iframe

I'm looking to customize the design of my Facebook feed by adding a custom style sheet inside a Facebook iframe. Here's what I have: <iframe width="1000px" height="1000px" frameborder="0" name="f1e348592ed856c" allowtransparency="true" allo ...

Error with Gmail displaying incorrect font

I've been struggling to change the font of my emails to Open Sans, especially with Gmail not rendering the correct font. However, I found a workaround for Outlook. Here is what I have: body { @font-face { font-family: 'O ...

Fixed top bar and navigation menu, with a body that can be scrolled

My current goal is to achieve the following layout: <div style="position:absolute; background-color:Transparent; left:0px; right:0px; height:100px; z-index:2;"> <div style="background-color:Silver; width:1000px; height:100px; margin:0 auto;"& ...

Creating an inline list with icons aligned using Bootstrap4

I have a list where some words span two lines, but the second line jumps under the icons at the bottom. How can I keep both lines next to the icon? I'm using Bootstrap and chose to use the list-inline class. Maybe using columns for this list would wor ...

As I scroll, the background color of my body vanishes

Seeking assistance with a CSS issue. I have set the height property of my body to 100%, which works well when all content is visible on screen. However, when I need to scroll due to window size changes, the body color disappears and only the HTML backgro ...

Ensure that the image remains positioned at the bottom of the page

Although it may seem like a repetitive question, the answers I have come across are quite unbelievable. Why would multiple lines of code be needed for such a simple task? It just doesn't make sense. I specifically want to ensure that the img is locat ...