I am trying to apply a class name based on the width of the viewport such that it doesn't "flash" before the JavaScript gets loaded and processed.
For example, I have a Bootstrap sidebar that I want to hide by default if the user is on a mobile device. If I just add some logic to document.ready event, then the menu is visible for a split second before disappearing, which is annoying.
To circumvent that behavior, I used document.write to create the open tag for my sidebar:
<script type="text/javascript">
// Prevent flicker of menu before collapsing on small screens
if (window.outerWidth < 768) {
document.write('<aside class="collapse" id="primary-sidebar">');
} else {
document.write('<aside class="collapse in width" id="primary-sidebar">');
}
</script>
...
</aside>
While this resolves the problem, I do get warnings in Firefox about unbalanced trees and I've read that document.write should not really be used in this manner.
Is there another way to add the in width class based on the window size without waiting until after the page is all loaded?
4 Answers 4
Instead of putting the Javascript in document.ready, put the <script> tag immediately after the element in question.
<aside class="collapse" id="primary-sidebar">
...
</aside>
<script type="text/javascript">
if (window.outerwidth >= 768) {
document.getElementById("primary-sidebar").className = "collapse in width";
}
</script>
While this will briefly display the wrong size, it should resize so quickly that the flicker should be unnoticeable. I put this logic in the desktop version, since the processing should be faster.
10 Comments
getElementById instead of querySelector. I'm guessing both behave the same, but I don't notice the flicker, even though I thought I had tried this before (which led me to the document.write idea). I'm pretty sure getElementById has wider range of support so it might be good to use this instead. I thought the getElementById and querySelector stuff was only run after the entire DOM tree was rendered which would result in the flicker. Maybe I'm wrong. Thank you, though.script tag before </body> element, to make sure that will run after DOM load...You can use:
var aside = document.querySelector("#primary-sidebar");
if (window.outerWidth < 768) {
aside.className = "collapse";
} else {
aside.className = "collapse in width";
}
1 Comment
You're going to cause yourself a lot of stress by using JavaScript to handle things like hiding/showing based on screen size.
The standard way to hide/show things based on screen size is with the @media CSS rule
For example:
@media (min-width: 768px) {
#primary-sidebar {
display:none;
}
}
6 Comments
display: none; then the collapsible toggle no longer functions.If you want to prevent your menu from being shown initially, set the element to
display: none;
or
visibility: hidden;
On the other hand you don't need to put it inside $(document).ready(); if your only condition is the width of the window.