I'm trying to hide an HTML element using Google Tag Manager, but I am wondering which method is faster, JavaScript or CSS.
I always assumed that inserting CSS itself, will hide the HTML element faster than using JavaScript to insert some inline CSS. However, I tested both and it feels that JavaScript actually hides element faster. However, I don't have numbers that prove my point. What's the logic behind?
JavaScript:
<script>
document.querySelector(".hello-world").style.display = "none";
</script>
CSS:
<style>
.hello-world{
display: none;
}
</style>
CSS is by far the best way to apply styling to any element on page load. This is because CSS can be applied after the stylesheet loads, which is generally before the DOM has been rendered, so you don't get a flicker of content appearing and disappearing.
This is in contrast to JS, which has to wait until the DOM has loaded which means the element will be visible before it's suddenly hidden (excepting cached scripts etc). This issue is known as a 'Flash of Unstyled Content', or FOUC.
As a side note, CSS is hardware accelerated, so if you have any animation you'd like to show, it's also good practice to try and create it using only CSS/SVG instead of JS.
Related
I am writing a free online e-book which needs a few minor formatting tweaks:
http://rperl.org/learning_rperl.html
The "Full Table Of Contents" at the very top of the page starts out by being visible for a few seconds, then finally collapses itself to be hidden. What we need is for it to start as hidden, and not be visible at all for the several seconds while the page loads. You can see that I have already tried to solve this issue by setting "var index_hidden=1;" at the following link, otherwise the table of contents would never hide itself at all:
https://github.com/wbraswell/rperl/blob/gh-pages/javascripts/metacpan_rperl.js#L832-L833
It probably shouldn't matter, but I'm using some custom Perl scripts to generate this file from Perl POD source, I can give more info if needed.
Although the described behavior does not appear for me (OSX + Firefox). Here's what you might do:
Hide the element by default using CSS. Add this to your head element (extend with stronger hiding CSS when needed).
<style>.wait-for-js { display: none; }</style>
And hide your element by adding the class
<div id="index-container" class="hide-index wait-for-js">
Last but not least, to make this trick functional. Remove the class as soon as JS is loaded, which would also mean that other logic has been loaded and you're save to show the table of contents. Be sure to load this JavaScript last thing you'll do.
<script>
document.getElementById('index-container').className = 'hide-index';
</script>
Or if you're using jQuery
<script>$('.wait-for-js').removeClass('wait-for-js');</script>
Welcome to SO!
I've ran into some weird cases of positioning problems when lazy loading CSS in Chrome, e.g. the positioning of some elements (absolute, relative and cascaded) is off by sometimes huge margin.
Basically what I'm doing is leaving out the standard loading of the stylesheet via an link-Tag and instead placing a placeholder span-Tag for the sake of having an easy way to retrieve the URL later on at the end of the body-Tag. After the DOM loaded fully, I replace the span-Tag with a generated link-Tag like this:
loadCSS: function()
{
var el = jQuery('.is_css');
if(!el.length) return;
// Build link element
var linkEl = jQuery('<link />').attr({
media: 'all',
type: 'text/css',
rel: 'stylesheet',
href: el.data('src')
});
el.replaceWith(linkEl);
}
I can verify that the CSS is fully loaded as most of the elements are looking exactly as if I embed the CSS directly in the head-Tag. My guess is that Chrome doesn't correctly calculate positions in some circumstances for absolute or relative positioned elements when the CSS is loaded after the DOM has been loaded.
I would like to provide you with HTML / CSS Snippets, unfortunately it's out of scope to isolate the falsely rendered Elements. So instead I'm asking if anybody encountered similar problems that can cause this behaviour. Maybe there are some general hints on how to fix such problems.
Kind regards
Sutuma,
The methodology you are trying could have strong performance impact.
As a principle CSS need to be loaded before html DOM is rendered to have an effect. My guess is your html is rendered before CSS get loaded.
Here are the option you may try:
1. Load all css in html header tag
2. Reload your html page one css is content is downloaded.
3. You can use html templating with (require js + require css plugin) for lazy loading.
require js ,
require-css plugin
I am building an AJAX-based website where all of website content is being loaded through AJAX.
Some pages have CSS that's being loaded along with content (code follows). Once the HTML and CSS is loaded I run a few scripts to change some image positions, alter width, and so on.
The problem is that sometimes my javascript gets executed before CSS rules get applied. For example: if my div width should be 200px according to the css, sometimes javascript reads it as 1000px, so I get wrong calculations.
My research has not yielded a cross-browser solution to detect not only loaded images but loaded CSS and everything else.
I use jQuery's AJAX function to get the desired HTML (this part is working fine). After I get the HTML I apply it with jQuery's html function.
Once that's done I use this code to load required css:
css = document.createElement('link');
css.rel = 'stylesheet';
css.type = 'text/css';
css.media = "all";
css.href = url;
document.getElementsByTagName("head")[0].appendChild(css);
I could use a timeout function, but it would just be blind guessing, and I want to make sure my script runs when it needs to run. Any sugguestions?
EDIT I have included this image to make explanation clearer
Never tried before, but what about Stylesheet load events? In case IE won't fired the onload event, and you need to support it, onreadystatechange should works.
I'm glad to see I'm not the only one who has this problem.
I have some JavaScript which needs to be run AFTER the CSS styles are applied to the DOM.
I think what ZER0 suggested is a good solution, but I could not use the OnLoad event on my CSS <link> tag because I load a single concatenated/minified JS file at the end of the document, while my concatenated/minified CSS is at the top of the document.
My solution:
Put the essential CSS styles that the JavaScript depends on directly on the DOM using <style> tags.
This way, the styles get applied immediately when the DOM gets loaded. By the time JS is running, the DOM has the essential styles applied.
I think that you are over-complicating the problem. If you set all of your CSS up to only react to a certain parent class--eg: if you dynamically load the about page--all the CSS should look like .about .example {} .about h2 {} etc. The same would go for the contact page .contact img {}
Now, unless your CSS file is absolutely massive, if you include the one file at the top, you can pretty much guarantee that the CSS will be applied.
I have done a bit of a web development faux pas by not starting with a functioning page and then building js functionality on top. The site I am redeveloping is an old site which has lots of pretty jquery animations.
I have gone to great trouble to ensure all page loads can be handled with or without ajax but I have just realised this is entirely pointless since the initial page load produces several elements which load with properties of display:none; or opacity:0; and are animated to be visible on doc ready
I would very much like to rectify this but there are several reasons I did it in the first place:
1: to hide a flash of unstyled menu before a jquery plugin kicks in. (I will replace this with a non js menu and animate into the jquery menu to solve this)
2: The other reason is that I like the initial animation on page load and would ideally like to keep it. But this presents a problem since I would like to have the bulk of the page invisible for js users and visible for non js users on load but how can I ensure that my elements css properties are changed BEFORE the page is rendered - I have tried doing this with jquery but by the time the jquery library has loaded (without caching) my page has already rendered so the content is flashed up before being hidden and animated back in?
This block will be visible only for users with JS turned off.
<noscript>html code here</noscript>
You can add some styles like this:
<noscript>
<style>
#content{
background: red;
}
</style>
</noscript>
You can add the following in your <head>:
<script>document.documentElement.className+='js'</script>
Then you can style javascript-enabled browsers differently using the js class on the html element, f.ex:
html .animate{opacity:1} /* all browsers */
html.js .animate{opacity:0} /* js-enabled browsers */
The class is added already in the head, so there is no flicker in the rest of the DOM.
You can also use the noscript tag, but personally I think this is cleaner because you can administrate the styles in a single stylesheet.
I'm learning Javascript and CSS and have run into an issue where my CSS styles aren't being applied to markup that I'm dynamically generated from XML and writing to document after the page has loaded. I can only assume that the styles aren't being applied because I'm modifying the document after it's already been loaded. Is this correct? If this isn't the case, do you have any ideas as to why the styles aren't being applied?
This javascript code...
$(function()
{
//Dynamically generate markup
strMarkup = GenerateMarkupFromXML();
//Display the dynamically generated markup
document.write(strMarkup);
});
dynamically generates this simple markup...
<div id="accordion"><h3>Title1</h3><h3>Title2</h3></div>
but these styles don't ever seem to be applied and the <h3> tags just get displayed with the default browser style...
h3
{
background-color:#ccc;
color:#003300;
font-size:1.1em;
}
I should also note that when I paste the dynamically generated markup directly into the body, the styles are applied correctly.
Thanks in advance for all your help!
Yes... the styles will be applied to any dynamically added markup.
The document.write() portion of your code may be causing problems here. In general, you should only use document.write() inline as the document is loaded and parsed. If you call it on DomReady as you seem to be doing it will overwrite your entire page, which I guess is what's causing the problem. I haven't tested though.
I'm not that familiar with jQuery, but instead of the document.write() line try doing something along the lines of (untested):
$('body').append('<div id="accordion"><h3>Title1/h3><h3>Title2</h3></div>');
Yes, css applied automatically. Your example don't work because document.write is evil )
It rewrites whole document with your custom styles, I suggest. If you want to use document.write call it in appropriate section of document, not in head. Example:
<head>
<style>
h3
{
background-color:#ccc;
color:#003300;
font-size:1.1em;
}
</style>
</head>
<body>
<script>
document.write('<div id="accordion"><h3>Title1</h3><h3>Title2</h3></div>');
</script>
</body>
Yes, CSS styles are applied to markup that is added after the page loads.
It could be that you aren't actually generating the same code that you think you are. Try selecting the generated code and doing "View Selection Source" in Firefox. This shows you the generated source (i.e. not just the static content that was served when the page was loaded).
Edit
I think there is a problem with using document.write() in the document ready function.. seems to be causing some kind of infinite loop (for me in Firefox, the browser keeps spinning the loading icon on the tab, even though the file is on my local machine). The $('body').append(strMarkup); solution posted by Andy works, though, as does $('body').html(strMarkup);;