1

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?

asked Jan 21, 2016 at 16:35

4 Answers 4

2

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.

answered Jan 21, 2016 at 16:46
Sign up to request clarification or add additional context in comments.

10 Comments

This is similar to the other answer but uses 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.
The important thing in this answer is that the JS must be put right after the element in the HTML. The other answer doesn't say that. The further away you put it, the more of the document will be rendered, so you'll get a longer flicker.
In fact is always better put the script tag before </body> element, to make sure that will run after DOM load...
@Barmar, thanks for the explanation. I had the same line of thought about the placement of the script tag, so this helps a lot.
@GuilhermeLopes But in this case we want to run it as soon as possible after the specific element is loaded, not wait for the entire DOM to load.
|
2

You can use:

var aside = document.querySelector("#primary-sidebar");
if (window.outerWidth < 768) {
 aside.className = "collapse";
} else {
 aside.className = "collapse in width";
}
answered Jan 21, 2016 at 16:38

1 Comment

I swear I thought I had tried this previously and it was still flashing the menu open. Maybe I was trying inside of a jQuery ready event. At any rate, I just tried again and it seems to be functioning appropriately. I'm going to sit on it for a few and make sure it works before accepting, but I think this might be it.
1

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;
 }
}
answered Jan 21, 2016 at 16:38

6 Comments

Thank you for sharing this. I agree that the @media CSS rule is appropriate for scenarios like this, but I was trying to utilize the standard Bootstrap classes to avoid having to duplicate the styles inside of a media selector. If I just add the media selector and say display: none; then the collapsible toggle no longer functions.
This won't help if "in" "collapse" styles come from a lib. like @Quantastical said.
@Quantastical If you or your library is relying on JavaScript to handle a collapsible toggle, THAT is the problem. Not the many issues you'll come across by doing it that way. If it's just an issue w/ the library not doing this for you, just find the file, and either edit it directly to account for screen size, or make a custom copy and edit that.
@Dave, I'm not sure I fully understand what you mean by that. How else could you create a toggle switch without JavaScript? I mean, I suppose you could use a hidden checkbox and label, but are people really doing that? How would you set the initial state of the checkbox based on the browser width?
@Quantastical you can still use javascript to run the onclick ...etc, but you set the initial state with CSS. And yes, that's how people do it. It is VERY nonstandard (and bad practice) to use javascript to set the visibility of something based on screen size.
|
0

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.

answered Jan 21, 2016 at 16:41

1 Comment

He needs to put it into document.ready to be able to refer to the element that needs to be modified.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.