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
Related
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.
I'm building a website for a gallery owner that has a lot of images per webpage.
Therefore I want to lazy load the images on the webpage, making the initial load
less heavy. However, I would like to implement this in a "progressive enhancement" way.
I've found a lot of lazy loading methods but they all require fiddling with the html code
in such a way that the webpage would be useless with javascript turned off. (eg. the src attribute of the img tags remains unset until the images is lazy loaded).
To implement a lazy loading method progressivly I think one would need the following:
prevent the browser from fetching the images, even though thers are on the page,
but only do this when javascript is on (so on non-javascript browsers, the images still
load as normal). This should be done without altering the html.
save the src attribute in a data-src attribute
sequentually load the images when scrolling down
Of these three steps the first one seems the hardest one. Even this stackoverflow discussion did not provide an answer that doesn't ruin progressive enhancement.
Has anyone got any ideas?
Since none has come up with an answer, I'll post what I found a reasonable solution.
This problem boils down to the following: while we want to prevent the browser from downloading the images when javascript is turned on, we must be sure the images are downloaded
when javascript is turned off or not available.
It is hard to consistently use javascript to stop loading images on a page when they are
in the "normal" format:
<img src="path/to/image.jpg"></img>
To stop the images from downloading we'd have to remove their src attributes, but in order
to do this, the DOM should be loaded already. With the optimisations a lot of browsers have nowadays it is hard to guarantee that the images aren't downloading already.
On top of that, we certainly want to prevent interrupting images that are already downloading,
because this would simply be a waste.
Therefore, I choose to use the following solution:
<img data-src="path/to/image.jpg" class="lazy"></img>
<noscript>
<img src="path/to/image.jpg"></img>
</noscript>
Notice how the images outside of the noscript tag have no src but a data-src attribute instead. This can be used by a lazyloading script to load the images one by one for instance.
Only when javascript is not available, will the images inside the noscript block
be visible, so there's no need to load the .lazy images (and no way to do this, since
javascript is unavailable).
We do need to hide the images though:
<noscript>
<style>
.lazy {
display: none;
}
</style>
</noscript>
Like the img tags inside the noscript block, this style block will only be visible to the browser when javascript is unavailable.
On a related note: I thought I could reduce the html size by not putting a src or data-src attributes on the lazy images at all. This would be nice because it eliminates
the redundant url from the page, saving us some bandwidth.
I thought I could pluck the src attribute out of the noscript block using javascript anyways. However, this is impossible:
javascript has no access to the contents of a noscript block. The above scheme is therefore
the most efficient I could come up with.
Not specifying a src attribute is invalid HTML, which is unfortunately how most lazy image loaders work.
I am working on a lazyloader that uses valid html markup, github link:
https://github.com/tvler/lazy-progressive-enhancement
A lazyloaded image would be declared by wrapping it in a noscript element:
<noscript><img alt="hello!" src="..."></noscript>
and the final outputted html would be
<img alt="hello!" src="...">.
You can view the whole project on github, which deals with batch loading, event hooking & more, but here's the basic functionality at the scope of a single noscript image:
var noscript = document.querySelector('noscript'), img;
(img = document.createElement('div')).innerHTML = noscript.textContent;
noscript.parentElement.replaceChild(img.firstChild, noscript);
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 am using the Google Webfont Loader to get my webfonts loaded with a callback and it is working fine.
Although, when a couple of components: Google +1 button, Twitter Search Widget and the Add This button is loaded, they add a new stylesheet to the DOM and makes the browser render the site again. This is causing the font-face to disappear and then show for each new stylesheet added to the dom.
I could hide the font entirely until the components are loaded but they tend to be pretty slow so that would leave me with a pretty bad user experience. About 1 sec of a headline-less site.
Andy tips on how to force font-face to not redraw or how to block dynamically loaded CSS from within Google, Twitter and FBs embed scripts?
Update: Demo here http://kristoferforsell.com/dev/fontexample/
This is currently an inherent issue with browsers and the #font-face property. The blink occurs when the font is loaded and the page updates to reflect the font. If you wish to remove the "blink" entirely, the only sure fire way is to include the font as a data URI in the style sheet. Of course, using the standard "safe" fonts will also remove the blink.
Data URIs allow you to actually embed the code for the font in the stylesheet so there's no blink when the page refreshes to show the desired font. Using data URIs, will obviously increase the file size (kb) of any style sheet.
An online converter to get base64 code can be found here
Usage for #font-face would be like so.....
#font-face {
font-family: "My Font";
src: url("data:font/opentype;base64,[ the base64 code here ]");
}
Not sure if it would fix your issue but you could use css to set the visibility of the elements to hidden until the font is loaded. Google's API provides wf-loading and wf-active classes which are added to the body to address this issue.
I always set up a separate stylesheet just for the #font-face rule, and within that put in the following rules, where replace is the class of the element that's being replaced, for you that would just be the p tag.
.wf-loading .replace { visibility: hidden;}
Yours would be
.wf-loading p { visibility: hidden;}
Then as soon as the webfont is loaded, JS puts the wf-active class on the body, and your text shows up. Let me know how that goes and if you have any issues then just drop me a line. It might also be worth doing some searching for "flash of unstyled content" or "flash of unstyled text" as this is a well known and well documented bug.
I can suggest a simple and dirty trick I have used myself to solve issues like this. If you implement this, from the user's side the effect will be that the entire page will load at once (with the correct Web Fonts), but after a delay. Once loaded, nothing will flicker or change.
Wrap your entire page contents in a div and set its visibility to hidden. Then use js to turn on the visibility once the whole page (stylesheets and all) is loaded.
Here's the code:
<head>
<script>
function show()
{document.getElementById('wrapper').style.visibility='visible';}
</script>
</head>
<body onload="show()">
<div id="wrapper">
...your entire page contents...
</div>
</body>
The onload ensures that the visibility is switched on only after the entire body has loaded. Although I haven't used Web Fonts, I use this trick to fade in the entire contents of this website with no changing or updating afterwards. But yes, there will be a delay before the entire page comes into view.
EDIT: I added Google Web Fonts to the site I linked. Still works fine. No font-face flickering.
This is a shot in the dark, as I've not tested it:
Could you create another html page with only those social networking buttons, and then load that into an iframe? Then only set the src to the iframe once the document is fully loaded, so it doesn't hold anything up.
In html:
<iframe id="socialMedia"></iframe>
In script:
$(document).ready(function() {
$('#socialMedia').src = "http://mysite.com/mysocialmediastrip.html";
});
Where mysocialmediastrip.html contains all the social media buttons. Setting the src will cause that iframe to reload and pull in that content, but IIRC, the rest of the page will be left alone -- all of the button rendering will have been done in mysocialmediastrip.html, not in your main page.
I totally understand what you are saying about the delay process, waiting while window loads before you actually show your goods. Abhranil provided a good solution but you can take his solution further. You can use jQuery's ajax to load your specific page content that's using the special font type. Why? because ajax comes with a special function called beforeSend(). Within the beforeSend function(), you can load a very cool gift animation that will display on your screen, before your main content is ready to viewed.
Use that moment to show some creativity towards your audience, before the main event!
The best and most simple answer is adding font-display: block when specifying a font face
#font-face {
font-display: block; /* Fix flickering */
}
You should also preload the font in the html file
<head>
<link rel="preload" as="font" href="/path_to_your_font.ttf">
<-- repeat for all typeface -->
</head>
I'm using jQuery for pagination. When the content is loaded into the (#results) div, it shows up on the page but I do not see it in the source code.
I believe this is the cause of issues I am having with CSS and jQuery functions related to that (#results) div. The CSS doesn't see any content in the div so the height doesn't actually cover the content in the div.
$("#results").load('pagination.php?page=' + page + ' #results-tbl > *');
I'm loading the #results-tbl div from pagination.php into the #results div on the current page.
Is there a better way to be loading this? What am I doing wrong?
Like Phil said,
View source will only show source when the page initially loaded. Any alterations to the DOM / source after this point will not be reflected in normal browser view source.
In addition to browser inspecting tools like Firebug etc, you can use add-ons like web developer add-on.
With the CSS issues, have a look with firebug to see your IDs and classes are actually hooking up to the CSS properties you have in your CSS file. As long as they hook up any new elements added to the DOM should get styled when added.
With height of your parent element, if you don't set its height explicitly, adding any content via AJAX should cause the parent element to stretch vertically to fit its new contents.