jQuery 3.0 alpha blog post screenshot

jQuery 3.0 breaking changes to hide() and show()

Sam RuebyCSS, Web Development 1 Comment

Show() and hide() were simplified (well, their internal implementation) and existing code that you wrote that uses them might not work anymore.

Why break something so simple?!

It wasn’t until I read their post that I understood that their job wasn’t so easy. There’s a few edge cases that don’t have simple answers.

Problem #1: They’re not responsive

When you call show() on an element, the CSS display value is inserted right into the element’s style  attribute. The problem occurs if an element can have a different display value dependent on another factor, such as adding a class or a media query going into effect.

Screenshot of jsFiddle showing the inconsistent display value  after using show()

.child should have a ‘display’ value of ‘block’. But because jQuery’s show() put the display value in the ‘style’ attribute, display: inline overrides this value.

In the above screen recording, the developer intended to have div.child to have a value of display: block . However, jQuery thwarted this when the call to show()  set display: inline  in the element’s style  attribute, tying the developer’s hands.

Sources: 

  • https://github.com/jquery/jquery/issues/1767 
  • https://jsfiddle.net/jinglesthula/ZttLJ/

Problem #2: They hurt performance

How could this hurt performance? Basically, jQuery has to keep track of the current CSS tree, which is costly. Paul Irish found this was the biggest bottleneck when loading Wikipedia’s visual editor. He brought up an important point:

Aside: Now that I’m looking, this magic behavior doesn’t make much sense. There seem to be two edge cases that have caused jQuery to punish every app’s performance:

  1. div { display:none; } is defined and user wants to override that with show()
  2. User has a custom display value defined on the inline style.

Is baking in support for these two edge cases into one of jQuery’s most simple looking APIs worth being the largest bottleneck in this editor?

Source: https://github.com/jquery/jquery.com/issues/88

What situation does jQuery 3.0 break hide() and show()?

If you have elements in a stylesheet that are set to display: none , the .show()method will no longer override that. So the most important rule for moving to jQuery 3.0 is this: Don’t use a stylesheet to set the default of display: noneand then try to use .show()– or any method that shows elements, such as .slideDown()and .fadeIn()– to make it visible.

Check out the following JSFIddle: https://jsfiddle.net/xwvzkx9y/2/

Screen recording of JSFIddle showing that in jQuery 3.0 slideToggle doesn't work because a class on the element sets display: none

slideToggle doesn’t work because display: none is set using a class.

Because the JSFiddle referencing jQuery edge (3.0), slideToggle no-longer functions because the element has the “hide” class, which jQuery will no-longer override. Removing “hide” fixes this, but the element is no-longer hidden by default. Replacing the ‘hide’ class with display: none on the element is another approved solution.

Okay. What do I do instead?

Well, they’re going to keep show()  and hide()  around but they removed the expensive calls they were doing that supported the few edge cases. From the blog post:

If you need an element to be hidden by default, the best way is to add a class name like “hidden” to the element and define that class to be display: none in a stylesheet. Then you can add or remove that class using jQuery’s .addClass() and .removeClass() methods to control visibility. Alternately, you can have a .ready() handler call .hide() on the elements before they are displayed on the page. Or, if you really must retain the stylesheet default, you can use .css(“display”, “block”) (or the appropriate display value) to override the stylesheet.

Personally I think suggesting calling hide() in the ready() handler is a poor suggestion. That’s going to run the risk of flash of unstyled content, which I don’t believe I’m alone in thinking FOUC appears unprofessional.

Use [add|remove]Class()

Screen recording using jsfiddle of hiding and showing a green box

Using jQuery’s recommended way to show and hide elements.

Using this method, it doesn’t matter if the div has a different display value for different media queries, providing you the ability to toggle an element’s display while also giving you the power to handle special situations (e.g. media queries). JSFiddle available at https://jsfiddle.net/m0ofoo4y/.