fakeguybrushthreepwood
fakeguybrushthreepwood

Reputation: 3083

Make the contents of a <details> tag animate when open with jQuery/JS

I simply want the contents of the HTML5 details tag to 'glide'/animate open rather than just pop open/appear instantly. Is this possible with jQuery/Javascript?

Fiddle

HTML:

<details>
<summary>Show/Hide</summary>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum laoreet metus auctor tempor dignissim. Nunc tempor ligula malesuada, adipiscing justo quis, ultrices libero. Curabitur pretium odio sagittis lorem euismod, a ultrices sem ultrices. Integer sapien nibh, mollis id pretium id, dignissim ut dui. Nam sit amet lectus lectus. Cras scelerisque risus a dui accumsan, in dignissim dolor sodales. Nunc aliquam pharetra dui, a consectetur velit lobortis vel.</p>
<p>Mauris convallis orci in semper aliquam. Ut mollis laoreet nibh pretium tincidunt. Donec aliquam at odio sit amet dictum. Phasellus sapien leo, feugiat sit amet sagittis in, congue vel lectus. Donec elementum est vitae nulla interdum laoreet. Curabitur fringilla a tellus non laoreet. Aliquam vel lectus convallis massa pulvinar pellentesque. Mauris laoreet pharetra turpis vel tristique. Sed ligula ligula, sodales sed auctor in, aliquam sit amet lorem. Etiam vestibulum, libero vel dignissim ultrices, lacus mauris lacinia enim, quis aliquam nibh mauris eu mauris. Etiam sapien leo, dapibus et libero sed, laoreet ornare tellus.</p>
<p>Sed placerat vehicula magna et adipiscing. Nam euismod nibh ut tellus tempor, eget lobortis metus iaculis. In laoreet, enim in dignissim pellentesque, felis augue tincidunt massa, vestibulum fringilla mauris sapien in diam. Duis interdum molestie fermentum. Aenean dictum varius augue, id luctus neque viverra id. Nam eleifend tempus mauris in mattis. Sed id risus non magna semper blandit in vel arcu. Suspendisse quis nisi ligula. Fusce vestibulum at enim eu.</p>
</details>

Upvotes: 3

Views: 3585

Answers (2)

Magnar Myrtveit
Magnar Myrtveit

Reputation: 2740

Based on @JoshCrozier's answer, I've made a solution that uses the open attribute instead of the extra open class. This way you don't have to change the css.

If you would like to use css to change the appearance of the <details> element, you can use the same style rules regardless of whether the browser supports the <details> element, and regardless of whether javascript is enabled in the browser, since you only have to consider the open attribute, and no special classes.

In addition, there is no special id on the wrapper element, making the solution slightly more robust and generic.

Also, this solutions takes <details> elements that should be open by default into account.

$('details summary').each(function() {
   var $Wrapper = $(this).nextAll().wrapAll('<div></div>').parent();
   // Hide elements that are not open by default
   if(!$(this).parent('details').attr('open'))
      $Wrapper.hide();
   $(this).click(function(Event) {
      Event.preventDefault();
      if($(this).parent('details').attr('open')) {
         $Wrapper.slideUp(function() {
            // Remove the open attribute after sliding so, so the animation is visible in browsers supporting the <details> element
            $(this).parent('details').removeAttr('open');
         });
      } else {
         // Add the open attribute before sliding down, so the animation is visible in browsers supporting the <details> element
         $(this).parent('details').attr('open', true);
         $Wrapper.slideDown();
      }
   });
});

Upvotes: 3

Josh Crozier
Josh Crozier

Reputation: 240948

Too bad a simple CSS transition can't be used.

I'd therefore suggest wrapping the sibling elements of the summary element and then using .slideToggle() on them. It isn't that simple though, you need to add the open attribute to details, and hide the inner wrapped elements by default.

This only works if you use e.preventDefault() to prevent the default functionality; however, you then need to rewrite the arrow indicators, (,).

You would use summary::-webkit-details-marker and display:none to remove the marker that is no longer working, and add your own custom markers via the :before/:after pseudo elements.

UPDATED EXAMPLE HERE

$('details summary').each(function(){
    $(this).nextAll().wrapAll('<div id="wrap"></div>');
});
$('details').attr('open','').find('#wrap').css('display','none');
$('details summary').click(function(e) {
    e.preventDefault();
    $(this).siblings('div#wrap').slideToggle(function(){
        $(this).parent('details').toggleClass('open');
    });
});

CSS:

summary::-webkit-details-marker {
    display: none;
}
summary:before {
    content: "►";
}
details.open summary:before {
    content: "▼";
}

If you want the details element to be open by default, add class="open" as opposed to the attribute open, and then use this: $('details.open div#wrap').css('display','block');

ALTERNATIVE EXAMPLE - (open by default)

Upvotes: 6

Related Questions