2

I am trying to use .slideToggle() to toggle a div with display: none to display: grid. However this animation seems to add display: block inline to the html and overwrite any other css class

CSS

.grid {
    display: grid;
}

jQuery

$('#nav-toggle').click(function() {
    $('.nav-menu').slideToggle(500, function() {
        $(this).toggleClass('grid')
    });
});

I had somewhat brief success using

$('#nav-toggle').click(function() {
    $('.nav-menu').slideToggle(500, function() {
         if ($(this).is(':visible')) {
             $(this).css('display','grid');
         }
    });
});
.nav-menu {
    display: none;
    grid-template-columns: repeat(3, 1fr);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id=nav-toggle>
    Toggle
</div>

<div class=nav-menu>
    <div>Item 1</div>
    <div>Item 2</div>
    <div>Item 3</div>
</div>

but the initial animation seems to play using display: block and once the animation is finished I guess jQuery then sees the element as visible and the HTML snaps from display: block (items stacked) to display: grid (items spaced).

All following animations seem to play nicely with display: grid.

How can I get the initial animation to display correctly too?

myol
  • 8,857
  • 19
  • 82
  • 143

2 Answers2

1

The solution is to set nav-menu to display:grid; and to hide and show it with JQuery. By the way if you have a user who disabled JavaScript, he will still be able to read your page.

Try the following code:

$('.nav-menu').hide(); // clearer than display none
$('#nav-toggle').click(function() {
  $('.nav-menu').slideToggle(500, function() {
    if ($(this).is(':visible')) {
      $(this).show(); // clearer than display previous (here grid)
    }
  });
});
.nav-menu {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="nav-toggle">
  Toggle
</div>

<div class="nav-menu">
  <div>Item 1</div>
  <div>Item 2</div>
  <div>Item 3</div>
</div>

Related to: https://stackoverflow.com/a/8144998/1248177

aloisdg
  • 22,270
  • 6
  • 85
  • 105
  • Thanks. Hmm this really makes responsive webpages a pain to implement, I guess I will look into other ways to display my menu. – myol Oct 01 '18 at 08:20
  • @myol you may want to use a framework like bootstrap to help you. Beside, did this fix you problem? If so, upvote and accept it. :) – aloisdg Oct 01 '18 at 08:46
  • 1
    It didn't fix my problem per-se but I've upvoted anyway since you took the time to answer. – myol Oct 01 '18 at 09:25
0

So in order to make responsive CSS media queries much cleaner and easier, I ended up wrapping the nav element in a div and simply having the div toggle between display: none and display: block.

I am still able to align the menu items within since the child of the block is the nav which kept the grid property. Also in my case this block was a child of a more complex display: grid layout, but since it is still a child, I could still use the CSS grid properties on it, I just had to use older CSS methods to expand and center the block.

Its not perfectly clean but I guess its the best I can do until jQuery is updated to support more than just display: block for its animations.

$('#nav-toggle').click(function() {
    $('.nav-menu-container').slideToggle(500, function() {
        if ($(this).css('display') == 'none') {
            $(this).css('display', '');
        }
    });
});
.nav-menu-container {
    display: none;
}

.nav-menu {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id=nav-toggle>
    Toggle
</div>
<div class=nav-menu-container>
    <div class=nav-menu>
        <div>Item 1</div>
        <div>Item 2</div>
        <div>Item 3</div>
    </div>
</div>
myol
  • 8,857
  • 19
  • 82
  • 143