Timothy J
Timothy J

Reputation: 3

How to fade between classes in a conditional query

I'm trying to work out how to fade between css classes triggered by a conditional button click. Instead of a simple class on and class off.

I've adapted the below jsfiddle from this answer to this; mostly working, except for the fade.

     // Check if localStorage is supported
    if ('localStorage' in window && typeof localStorage == 'object') {
      $(document).ready(function() {

        // Set the class if greyscale is set
        // Note that localStorage saves everything as strings
        if (localStorage["darkmode"] == "1") {
          $('html').addClass('dark');
          $('.daytime').addClass('nighttime').removeClass('daytime');
          $("#lightson").val("Turn Lights back on");
        }
        // Register click listener for the button
        $('#lightson').click(function() {
          // Toggle greyscale on and off
          if (localStorage["darkmode"] != "1") {
            $('html').addClass('dark').removeClass('light').fadeIn("fast");
            localStorage["darkmode"] = "1";
            $('.daytime').addClass('nighttime').removeClass('daytime');
            $("#lightson").val("Turn Lights back on");
          } else {
            $('html').removeClass('dark').addClass('light').fadeIn("fast");
            localStorage["darkmode"] = "0";
            $('.nighttime').addClass('daytime').removeClass('nighttime');
            $("#lightson").val("Dark Mode");
          }
        }); // - button click
      }); // - doc ready
    }
html.light {
  background: white;
  color: grey;
}
html.dark {
  background: grey;
  color: white;
}
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus egestas libero lectus, ac elementum est euismod sit amet. Sed maximus ac ipsum non pulvinar. Nulla tempor turpis a metus sollicitudin, in interdum dui mollis. Curabitur dictum magna magna,
  sit amet tempus justo consequat sit amet. Vestibulum varius nisl justo, vel egestas justo scelerisque sit amet. Duis vulputate lacinia lacus id lacinia. Sed vel tellus id nulla finibus pellentesque vel eu sapien. Praesent risus eros, pellentesque in
  tempor a, vestibulum sit amet purus. Mauris sapien velit, varius nec ex eget, vestibulum laoreet diam. Nam eros nisi, euismod ultrices viverra eu, dictum quis nisl. Suspendisse quis eleifend quam. Curabitur consectetur diam non ante rutrum, tincidunt
  placerat felis tincidunt. Fusce vitae dolor dui. Morbi mattis eu dui sit amet laoreet.</div>
<input type="button" id="lightson" class="daytime" value="Dark Mode">

You can see the transition is harsh between dark to light and I would like to fade between them some how. I tried appending: .fadeIn("fast"); to the two 'add and removeClass' lines in the above jsfiddle statements like this: $('html').addClass('dark').removeClass('light').fadeIn("fast");

However that seemed to not do anything at all, and probably for a good reason

I cannot solve the issue with plain css in the stylesheet as I don't want the fade in effect each time the page loads, just when the button is pressed.

Upvotes: 0

Views: 435

Answers (5)

Jordan Burnett
Jordan Burnett

Reputation: 1844

The 'fadeIn' method in jQuery animates the opacity of a hidden element rather than animating between classes.

Have you considered using css transitions?

html {
    background:white;
    color:grey;
    transition: all 0.4s
}
html.dark {
    background: grey;
    color: white;
}

Then the only javascript you need is to toggle the 'dark' class on the html element.

The reason you get the fade in when you load the page, is in your original code you are applying the 'dark' class after the page has loaded, which triggers the animation. If you ensure that the HTML tag doesn't have the 'transition' property until after you've set your initial styles you can avoid this unwanted animation.

Here's an example using your original code. Note the extra line:

document.createElement('div').offsetHeight;

This is needed because some browsers won't apply style changes immediately as they try and optimise the number of times they redraw the layout by queueing changes until they have to. This hack forces the browser to apply your styles immediately as it has to make sure it's giving you the correct value.

Upvotes: 2

Anananasu
Anananasu

Reputation: 80

Since this was downvote-worthy, I'll elaborate.


You can't fade in or out a class. Either you have it, or you don't. What you can do is to transition the styles associated with that class. However, the fadeIn / fadeOut functions are not the way to do that:

The fadeIn() method gradually changes the opacity, for selected elements, from hidden to visible (fading effect).

http://www.w3schools.com/jquery/eff_fadein.asp

Maybe this is more what you're looking for. The pertinent bits being the transition property. Example:

JSFiddle

Summary of changes:

  • Removed the fade in and fade out.
  • Moved the light mode from html.light to html (cleaner markup, and more importantly: no undefined state of neither light nor dark)
  • Added: "transition: all 0.8s;" to both styles

JS

// Check if localStorage is supported
if ('localStorage' in window && typeof localStorage == 'object') {
    $(document).ready(function () {

        // Set the class if greyscale is set
        // Note that localStorage saves everything as strings
        if (localStorage["darkmode"] == "1") {
            $('html').addClass('dark');
            $('.daytime').addClass('nighttime').removeClass('daytime');
            $("#lightson").val("Turn Lights back on");
        }
        // Register click listener for the button
        $('#lightson').click(function () {
            // Toggle greyscale on and off
            if (localStorage["darkmode"] != "1") {
                $('html').addClass('dark');
                localStorage["darkmode"] = "1";
                $('.daytime').addClass('nighttime').removeClass('daytime');
                $("#lightson").val("Turn Lights back on");
            } else {
                $('html').removeClass('dark');
                localStorage["darkmode"] = "0";
                $('.nighttime').addClass('daytime').removeClass('nighttime');
                $("#lightson").val("Dark Mode");
            }
        }); // - button click
    }); // - doc ready
}

CSS

html {
    background:white;
    color:grey;
    transition: all 0.8s;
}
html.dark {
    background: grey;
    color: white;
    transition: all 0.8s;
}

Upvotes: 1

dops
dops

Reputation: 800

You can use jquery-ui and the .switchClass() function

$('html').switchClass('light','dark', 1000, 'linear');

and to change back

$('html').switchClass('dark','light', 1000, 'linear');

.switchClass() Documentation

Alternatively you can use the .toggleClass() and give the body the default light properties, this would be easy for toggling.

.toggleClass() Documentation

You can also use the jquery .animate() function, you would need to specify the css within the function however not the class names.

.animate() Documentation

Upvotes: 2

Bojan Petkovski
Bojan Petkovski

Reputation: 6933

You need jQuery ui to make transitions between classes.

Example here http://jsfiddle.net/v5vw9r3a/6/

$('html').addClass('dark', 1000, "easeOutSine");

Upvotes: 1

Mooseman
Mooseman

Reputation: 18891

I recommend using a CSS3 transition instead of JS animations:

html{
    transition: all 0.5s;
}

Demo: http://jsfiddle.net/v5vw9r3a/4/


However, to answer your asked question, fadeOut the element, and make the class change and fadeIn a callback of it, i.e.:

$html = $('html'); // Don't search for the element so many times -- that is slow
$html.fadeOut("fast",function(){ // fadeOut fast, then:
    $html.addClass('dark').removeClass('light').fadeIn("fast"); // addClass, removeClass, and fadeIn
});

Demo: http://jsfiddle.net/v5vw9r3a/5/

Upvotes: 1

Related Questions