Panel toggle available only on mobile, visible on all other viewports

Hi there,

I’ve got a section I’m working on which I only want to be togglable on small tablet/mobile viewport (in my case 799px and below) and display permanently on 800px and above. The problem I’m having is there’s a conflict whereby the toggle and visibility don’t work at some points when I resize the window.

By default, I want the filters to be hidden on mobile but give the user the ability to show/hide at will. On 800px and above the filters should just display. Both of these scenarios should work if you resize the window/change orientation.

The problem I’ve got is that I’ve used flexbox for layout purposes so that complicates matters a bit for the show/hide.

See here (the “Filters” section) for details. Below is the JS that I currently have controlling this area.

// toggle film filter panel

    function toggleFilmPanels() {

        if ($(window).width() <= 799) {

            $('#film-filters-toggle').removeClass("active");

            $('#film-filters-panel').css('display', 'none');

            $('#film-filters-toggle').click(function() {

                $(this).toggleClass("active");

                $("#film-filters-panel").slideToggle({

                    start: function() {

                        $("#film-filters-panel").css({

                            display: "flex"

                        })

                    }

                });

            });

        } else{

            $('#film-filters-toggle').removeClass("active");

            $('#film-filters-panel').css('display', 'flex');

        }

    }

    toggleFilmPanels();

Any thoughts please?

It’s late here, so sorry if I am mistaken.

A quick scan through your code and I can’t see a ‘resize’ event listener. You’ll want that event to trigger/fire your toggleFilmPanels function.

Just a couple of quick links I found

https://www.techiedelight.com/handle-resize-event-javascript/

In the following he’s using a debounce technique, which means it will only trigger your toggle function when resizing is complete — a pretty good idea.

https://css-tricks.com/snippets/jquery/done-resizing-event/

Some more info on debounce here (specifically resizing)
https://css-tricks.com/debouncing-throttling-explained-examples/#debounce-examples

2 Likes

I would do as much in css as you can and that reduces the JS.

For example use media queries to show and hide the toggle and then your JS does not need a width detection routine. Just apply the routine once at the start. It doesn’t matter that you apply it on desktop because css has hidden the toggle.

When the media query clicks in and reveals the toggle then you can use it as required.

You’ll need 2 media queries. One will be min-width: 800px and one will be max-width: 799px.

In those media queries you can apply the styles to show and hide those elements and you won’t need the active classes as css will do that.

The only thing the JS needs to do is apply the click event listener and then activate your slide toggle. The only complication is that the slide toggle writes an inline style so in your min-width media query you will add !important to the display:flex rule for the film div.

I’m on a mobile at the moment but I’ll offer some real code when I get back home later today :slight_smile:

3 Likes

Here’s a working version but the main thing to note is that I made the arrow toggle the element and not the word “Filter”. If you wanted the word Filter to be part of the toggle it could be done but would need a bit of tweaking.

I’ve only added enough of your styles to make this work so is not an exact copy but should show the working parts. The js in the side panel is all you need plus the new css in the css panel. It should be self explanatory.

Aldo note that if you open the panel on small screen and then go to large screen the display is as expected on large screen but once you return to small screen the panel will still be open because that’s how you left it. That’s the design pattern I use for all of these as I dislike it when you open a menu on small screen and then enlarge your screen for a second and come back to small screen to find the menu has closed. If I open the menu on small screen I want it to stay open until I close it. :slight_smile:

3 Likes

I always go to the effort of programming that bit of cleanup. lol

Might have to have a re-think on that :smiley:

3 Likes

Thank you Paul!

I did a quick test on my Pixel 4 and spotted that on first open there is a jump? Subsequent opens are much smoother - is this due to the padding/margin applied?

Screen recording below:

Thanks again for looking into this for me.

1 Like

The jquery slideToggle is known for being jumpy in some situations. Usually as you say it’s margin or padding that upsets it so you need to make sure that the toggled element is as straight forward as possible.

It works best on elements of fixed height but of course that is bad in a responsive layout.

I’ll try and have a look in the morning and see if it can be improved:)

2 Likes

The only way I can seem to stop the jump is by adding a height to that panel.

Code updated here.

As you only have the two items in that panel it should be ok to have a fixed height.


@media screen and (max-width: 799px) {
  #film-filters-panel {
    display: none;
  }
  #film-filters .genericpage--films__filters__panel {
    height: 43px;/* tweak to suit*/
  }
}

I remember that the jquery slideToggle was always a pain without fixed heights and was never that smooth.

2 Likes

Thanks Paul - agreed I think that’s the only way I’ve managed to fix it in the past as well.

I decided against hiding the panel onload to both negate this issue but also because it made sense from a UX point of view to have the panel open - visitors are more than likely going to filter the results since there will be so many and leaving the panel open also encourages this behaviour… so actually, this issue works in my favour!

I’ve applied those changes and tweaked a couple of styling pieces but I think the next part I’m finding tricky is getting the “Filters” text to be clickable, without it being available on desktop. One quick solution I thought of was to have a completely separate version of the button for mobile and attach the JS to that but that seems a little messy to me, especially if for example I wanted to change the button text later - I’d have to change it in multiple places.

So, in short - what’s needed to get the whole “Filters” text clickable without running into issues on desktop (i.e. at the moment the “Filters” text is clickable which means the slideToggle animation runs unnecessarily on the 800px and above viewport.

Just add pointer-events:none in the larger screen and it wont be able to be clicked.

@media screen and (min-width:800px){

    #film-filters-toggle{pointer-events:none;}
}
3 Likes

Ah of course, simple as that! haha. Thanks so much for your help as always!

2 Likes

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