I am trying to understand how CSS is evaluated in a specific setting:
Lets assume I have the following content in my <head> tag:
<html><head>
...
<link href="reset.css" type="text/css" rel="stylesheet">
<link href="style.css" type="text/css" rel="stylesheet">
<link href="autocomplete.css" type="text/css" rel="stylesheet">
</head>
<body>
... html ...
<script type="text/javascript" src="/js/script.js"></script>
</body></html>
Now, let's assume reset.css and style.css contain some rules that immediately affect the above the fold content or the the elements in the HTML. However, autocomplete.css only contains class used that are used later by some JavaScript.
Now, let's further assume the browser already downloaded reset.css and style.css but autocomplete.css is still pending.
I am wondering what would happen if the browser would do it encounters the blocking script tag at the end of the page? Obviously, it can render the HTML up to the script tag, but is the execution of the script blocked by the missing autocomplete.css?
Note that the script tag is not a sync.
I've read:
https://developers.google.com/web/fundamentals/performance/critical-rendering-path/analyzing-crp
And there it says that the execution of the JavaScript is blocked until the CSSOM is there.
Now:
1. Will the page start rendering even autocomplete.css has not yet arrived? and,
2. Is the execution of the script.js javascript blocked until the autocomplete.css is there?
Note, I am referring to two different things: rendering and script execution.
All CSS is render blocking. The only exception from this rule would be CSS that your DOM does not yet know about (loaded async, built/loaded on the fly via javascript).
Until your browser didn't resolve (or thinks it resolved) all CSS by building the CSS Object Model, the page won't render and javascript will not be executed. However, resolve does not necessarily mean load. It can mean two things:
load & parse. If it's above 2k lines of code, you're going to notice it when measuring with proper tools. If it's above 10k lines of code, you'll be able to notice it without using any tools. This is regardless if it contains rules concerning elements above the fold or not.
not being able to load/parse (due to network problems or invalid rules) - if an error is returned when CSS is loaded/parsed, it will resolve faster and the resulting differences will be hardly noticeable. If the server does not return an error (and just doesn't respond) - that's going to block your CSSOM from building, your page from loading and your scripts from executing.
Resources:
W3C's CSSOM spec.
MDN's CSSOM resource page
What is CSSOM?
The latest performance recommendations are as follows:
1) Inline all css into the header that the browser needs to render above-the-fold-content. Content which is visible without scrolling.
2) Add all other css to the bottom of the page or better load it asynchronously with something like this: https://github.com/filamentgroup/loadCSS
autocomplete is a css file. As such, it only adds style properties to the classes which are defined in the html. The javascript will still execute correctly, even if the css is missing.
The only thing that might happen is that if the js changes some css styles of the classes which style is defined in autocomplete.css. However even then it's unlikely.
Related
I use two CSS files, one is a little one for my home.html with all the important things for this page and there I pre fetch a bigger CSS file that takes care of the internal structure.
It works as I want but when I try to pass the W3C validation it complains with:
Error: A link element with an as attribute must have a rel attribute
that contains the value preload.
<link rel="prefetch alternate stylesheet" href="/css/internal.css" as="style">
Can I get rid correctly of this?
What is the right way to insert HTML snippet into main HTML file with HTML5 imports?
The answer to more generic question https://stackoverflow.com/a/22142111/239247 mentions that it is possible to do:
<head>
<link rel="import" href="header.html">
</head>
But this doesn't work. I don't need to insert JS and CSS. Only plain HTML markup inserted at the top of <body>. What is the most simple way to do this and keep HTML readable?
The way I have found to do this is to use ASP.NET and .cshtml files and use razor, as seen here:
http://weblogs.asp.net/scottgu/asp-net-mvc-3-layouts
Beyond simply inserting html into other html this also allows you to have consistent navigation bars, footers, etc. and minimizes your code profile. Also, the use of a layout file gives the site a better feel as only a section of the site refreshes when you click an internal link, as opposed to the whole site.
Found a way to do this from html5rocks, but it is far from being readable. This is the ideal way:
<body>
<include src="header.html"/>
</body>
And this is how it is implemented by HTML5 imports:
<head>
<link rel="import" href="header.html">
</head>
<body>
...
<script>
document.body.appendChild(
document.querySelector('link[rel="import"]')
.import
.querySelector('body')
.cloneNode(true));
</script>
</body>
Notes:
not clear how to choose include if both header.html and footer.html are there
querySelector('body') is required to avoid Uncaught HierarchyRequestError: Failed to execute 'appendChild' on 'Node': Nodes of type '#document' may not be inserted inside nodes of type 'BODY'.
not clear how to insert <body> tag contents without the tag itself
HTML5 import doesn't work in Firefox (38) http://caniuse.com/#feat=imports =/
See: http://www.w3schools.com/angular/angular_includes.asp
It says:
HTML Includes in Future HTML. Including a portion of HTML in HTML is, unfortunately, not (yet) supported by HTML.
So this is on its way, but not here yet.
EDIT: If you are able to, I would use PHP, which is close to the level of cleanliness. The link I inclueded shows multiple ways to do what you are trying to do.
Late edit: if it still counts (for those worried about sourcing): http://caniuse.com/#feat=imports
I am creating a mobile simulator that mocks the appearance and functionality of an iPhone (and other devices later) in a web browser, using 100% javascript, HTML5, and CSS, with the simulator fully functional with only client side code.
While trying to accomplish this task with as little modification as necessary to the original app projects themselves to be hosted in the simulator, I am injecting the <script> and <link> tags into the head of the page, then loading the html into a <div> screen.
The problem is that when I load in a new css file, it (obviously) overrides the one I'm using to style the page, and therefor some elements are affected (ex the background changes color).
My question is: Is there any way to limit the "scope" of an external .css file to apply only to objects within the <div> screen? Would it make any difference if instead of me injecting it into the <head> of the page, I inject it into a <style> element in the <div> screen?
UPDATE Support for this feature has been dropped. Please seek other options
Original Post:
You may want to look at scoped styles; see http://css-tricks.com/saving-the-day-with-scoped-css/.
The basic idea is
<div>
<style scoped>
#import "scoped.css";
</style>
</div>
However, you are on the bleeding edge here in terms of browser support. See http://caniuse.com/style-scoped.
One alternative would be to use an iframe.
Simply wrap all you css code inside the selector for parent element, say it's a div with id of foo you'd do the following:
div#foo{
//All your css
}
And convert it as less to css, it will prepend the right selectors. Note that you'll need to take care manually of things like #media queries and so on.
While writing this, the <style scoped> is deprecated by the Chrome team.
As a result I experimented with some approaches and released https://github.com/thgreasi/jquery.scopeLinkTags .
Note: you should only have to use this approach in case that you can't control the imported CSS file. If you can use SASS/LESS/anything to pre-process your CSS, you should prefer that.
A simple way is adding pre-class before all selector in css file.
I find a grunt script can do this:
https://github.com/ericf/grunt-css-selectors
This is how i do it if not using preprocessor in my project. Search for a online preprocessor then load copy paste the css under the parent class/id
.parent{
// copy paste here
}
Example
Find a preprocessor for example https://beautifytools.com/scss-compiler.php works very well for me (I have no affiliation with the given link)
if you are using from a URL add the URL using the load URL button.
Wrap the css code under parent and hit compile then minify.
I had a similar issue and found that Shadow DOMÂ can solve it easily.
let output = d.querySelector('#output')
let shadow = output.attachShadow({
mode: 'closed'
});
shadow.innerHTML = HTMLcontent // HTMLÂ content and style injected
Source
I'm building up my site over at http://royronalds.com, and I'm trying to figure out what order of elements in the <head> makes most sense. Just to take from what I currently have, I have:
<head>
<style> external stylesheet
<meta>
<title>
<link> to favicon
<script> for jQuery
<script> main javascript for site
<script> google analytics, asynchronous script.
</head>
Are there reasons to order these differently so that load times and other issues happen more smoothly, and if so, what would the ideal order be?
Modern browsers wait with any sort of rendering until the entire <head> section is retrieved (including the files linked within it). The order therefore doesn't matter for performance. For Javascript, the order of the files is the order of execution. For stylesheets, the order determines precedence (the rule that was defined last has precedence if all other things are equal).
If you want to optimise client performance, it is strongly advisable to move your Javascript includes to the very end of the <body> element, instead of putting them in the <head> at all. There are more considerations, Yahoo's list of optimisations is well worth your time to read through. Google has some good advice as well.
One thing that can have a big effect is moving <script> tags to the bottom of the page if they are not essential to the content.
For instance, I would move the google analytics <script> tag to be the last thing before the </body> tag on every page. Script tags are "blocking content", so the browser will not continue with a page render until the script has been downloaded and executed. Your main javascript and JQuery files probably can't be moved as easily depending on how you're using them, but analytics for sure can be at the bottom.
Check out the YSlow best practices for more optimization techniques.
Also consider the fact that browsers will halt javascript execution when an error occurs.
Because of this, it is very important that your javascript work on all browsers else you risk your Analytics code not executing and capturing stats...
I usually place my Google Analytics above my own code so it runs first, and if in the rare event that my code breaks or causes JS errors, I am still able to get tracking information.
my order would be:
<head>
<meta> content encoding
<title>
<link> favicon
<style> external/third-party stylesheet
<style> site stylesheet
</head>
<body>
...
<script> google analytics
<script> jQuery
<script> jQuery plugins
<script> site javascript
</body>
by the way, try to antispam your email address...
ie:
<SCRIPT TYPE="text/javascript">
document.write('' + 'example' +'#' + 'example' +'.' + 'fr' + '<BR>')
</SCRIPT>
It works for me...
If you are using Wordpress then you can easily use this plugin: http://wordpress.org/extend/plugins/performance-optimization-order-styles-and-javascript/
and take advantage of it.
Can I load javascript code using <link> tag in my website ?
For example I have a javascript file, test.js, which contains the simple code alert('hello');
Can I make the popup window appear using:
<link href="test.js"></link>
No. There was a proposal to allow:
<link rel="script" href=".../script.js"/>
analogously to stylesheets. This is even quoted as an example in the HTML 4 DTD, but browser implementation never happened. Shame, as this would have been much cleaner.
You need to use the <script> tag to include JavaScript source files:
<script type="text/javascript" src="mysrc.js"></script>
The end tag must be the full </script>, don't abbreviate the way you can with some tags as in <script type="text/javascript" src="..."/>.
Yes, alert statements in the included source will appear when they are evaluated by the browser.
For information on the uses of the <link> tag, see w3.org.
Modern browsers support the preload keyword, which is used to preload various resources, including scripts. From MDN:
The preload value of the <link> element's rel attribute allows you to
write declarative fetch requests in your HTML <head>, specifying
resources that your pages will need very soon after loading, which you
therefore want to start preloading early in the lifecycle of a page
load, before the browser's main rendering machinery kicks in. This
ensures that they are made available earlier and are less likely to
block the page's first render, leading to performance improvements.
A simple example might look like this (see our JS and CSS example
source, and also live):
<head>
<meta charset="utf-8">
<title>JS and CSS preload example</title>
<link rel="preload" href="style.css" as="style">
<link rel="preload" href="main.js" as="script">
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>bouncing balls</h1>
<canvas></canvas>
<script src="main.js"></script>
</body>
Possible rationale why not
link elements are only allowed where "Metadata content" is allowed, typically head, and not in the body. See: Contexts in which this element can be used. All embedded elements that go in the body have separate elements for them: img, iframe, etc.
link elements must be empty, and script may be non-empty. See: Content model
Therefore it is natural to have a separate element for JavaScript, and since we must have a separate element, it is better not to duplicate functionality with link rel="script".
This theory also explains why img and style have separate elements:
img can be placed in the body, so it gets a separate element, even though it must be empty.
style can be non-empty, so it gets a separate element, even though until HTML5 it could not be placed in the body (now it can via scoped, but still not to include external scripts).
Apparently Tim Berners-Lee wanted everything to be done with <a: https://youtu.be/3QEoJRjxnxQ?t=901 !
JavaScript code would generally be loaded using a script tag, like so:
<script type="text/javascript" src="test.js"></script>
To answer your question directly, no. Not by that method. However I was led to this question while searching a similar issue which lead me to this question. Seeing the answers already supplied which for the most part are correct I went to check syntax on http://w3schools.com/ . It seems that with HTML5 there is a new attribute for for the script elements in html.
This new attribute allows javascript files to be defered or loaded and executed asynchronously (not to be confused with AJAX).
I'm just going to leave the link here and let you read up on the details yourself as it is already supplied on the internet.
http://www.w3schools.com/tags/att_script_async.asp
The other option for this is, you can dynamically insert a script file into the current document, by creating a SCRIPT tag, setting its "src" attribute to the URI of the script, and then inserting it as a child of the page's HEAD node.
Doing those things will get the browser to fetch the script file, load it into the document, and execute it.
Typically you would use a <script> tag, but actually, you can do <link href="test.js"></link> as you described. Here is a example
I'm wrong here. Apparently, Parcel is doing some special stuff and the final output uses a <script> tag. You need a script tag (even if you use <link> to preload a .js file, you still are forced to use a <script> tag to actually load it).
Leaving this here so that others might not be confused by Parcel's bundling magic as I was.
No. A Link tag like is for CSS files or for relational links (like next).
This is not the way to load javascript into the page. You need to use the <script> tag:
<script language="javascript" src="file.js" />