68

I'm working on a mobile version of my site. I'm using media queries and CSS as much as possible, but I'm also using some javascript to, for example, turn my navigation into a collapse/expand list on smaller devices to save room.

To handle all of this, I was attempting to use the window.resize event. This allows the magic to happen on desktop browsers while they're resized, but I'm getting resize events on iPad/iPhone when I'm not expecting them.

On desktop browsers, I only get a resize event if I actually resize the window. On mobile browsers I get the resize event when I change orientation (expected), but I also get it when I toggle to expand/collapse something.

Here's a simple example:

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<title>Resize test</title>
<style>
.box {height: 10000px; background: green; display: none;}
</style>
<script>
$(function(){
    $(".opener").click(function(){
        $(".box").slideToggle();
    });
    $(window).resize(function(){
        alert("resized");
    });
});
</script>
</head>

<body>
<a href="#" class="opener">Open/close me</a>
<div class="box"></div>
</body>
</html>

When you click the link on a desktop browser, no alert. Click the link on iPhone/iPad, you get the alert. What's the deal?

rdoyle720
  • 2,940
  • 3
  • 17
  • 19

8 Answers8

141

Store the window width and check that it has actually changed before proceeding with your $(window).resize function:

jQuery(document).ready(function($) {

    // Store the window width
    var windowWidth = $(window).width();

    // Resize Event
    $(window).resize(function(){

        // Check window width has actually changed and it's not just iOS triggering a resize event on scroll
        if ($(window).width() != windowWidth) {

            // Update the window width for next time
            windowWidth = $(window).width();

            // Do stuff here

        }

        // Otherwise do nothing

    });

});
Sven
  • 1,450
  • 3
  • 33
  • 58
James Greig
  • 1,683
  • 1
  • 11
  • 16
  • 4
    THANK YOU. just spent way too long on this issue myself. Great simple solution! – am80l Jan 30 '15 at 06:55
  • 13
    I like that solution. F*ck to iOS that make scroll fires `resize` event. Incomprehensible. – Marcos Pérez Gude Dec 14 '15 at 12:46
  • This solution saves my life today again. I don't understand why this answer is not marked as the valid answer, but this answer is meritory to have almost 1000 upvotes (there are little stupid things that have much more upvotes). – Marcos Pérez Gude Jan 15 '16 at 12:46
  • 2
    @MarcosPérezGude it makes sense because it literally is resizing the viewport - your content is shifted and re-rendering takes place due to the changing controls and url bar resizing. There are times where this might be a feature, not a bug. – Anthony Manning-Franklin Nov 18 '16 at 04:03
  • Almost spend 3 hours(on my own to figure the issues and failed) and then I found this golden answer. Cheers @3stripe – Rahul Dec 21 '16 at 13:34
  • 3
    2017, scrolling still considered resize event. – SamSig Jan 26 '17 at 19:51
  • THANK YOU! This just helped me so much – vinni Apr 23 '18 at 09:11
  • 2019, scrolling still fires resize event. – hurricane Jan 15 '19 at 15:05
  • 2020, scrolling and PINCH ZOOMING still fires resize event. – Sevron Jan 12 '20 at 13:09
  • 1
    If someone wants to detect also changes in height (not very common but could happen), I would suggest to make the same check on `$(window).height()` – Giorgio Tempesta Jul 31 '20 at 09:34
  • 1
    scroll == resize – 00-BBB Oct 15 '20 at 16:58
  • 1
    The problem is a bit more complex.... the resize events reacts to 2 types of parameters changing , the width (which obviously never changes) and the height changing, if any of those change , it gets triggered.. What happens is that safari ios starts changing the height on scrolling ... to show or hide the url bar... so it triggers the resize on scroll. There is no a specif event listener for the width changing. – Mg Gm Jun 01 '22 at 23:21
12

Here's the vanilla javascript version of the accepted answer

document.addEventListener('DOMContentLoaded', function() {

    // Store the window width
    var windowWidth = window.innerWidth

    // Resize Event
    window.addEventListener("resize", function() {

        // Check window width has actually changed and it's not just iOS triggering a resize event on scroll
        if (window.innerWidth != windowWidth) {

            // Update the window width for next time
            windowWidth = window.innerWidth

            // Do stuff here

        }

        // Otherwise do nothing
    })

})
btjakes
  • 405
  • 3
  • 13
2

I found out the answer in StackOverflow itself link of the solution. it's the answer by sidonaldson that helped me solve an issue faced earlier like this. ty

the answer is:

var cachedWidth = $(window).width();
    $(window).resize(function(){
        var newWidth = $(window).width();
        if(newWidth !== cachedWidth){
            //DO RESIZE HERE
            cachedWidth = newWidth;
        }
    });
Jithin Raj P R
  • 6,667
  • 8
  • 38
  • 69
2

I needed to specify a width:

   <meta name="viewport" content="width=1000, initial-scale=1.0, user-scalable=yes">

Styles:

html, body
{
       height:100%;
       width:100%;
       overflow:auto;
}
Kees C. Bakker
  • 32,294
  • 27
  • 115
  • 203
  • 4
    Thanks, but then I lose the responsive part of the design, having it adapt to different resolutions... – rdoyle720 Jan 17 '12 at 16:57
  • Good point. Do you even get the events if body and html are: height:100%; with:100%; overflow:auto ? – Kees C. Bakker Jan 17 '12 at 17:00
  • 2
    That did it, adding: html, body {height: 100%; overflow: auto; margin: 0} Stopped the resize events. – rdoyle720 Jan 17 '12 at 17:39
  • 2
    Actually no, that didn't quite fix it. overflow: auto makes me lose the momentum scrolling. If I add -webkit-overflow-scrolling: touch I get it back, but lose the linen texture underneath on the bounce. Maybe that's as good as I can get it. – rdoyle720 Jan 17 '12 at 17:47
  • 1
    So basically the events are height-sizing-events that are getting in. Maybe iScroll 4 could fix the scolling issue? http://cubiq.org/iscroll-4 – Kees C. Bakker Jan 17 '12 at 17:53
  • 1
    Just to add to this.. I had the same problem and it seemed by changing the overflow on the html & body, the resize event stopped firing - problem solved! Thanks richard – alimac83 Sep 19 '12 at 10:58
1

Is the assumption wrong, that you only want to have the effect of the resize event on a non-touch device? If so you could just use Modernizr and do a check like:

    $(window).resize(function(e){
       if(Modernizr.touch) {
         e.preventDefault();
       }
    });
Felix
  • 4,213
  • 1
  • 21
  • 27
  • 1
    Unfortunately, Modernizr can no longer detect touch and nor should it. http://www.stucox.com/blog/you-cant-detect-a-touchscreen/ – Alex Jul 05 '16 at 16:03
0

@3stripe has the correct answer.

This is just a slight modification which makes it more efficient by caching the window object rather than repeatedly instantiating jQuery (keep in mind the resize event may be called rapidly on an actual resize).

jQuery(document).ready(function($) {

    // Cached window jQuery object
    var $window = $(window);

    // Store the window width
    var windowWidth = $window.width();

    // Resize Event
    $window.resize(function(){

        // Check window width has actually changed and it's not just iOS triggering a resize event on scroll
        if ($window.width() != windowWidth) {

            // Update the window width for next time
            windowWidth = $window.width();

            // Do stuff here

        }

        // Otherwise do nothing

    });

});
anthonygore
  • 4,722
  • 4
  • 31
  • 30
  • Yep, this is better but shouldn't it be "var $window = $(window);" (you're missing the var declaration) – Ralphonz Sep 06 '16 at 09:52
0

Check if your explicitly scrolling the html body wrapper to hide the address bar when the page loads.

Abhidev
  • 7,063
  • 6
  • 21
  • 26
-1

It feels hacky to check the window size to see if it's changed. Instead, use the resources jQuery provides you!

In the event handler, you can check the jQuery event's target field, which is always set to the DOM element that originated the event. If the user resizes the window, target will be the window. If the user resizes #someDiv, target will be the #someDiv.

$(window).on('resize', function(event) {
    if ($(event.target).is($(window))) {
       doTheThing();
    }
});
Matt
  • 23,363
  • 39
  • 111
  • 152
  • 1
    Have you checked your answer before ? On the iOS scroll it get fired window.resize event (with the target window) thus you cannot say if it was or not indeed resized, leaving us with the only solution to check it against a stored value (but you can optimise a little bit and do this only for iOS - check navigator agent as well) – qdev Feb 11 '18 at 12:17