CSS styles not applying immediately when class toggled with jQuery












2















I am trying to change the style of an element while some javascript is running in the background, to indicate that the page is 'busy' or 'loading'. I've been attempting to do this by toggling a class on at the start of the JS script with jQuery's .toggleClass(), and toggling it off at the end, with some suitable CSS styling attached to the class.



Although the class is toggled immediately, the CSS styling attached to it doesn't apply until after the JS has finished executing, however. So if the class is toggled both on and off, the user does not see any change in style.



I've included a simple example below. How can I force the change in CSS styling to apply immediately, before the rest of the JS code executes?






$(function() {
$('#box').click(function() {

// Toggle class 'red' on.
$(this).toggleClass('red');

// Do something that takes time.
for (i = 0; i < 10000; i++) {
console.log(i);
}

// Toggle class 'red' off.
$(this).toggleClass('red');
});
});

.wrapper {
margin: 15px;
text-align: center;
color: #000;
}

#box {
margin: 15px 0;
width: 100px;
height: 100px;
line-height: 100px;
cursor: pointer;
background: #ccc;
border: solid 3px #ccc;
-webkit-transition: all .3s linear 0s;
transition: all .3s linear 0s;
}

#box.red {
background: #f43059;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<div id="box">Click me.</div>
</div>












share|improve this question



























    2















    I am trying to change the style of an element while some javascript is running in the background, to indicate that the page is 'busy' or 'loading'. I've been attempting to do this by toggling a class on at the start of the JS script with jQuery's .toggleClass(), and toggling it off at the end, with some suitable CSS styling attached to the class.



    Although the class is toggled immediately, the CSS styling attached to it doesn't apply until after the JS has finished executing, however. So if the class is toggled both on and off, the user does not see any change in style.



    I've included a simple example below. How can I force the change in CSS styling to apply immediately, before the rest of the JS code executes?






    $(function() {
    $('#box').click(function() {

    // Toggle class 'red' on.
    $(this).toggleClass('red');

    // Do something that takes time.
    for (i = 0; i < 10000; i++) {
    console.log(i);
    }

    // Toggle class 'red' off.
    $(this).toggleClass('red');
    });
    });

    .wrapper {
    margin: 15px;
    text-align: center;
    color: #000;
    }

    #box {
    margin: 15px 0;
    width: 100px;
    height: 100px;
    line-height: 100px;
    cursor: pointer;
    background: #ccc;
    border: solid 3px #ccc;
    -webkit-transition: all .3s linear 0s;
    transition: all .3s linear 0s;
    }

    #box.red {
    background: #f43059;
    }

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="wrapper">
    <div id="box">Click me.</div>
    </div>












    share|improve this question

























      2












      2








      2








      I am trying to change the style of an element while some javascript is running in the background, to indicate that the page is 'busy' or 'loading'. I've been attempting to do this by toggling a class on at the start of the JS script with jQuery's .toggleClass(), and toggling it off at the end, with some suitable CSS styling attached to the class.



      Although the class is toggled immediately, the CSS styling attached to it doesn't apply until after the JS has finished executing, however. So if the class is toggled both on and off, the user does not see any change in style.



      I've included a simple example below. How can I force the change in CSS styling to apply immediately, before the rest of the JS code executes?






      $(function() {
      $('#box').click(function() {

      // Toggle class 'red' on.
      $(this).toggleClass('red');

      // Do something that takes time.
      for (i = 0; i < 10000; i++) {
      console.log(i);
      }

      // Toggle class 'red' off.
      $(this).toggleClass('red');
      });
      });

      .wrapper {
      margin: 15px;
      text-align: center;
      color: #000;
      }

      #box {
      margin: 15px 0;
      width: 100px;
      height: 100px;
      line-height: 100px;
      cursor: pointer;
      background: #ccc;
      border: solid 3px #ccc;
      -webkit-transition: all .3s linear 0s;
      transition: all .3s linear 0s;
      }

      #box.red {
      background: #f43059;
      }

      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      <div class="wrapper">
      <div id="box">Click me.</div>
      </div>












      share|improve this question














      I am trying to change the style of an element while some javascript is running in the background, to indicate that the page is 'busy' or 'loading'. I've been attempting to do this by toggling a class on at the start of the JS script with jQuery's .toggleClass(), and toggling it off at the end, with some suitable CSS styling attached to the class.



      Although the class is toggled immediately, the CSS styling attached to it doesn't apply until after the JS has finished executing, however. So if the class is toggled both on and off, the user does not see any change in style.



      I've included a simple example below. How can I force the change in CSS styling to apply immediately, before the rest of the JS code executes?






      $(function() {
      $('#box').click(function() {

      // Toggle class 'red' on.
      $(this).toggleClass('red');

      // Do something that takes time.
      for (i = 0; i < 10000; i++) {
      console.log(i);
      }

      // Toggle class 'red' off.
      $(this).toggleClass('red');
      });
      });

      .wrapper {
      margin: 15px;
      text-align: center;
      color: #000;
      }

      #box {
      margin: 15px 0;
      width: 100px;
      height: 100px;
      line-height: 100px;
      cursor: pointer;
      background: #ccc;
      border: solid 3px #ccc;
      -webkit-transition: all .3s linear 0s;
      transition: all .3s linear 0s;
      }

      #box.red {
      background: #f43059;
      }

      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      <div class="wrapper">
      <div id="box">Click me.</div>
      </div>








      $(function() {
      $('#box').click(function() {

      // Toggle class 'red' on.
      $(this).toggleClass('red');

      // Do something that takes time.
      for (i = 0; i < 10000; i++) {
      console.log(i);
      }

      // Toggle class 'red' off.
      $(this).toggleClass('red');
      });
      });

      .wrapper {
      margin: 15px;
      text-align: center;
      color: #000;
      }

      #box {
      margin: 15px 0;
      width: 100px;
      height: 100px;
      line-height: 100px;
      cursor: pointer;
      background: #ccc;
      border: solid 3px #ccc;
      -webkit-transition: all .3s linear 0s;
      transition: all .3s linear 0s;
      }

      #box.red {
      background: #f43059;
      }

      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      <div class="wrapper">
      <div id="box">Click me.</div>
      </div>





      $(function() {
      $('#box').click(function() {

      // Toggle class 'red' on.
      $(this).toggleClass('red');

      // Do something that takes time.
      for (i = 0; i < 10000; i++) {
      console.log(i);
      }

      // Toggle class 'red' off.
      $(this).toggleClass('red');
      });
      });

      .wrapper {
      margin: 15px;
      text-align: center;
      color: #000;
      }

      #box {
      margin: 15px 0;
      width: 100px;
      height: 100px;
      line-height: 100px;
      cursor: pointer;
      background: #ccc;
      border: solid 3px #ccc;
      -webkit-transition: all .3s linear 0s;
      transition: all .3s linear 0s;
      }

      #box.red {
      background: #f43059;
      }

      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      <div class="wrapper">
      <div id="box">Click me.</div>
      </div>






      javascript jquery html css






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jan 1 at 3:37









      Luke ThorburnLuke Thorburn

      2441316




      2441316
























          1 Answer
          1






          active

          oldest

          votes


















          1














          The problem is that your "something that takes time" is synchronous and blocking - while it's operating, browser repainting will be disabled.



          One option would be to listen to a transitionend event, to ensure that the animation to red completes before the resource-intensive operation runs.



          So that the removal of .red animates properly too, you could set a setTimeout right after the heavy operations finish. Note that your code will a bit be clearer if you use addClass and removeClass instead of toggleClass:






          $('#box').click(function() {
          $(this).one('transitionend', () => {
          // Do something that takes time.
          for (i = 0; i < 1000; i++) {
          console.log(i);
          }
          // Toggle class 'red' off.
          setTimeout(() => {
          $(this).removeClass('red');
          });
          });
          $(this).addClass('red');
          });

          .wrapper {
          margin: 15px;
          text-align: center;
          color: #000;
          }

          #box {
          margin: 15px 0;
          width: 100px;
          height: 100px;
          line-height: 100px;
          cursor: pointer;
          background: #ccc;
          border: solid 3px #ccc;
          -webkit-transition: all .3s linear 0s;
          transition: all .3s linear 0s;
          }

          #box.red {
          background: #f43059;
          }

          <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
          <div class="wrapper">
          <div id="box">Click me.</div>
          </div>








          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53992871%2fcss-styles-not-applying-immediately-when-class-toggled-with-jquery%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            1














            The problem is that your "something that takes time" is synchronous and blocking - while it's operating, browser repainting will be disabled.



            One option would be to listen to a transitionend event, to ensure that the animation to red completes before the resource-intensive operation runs.



            So that the removal of .red animates properly too, you could set a setTimeout right after the heavy operations finish. Note that your code will a bit be clearer if you use addClass and removeClass instead of toggleClass:






            $('#box').click(function() {
            $(this).one('transitionend', () => {
            // Do something that takes time.
            for (i = 0; i < 1000; i++) {
            console.log(i);
            }
            // Toggle class 'red' off.
            setTimeout(() => {
            $(this).removeClass('red');
            });
            });
            $(this).addClass('red');
            });

            .wrapper {
            margin: 15px;
            text-align: center;
            color: #000;
            }

            #box {
            margin: 15px 0;
            width: 100px;
            height: 100px;
            line-height: 100px;
            cursor: pointer;
            background: #ccc;
            border: solid 3px #ccc;
            -webkit-transition: all .3s linear 0s;
            transition: all .3s linear 0s;
            }

            #box.red {
            background: #f43059;
            }

            <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
            <div class="wrapper">
            <div id="box">Click me.</div>
            </div>








            share|improve this answer




























              1














              The problem is that your "something that takes time" is synchronous and blocking - while it's operating, browser repainting will be disabled.



              One option would be to listen to a transitionend event, to ensure that the animation to red completes before the resource-intensive operation runs.



              So that the removal of .red animates properly too, you could set a setTimeout right after the heavy operations finish. Note that your code will a bit be clearer if you use addClass and removeClass instead of toggleClass:






              $('#box').click(function() {
              $(this).one('transitionend', () => {
              // Do something that takes time.
              for (i = 0; i < 1000; i++) {
              console.log(i);
              }
              // Toggle class 'red' off.
              setTimeout(() => {
              $(this).removeClass('red');
              });
              });
              $(this).addClass('red');
              });

              .wrapper {
              margin: 15px;
              text-align: center;
              color: #000;
              }

              #box {
              margin: 15px 0;
              width: 100px;
              height: 100px;
              line-height: 100px;
              cursor: pointer;
              background: #ccc;
              border: solid 3px #ccc;
              -webkit-transition: all .3s linear 0s;
              transition: all .3s linear 0s;
              }

              #box.red {
              background: #f43059;
              }

              <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
              <div class="wrapper">
              <div id="box">Click me.</div>
              </div>








              share|improve this answer


























                1












                1








                1







                The problem is that your "something that takes time" is synchronous and blocking - while it's operating, browser repainting will be disabled.



                One option would be to listen to a transitionend event, to ensure that the animation to red completes before the resource-intensive operation runs.



                So that the removal of .red animates properly too, you could set a setTimeout right after the heavy operations finish. Note that your code will a bit be clearer if you use addClass and removeClass instead of toggleClass:






                $('#box').click(function() {
                $(this).one('transitionend', () => {
                // Do something that takes time.
                for (i = 0; i < 1000; i++) {
                console.log(i);
                }
                // Toggle class 'red' off.
                setTimeout(() => {
                $(this).removeClass('red');
                });
                });
                $(this).addClass('red');
                });

                .wrapper {
                margin: 15px;
                text-align: center;
                color: #000;
                }

                #box {
                margin: 15px 0;
                width: 100px;
                height: 100px;
                line-height: 100px;
                cursor: pointer;
                background: #ccc;
                border: solid 3px #ccc;
                -webkit-transition: all .3s linear 0s;
                transition: all .3s linear 0s;
                }

                #box.red {
                background: #f43059;
                }

                <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
                <div class="wrapper">
                <div id="box">Click me.</div>
                </div>








                share|improve this answer













                The problem is that your "something that takes time" is synchronous and blocking - while it's operating, browser repainting will be disabled.



                One option would be to listen to a transitionend event, to ensure that the animation to red completes before the resource-intensive operation runs.



                So that the removal of .red animates properly too, you could set a setTimeout right after the heavy operations finish. Note that your code will a bit be clearer if you use addClass and removeClass instead of toggleClass:






                $('#box').click(function() {
                $(this).one('transitionend', () => {
                // Do something that takes time.
                for (i = 0; i < 1000; i++) {
                console.log(i);
                }
                // Toggle class 'red' off.
                setTimeout(() => {
                $(this).removeClass('red');
                });
                });
                $(this).addClass('red');
                });

                .wrapper {
                margin: 15px;
                text-align: center;
                color: #000;
                }

                #box {
                margin: 15px 0;
                width: 100px;
                height: 100px;
                line-height: 100px;
                cursor: pointer;
                background: #ccc;
                border: solid 3px #ccc;
                -webkit-transition: all .3s linear 0s;
                transition: all .3s linear 0s;
                }

                #box.red {
                background: #f43059;
                }

                <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
                <div class="wrapper">
                <div id="box">Click me.</div>
                </div>








                $('#box').click(function() {
                $(this).one('transitionend', () => {
                // Do something that takes time.
                for (i = 0; i < 1000; i++) {
                console.log(i);
                }
                // Toggle class 'red' off.
                setTimeout(() => {
                $(this).removeClass('red');
                });
                });
                $(this).addClass('red');
                });

                .wrapper {
                margin: 15px;
                text-align: center;
                color: #000;
                }

                #box {
                margin: 15px 0;
                width: 100px;
                height: 100px;
                line-height: 100px;
                cursor: pointer;
                background: #ccc;
                border: solid 3px #ccc;
                -webkit-transition: all .3s linear 0s;
                transition: all .3s linear 0s;
                }

                #box.red {
                background: #f43059;
                }

                <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
                <div class="wrapper">
                <div id="box">Click me.</div>
                </div>





                $('#box').click(function() {
                $(this).one('transitionend', () => {
                // Do something that takes time.
                for (i = 0; i < 1000; i++) {
                console.log(i);
                }
                // Toggle class 'red' off.
                setTimeout(() => {
                $(this).removeClass('red');
                });
                });
                $(this).addClass('red');
                });

                .wrapper {
                margin: 15px;
                text-align: center;
                color: #000;
                }

                #box {
                margin: 15px 0;
                width: 100px;
                height: 100px;
                line-height: 100px;
                cursor: pointer;
                background: #ccc;
                border: solid 3px #ccc;
                -webkit-transition: all .3s linear 0s;
                transition: all .3s linear 0s;
                }

                #box.red {
                background: #f43059;
                }

                <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
                <div class="wrapper">
                <div id="box">Click me.</div>
                </div>






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jan 1 at 3:46









                CertainPerformanceCertainPerformance

                87k154774




                87k154774
































                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53992871%2fcss-styles-not-applying-immediately-when-class-toggled-with-jquery%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Monofisismo

                    Angular Downloading a file using contenturl with Basic Authentication

                    Olmecas