Biggztyle
Biggztyle

Reputation: 111

Nav menu with transition logo on scroll

I am trying to get a logo to change state on scroll. (example: www.digitalblb.com)

How it should work; 1. Big Logo is originally shown - on scroll changes to 2. Mini Logo - has spinning transition effect of 360'

header.html

<div class="navbar-header">
    <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
    </button>
<%= link_to image_tag("biglogo-160x80.png", alt: "BigLogo"), root_url,class:"menu__biglogo" %>
<%= link_to image_tag("minilogo.png", alt: "MiniLogo"), root_url, class:"menu__minilogo" %>
</div>

CSS /* LOGO FOR TRANSITION*/

.menu__minilogo{
    opacity: 1;
    visibility: visible;
    margin-left: 60px;
    -webkit-transform: rotate(360deg);
    -moz-transform: rotate(360deg);
    -o-transform: rotate(360deg);
    transform: rotate(360deg);
}

.menu__biglogo{
    width: 220px;
    overflow: hidden;
}

JS

$(document).ready(function(){
  var logo = $(".navbar-header");
  logo.find(".menu__minilogo").hide();
  $(window).scroll(function() { // check if scroll event happened
    if ($(document).scrollTop() > 50) { // check if user scrolled more than 50 from top of the browser window
      $(".navbar").css("background-color", "#fff"); // if yes, then change the color of class "navbar-fixed-top" to white (#f8f8f8)
      $(".nav a").css('color', '#0a4f6f');
      logo.find(".menu__biglogo").hide();
      logo.find(".menu__minilogo").show();

      console.log(logo.find(".menu__biglogo"))
    } else {
      $(".navbar").css("background-color", "transparent"); // if not, change it back to transparent
      $(".nav a").css('color', 'white');
      logo.find(".menu__minilogo").hide();
      logo.find(".menu__biglogo").show();

    }
  });
});

Current state. The big logo is shown and on scroll the mini logo appears but without any spinning transition.

Sometimes the logos are load stacked above each other randomly when clicking about the website, but on refresh of that page it reverts to the big logo again (so this is just a little bug on loading).

Any help will be greatly appreciated. Thanks

Upvotes: 2

Views: 2292

Answers (1)

tao
tao

Reputation: 90048

You are using jQuery's .show() and .hide() functions to show/hide your logos. That works, but what they actually do is toggle the display property of your logos from block to none and vice-versa.

The problem with display is that it's not animatable. There cannot be a transition between display:none and display:block. It's on or off.

So here what you could do:

  • have both your logos displayed at all times
  • code the initial state of their animation
  • code the final state of their animation when they would have a custom class (usually active - but you could use any class, as long as it doesn't conflict with anything).
  • all the properties you want to animate on them should be animatable (w3schools is a great resource in this regard)
    • the most important being opacity, as it will control the visibility of your logos.
  • load the page with the big logo having the class active and the small one without.
  • on scroll/click/mouse-flip-flop/whatever-event toggle the class ('active') on both the logos, removing from one and adding on the other. Because they have animatable properties and a transition set for those animations, they will animate nicely.

Here's an example:

$(document).ready(function(){
  var navbar = $(".navbar-header");
  $(window).scroll(function() {
    if ($(document).scrollTop() > 50) { 
      $(".navbar").css("background-color", "#fff"); 
      $(".nav a").css('color', '#0a4f6f');
      
      navbar.find(".menu__biglogo").removeClass('active');
      navbar.find(".menu__minilogo").addClass('active');

    } else {
      $(".navbar").css("background-color", "transparent");
      $(".nav a").css('color', 'white');
      navbar.find(".menu__biglogo").addClass('active');
      navbar.find(".menu__minilogo").removeClass('active');

    }
  });
});
.navbar-header {
  position: fixed;
}

.menu__minilogo{
    width: 200px;
    height: auto;
    position: absolute;
    opacity: 0;
    margin-left: 0;
    transform: rotate(0deg);
    transition: all .6s cubic-bezier(.4,0,.2,1);
}
.menu__minilogo.active {
  width: 60px;
  margin-left: 60px;
  opacity: 1;
  transform: rotate(360deg);
}

.menu__biglogo{
    width: 220px;
    height: auto;
    opacity: 0;
    transition: opacity .6s cubic-bezier(.4,0,.2,1);
}
.menu__biglogo.active {
  opacity: 1;
  transition: opacity .3s cubic-bezier(.4,0,.2,1) .3s;
}

body {
  min-height: 200vh;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="navbar-header">
    <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
    </button>
  <img src="http://lorempixel.com/g/400/400/fashion" class="menu__minilogo" />
  <img src="http://lorempixel.com/g/400/400/fashion" class="menu__biglogo active" />
</div>

I didn't load Bootstrap in it, but I assume you got that part covered.
Side note: If your big and small logos are the same image, there's no point in having both of them. You could just resize/rotate the big one into the small position and back, only animating it's transform properties, not the opacity.

Upvotes: 4

Related Questions