How to hide elements with jQuery before they get r

2019-01-21 19:01发布

问题:

I want to generate html layout with areas (divs, spans) that can be shown/hidden conditionally. These areas are hidden by default.

If I call .hide() method with jquery on document.ready these areas may blink (browsers render partially loaded documents). So I apply "display: none" style in html layout.

I wonder what is the best practice to avoid blinking, because applying "display:none" breaks incapsulation rule - I know what jquery does with hide/show and use it. If jquery's hiding/showing implementation will change one day, I'll get the whole site unworkable.

Thank you in advance

回答1:

There's absolutely nothing wrong with setting an intial display property of an element, especially if you encapsulate it in a css class.



回答2:

@Andrew,

I know the answer has already been accepted, but using display: none; will be a nightmare to users without Javascript.

Using inline Javascript, you can hide an element without it ever blinking. Users without Javascript will still be able to see it.

Consider a few divs that should be hidden when the page loads.

<head>
    <script type="text/javascript" src="jQuery.js"></script>
</head>
<body>
    <div id="hide-me">
        ... some content ...
    </div>
    <script type="text/javascript">
        $("#hide-me").hide();
    </script>

    <div id="hide-me-too">
        ... some content ...
    </div>
    <script type="text/javascript">
        $("#hide-me-too").hide();
    </script>
</body>

The inline Javascript will run as soon as the element is rendered, thus hiding it from the user.



回答3:

I agree with Boris Guéry, that it is not over-engineering, but rather, a standard best practice. I would go a slightly different way than Boris, by adding a no-js class to the html initially and then removing it with JavaScript.

This way you're not waiting for the document to be ready to hide the content, and without any JavaScript you still see the content. Assuming the user has not JavaScript is more in line with the philosophy of progressive enhancement.

ex:

<html class="no-js">
<body>
<div id="foo"></div>
</body>
</html>

my css :

#foo {
    display: none;
}
html.no-js #foo {
    display: block;
}

and javascript

$(document).ready(
   function()
   {
     $('html').removeClass('no-js');
   }
);

********* OR on a per-case basis***********

ex:

<div class="no-js" id="foo">foobar and stuff</div>

css:

.no-js {
  display:none;
}
#foo {
  display: block;
}
#foo.no-js {
  display: none;
}

js:

$(document).ready(function(){
  // remove the class from any element that has it.
  $('.no-js').removeClass('no-js');
});


回答4:

I usually set a .js class to my element to set the proper property when javascript is enabled.

I then can set the CSS depending on if javascript is present or not.

ex:

<html class="js">
<body>
<div id="foo"></div>
</body>
</html>

my css :

html.js #foo
{
    display: none;
}

and javascript

$(document).ready(
   function()
   {
     $(html).addClass('js');
   }
);


回答5:

I struggled with this too, especially in IE, and I found this very helpful: http://robertnyman.com/2008/05/13/how-to-hide-and-show-initial-content-depending-on-whether-javascript-support-is-available/



回答6:

Why not do just this?:

// Hide HTML element ASAP
$('html').hide();

// DOM-ready function
$(function () {
   // Do stuff with the DOM, if needed
   // ...

   // Show HTML element
   $('html').show();
}

It seems to work fine!

Regards.



回答7:

you can apply "display: none" in a CSS class.

Because the order which a browser have to read some HTML code in order for the JavaScript to find the Element. You have to mark the element hidden, as the browser reads your HTML.

How ever you can also insert the HTML in your JavaScript, and you can call hide before it is rendered.



回答8:

I would always use Modernizr.js http://modernizr.com/ to handle this.

With Mondernizr a class 'js' or 'no-js' is added to the HTML tag of your page.

From here you can hide your elements only if the html tag has the js class.

Modernizr is great for so many other applications and worth reading up on if you've not used it before: http://modernizr.com/docs/



回答9:

What I always do is create an empty div. And if some data inside that component needs to be shown, I asynchronously load data (i.e. html) into it using $.ajax().

No need for an extra lib.



回答10:

This is my suggestion. It utilizes this solution to create a new CSS rule. The main thing: a CSS class that hides some html will be created if JS is available, otherwise not. And this happens before the main content (with the html parts that should be initially hidden) gets processed!

<html>
<head>
    <style>
        /* This class gets overwritten if JS is enabled. If a css file (bootstrap, ...) 
        gets loaded with such a class this would be also overwritten. This solution does 
        not require the class. It is here just to show that it has no effect 
        if JS is activated.*/
        .hidden {
            display: block;
            background: red;
        }
    </style>
    <script>
        // this is copied from the linked stackoverflow reply:
        function setStyle(cssText) {
            var sheet  = document.createElement('style');
            sheet.type = 'text/css';
            /* Optional */
            window.customSheet = sheet;
            (document.head || document.getElementsByTagName('head')[0]).appendChild(sheet);
            return (setStyle = function (cssText, node) {
                if (!node || node.parentNode !== sheet)
                    return sheet.appendChild(document.createTextNode(cssText));
                node.nodeValue = cssText;
                return node;
            })(cssText);
        }

        // And now: This class only gets defined if JS is enabled. Otherwise 
        // it will not be created/overwritten.
        setStyle('.hidden { display: none; }');

        // Attention: Now that the class is defined it could be overwritten 
        // in other CSS declarations (in style tags or with loaded CSS files).
    </script>
</head>
<body>

    <button>Show/Hide</button>

    <div class="">before</div>
    <div class="my-element hidden">
        Content that should be initially hidden if possible.
        You may want to multiply this div by some thousands
        so that you see the effect. With and without JS enabled.
    </div>
    <div class="">after</div>

    <script src="https://code.jquery.com/jquery-2.2.3.min.js"></script>
    <script>
        // Here is some 'normal' JS code. Very likely loaded as a JS file:
        $('button').click(function () {
            $('.my-element').toggleClass('hidden');
            // or setting display directly: 
            //   $('.my-element').toggle() 
            // but well, having class hidden though it is not 
            // hidden makes is not so nice...
        })
    </script>

</body>
</html>

A bit more complicated, but I think this is a proper solution. The advantage is that flickering is prevented and that it works if JS is not enabled. And it doesn't require jQuery.



回答11:

After some time of thinking I've got the idea to the following solution. Compared to my other solution I have reduced it to the essential part (and used this to add a class by JS):

<html>
<head>
    <style>
        /* This could be also part of an css file: */
        .container-with-hidden-elements .element {
            display: none;
        }
    </style>
</head>
<body>
    <div class="container">
        <script>
            document.getElementsByClassName('container')[0]
                    .className += ' container-with-hidden-elements';
        </script>

        <div class="element">Content that should be initially hidden if possible.</div>
    </div>
</body>
</html>

The script tag gets executed immediately and adds a class to a container. Within this container there are some nested elements that get now hidden because the container has got the special class and there is a CSS rule that now has an effect.

Again, this happens before the remaining html gets processed (prevents blinking). And also, if JS is disabled, all the elements are visibly by default - what may be called Progressive enhancement.

Not sure if this works in every browser. But IMO it would be simple and neat solution.