Adding/Removing classes on resize JQuery

Just like the title of the thread, just trying to add and remove a class on resize with jQuery. I cant seem to get it to work on resize, I can get it to work on window load though. Heres my code:

$(window).load(function() {
    
    var viewportWidth = $(window).width();
    if (viewportWidth < 600) {
            $(".view").removeClass("view view-portfolio").addClass("gallery-mobile");
    }
    
    $(window).resize(function () {
    
        if (viewportWidth < 600) {
            $(".view").removeClass("view view-portfolio").addClass("gallery-mobile");
        }
    });
});

Any help would be awesome, thanks

You can actually combine those functions. Also, you don’t need the on load jQuery if you place your script right before </body>. So actually, I’m going to remove the load. Untested…but…

$(window).resize(function () {
    var viewportWidth = $(window).width();
    if (viewportWidth < 600) {
            $(".view").removeClass("view view-portfolio").addClass("gallery-mobile");
    }
});

If you don’t want it combined…then…

$(window).on("load, resize", function() {
    var viewportWidth = $(window).width();
    if (viewportWidth < 600) {
            $(".view").removeClass("view view-portfolio").addClass("gallery-mobile");
    }
});

Again, untested.

As @RyanReese suggested, you should combine these two functions to avoid redundancy in code.

If you want to go with the same code then here is my understanding to the issue - you are calculating viewport width on page load event which is one time fill. All you need to do is to re-calculate viewportwidth inside resize function as well to get the updated value with each resize event call.

    $(window).load(function() {
        var viewportWidth = $(window).width();
        if (viewportWidth < 600) {
            $(".view").removeClass("view view-portfolio").addClass("gallery-mobile");
        }
     });

    $(window).resize(function () {
        var viewportWidth = $(window).width();
        if (viewportWidth < 600) {
            $(".view").removeClass("view view-portfolio").addClass("gallery-mobile");
        }
    });

There is though lots of duplication that should according to the DRY principle (Don’t Repeat Yourself) be brought together.

A first attempt is to give the functions a common name:

function mobileViewUpdate() {
    var viewportWidth = $(window).width();
    if (viewportWidth < 600) {
        $(".view").removeClass("view view-portfolio").addClass("gallery-mobile");
    }
}

$(window).load(mobileViewUpdate);
$(window).resize(mobileViewUpdate);

Now that some of duplication has been removed, we can see that there is further duplication in the load and resize calls. We can trigger mobileViewUpdate when either the load or resize event occurs on the window, with:

$(window).on('load, resize', mobileViewUpdate);

And because we have a call to the mobileViewUpdate function in just the one place here, we can inline that function, getting us back to something very close to what Ryan suggests above:

$(window).on('load, resize', function mobileViewUpdate() {
    var viewportWidth = $(window).width();
    if (viewportWidth < 600) {
        $(".view").removeClass("view view-portfolio").addClass("gallery-mobile");
    }
});

Leaving it as a named function provides the benefit when debugging of being able to easily recognise it in the call-stack too.

1 Like

@Paul_Wilkins very well explained Sir. It’s a learning for me, that we should explain things in such a way that one can absorb & understand things with ease.

Excuse the possible silly question but what does this accomplish that can’t be more easily done with media queries (unless you are adding dynamic actions to the classes you are adding)? If its purely a styling thing then you can do that with media queries.

Also with the script above won’t you also need to check when the viewport is greater than 600 otherwise the 2 classes you added when it was made smaller will still stay in place. If a user sizes there screen smaller the 2 classes come in to play but if you widen the viewport again those smaller viewport classes will still stay in place.

That’s not a silly question at all. The less that we have to rely on scripting the better. It’s better to rely instead on more reliable techniques.

What do you think is the best way to use media queries to achieve what he’s after?

His jQuery is only adding a class to the element.

So imagine if we did this.

@media only screen and (max-width:600px)
{
  //Pretend the class stuff goes here.
}

Again, as Paul said, this would 100% rely on the fact that the class is purely for styling. His jQuery determines if the screen is 600px or under. This media query will active ONLY at 600px and under.

Move those class rules, into this media query. Might be a bit more complicated (we don’t know his setup) but the idea is there. Simple to implement.

Everyone here has given outstanding advice, thank you. So to answer some of the questions, the styling I wanted to do based on different viewport widths is quite large and complicated, so instead of resetting/setting 30+ lines of css with media queries, its much easier to just swap out a class with JS. Iv taken the advice for DRY coding, as Im new to JS I was just happy to write legible code that worked, the problem was indeed that I needed to state the variable for resize and window load. So now Im using Paul W’s code and its working on resize but not on load, not sure why

I’m glad you have it working, although while it may be easier, it’s not actually the best way. You wouldn’t be resetting in the media query. The media query would basically “add the class” (trying to translate to how you think of it in JS) to the element in under 600px. You wouldn’t need to reset 30 lines of CSS. You’d simply need to change the couple properties that you need to change for under 600px.

You’d only be in a “reset” situation, if the initial element in CSS was in a media query that ONLY sets the 30 lines in 600px+ viewport sizes. Otherwise, it’ll translate into every screen. Media queries overwrite the default. Not replace :slight_smile: .

Just FYI :slight_smile: .

I understand this, but I would be resetting almost EVERY style thats > 600px, I needed a blank slate for the same content for < 600px. And BTW, the code is not working for window load, only resize

You can do that ever so simply with media queries and avoid throttling the resize event.

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<style>

@media screen and (max-width:600px){
	.test{
		background:blue;	
	}	
}
@media screen and (min-width:601px){
	.test{
		color:red	
	}	
}


</style>

</head>
<body>
<div class="test">My background is blue at less than 600px and text is red at greater than 600px</div>
</body>
</html>

No need to reset anything, No need for extra classes.No conflicts, no repetition and no javascript needed. They are both totally separate.

Usually though elements have common themes even at large sizes so you can apply common rules outside those media queries if you want.

Your script is still wrong (even though its totally unnecessary for what you want) though because you aren’t catering for when the window is closed small and opened again as I mentioned above.

I will re-iterate that there is absolutely no need for javascript here and you will be hurting your pages performance by using such methods.

If it makes it easier for you you can use separate classes anyway.

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<style>

@media screen and (max-width:600px){
	.desktop{
		background:blue;	
	}	
}
@media screen and (min-width:601px){
	.mobile{
		color:red	
	}	
}


</style>

</head>
<body>
<div class="desktop mobile">My background is blue at less than 600px and text is red at greater than 600px</div>
</body>
</html>

Okay so everything is sorted out now. You can take a look at [www.darren-segal.com][1][1]: http://darren-segal.com

My only problem now is that for some strange reason the links dont go to the correct anchor point on the mobile version (< 500px). It seems like theres a margin somewhere but I looked through everything and I cant figure it out.

Seems to be ok on the iphone if we are talking about the menu items?

Everything on the site is now working and is completely finished over at www.darren-segal.com
I really could not have made it look at work just the right way without all of your help. I always get the best advice in a staggeringly short amount of time here at SitePoint. Now I just have to move on to SEO…gonna be fun.

If you guys have any advice or criticism about the site, Id be happy to here it

Thanks again people

Looks good to me.:slight_smile:

Just an idea but you could have used css columns for the three columns of text instead of three divs divided into columns. Only modern browser support (pre-fix needed for some) but older browsers just default to the one column (or use a polyfill).

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.