In my Angular application I want to load the css files in a modular way - each module has it's own css file. This way I can add, remove or move modules easily.
The best way I found so far to do it is by creating a service:
angular.module('cssLoadingService', []).factory("CssLoadingService", function () {
return {
loadCss: function (url) {
if (document.createStyleSheet) { //IE
document.createStyleSheet(url);
} else {
var link = document.createElement("link");
link.type = "text/css";
link.rel = "stylesheet";
link.href = url;
document.getElementsByTagName("head")[0].appendChild(link);
}
}
};
});
Each controller loads it's template css.
Although I inject the path (by another service), still it feels like I'm breaking the seperation between the logic and the view.
It there any other elegant way (that doesn't includes packing the css files into one huge file)?
If your target is HTML5 browser, and assuming that you have a view per module, you can use scoped stylesheets in your views to accomplish this. If you wish to use a css file, you can use #import syntax to load the css file into the <style> tag. Here is a HTML of a view:
<div>
<style scoped>#import url('main.css')</style>
<h1>This is Main and should be Gray</h1>
</div>
Check out this plunker. It worked for me in the latest version of Chrome (27.x) and Firefox (21.x) under Mac OS X.
Please note that many recommend against the use #import for performance reasons. In fact, you can see that there is slight delay between loading of the page and style being applied.
Related
I am using Preact 3.0. I have a few style tags in the template index.html file. The purpose is to it keep it during building.
For example,
<style id="keep-this-tag">
some-styles-that-should-not-be-put-in-style.css-file
</style>
You need the tags themselves to stick around?
If so, just use the following config, or add to your existing:
// preact.config.js
export default (config, env, helpers) => {
const critters = helpers.getPluginsByName(config, 'Critters')[0];
if (critters) {
critters.plugin.options.mergeStylesheets = false;
}
}
Critters is used for critical CSS inlining and, by default, it merges your style tags together. Easily disabled though, hope this helps.
Edit: With prerendering disabled, Critters will strip all CSS, as it's all thought to be "unused". To disable Critters, you can use the --no-inline-css flag, i.e., preact build --no-inline-css.
You do lose out on the inlining, but there's no way around it.
I'v defered all my CSS using
media="none" onload="if(media!='all')media='all'"
and images using yall.min.js
But PageSpeed Insights continues claiming it (and the images are visibles too)
How do I could optimize this?
Thanks, Ari
I'm using JavaScript to asynchronously load external CSS files.
Similar to old solutions where one would put scripts before the closing </body> tag, I'm now introducing data-attributes to create <link> tags, so they're made asynchronous automatically:
HTML
<div data-dom="link" data-href="#asyncCssBundle" data-media="screen"></div>
<div data-dom="link" data-href="#printBundle" data-media="print"></div>
jQuery
/**
* Loads an array object of CSS files in async mode
* stops render blocking CSS loading
* good for fonts and #imports
* #prop {object} asyncLinkTag data representation of a link tag on a div element
*/
function loadCssAsync() {
var arr = [];
$.each($('[data-dom="link"]'), function () {
var el = $(this),
link = $('<link />').prop({
href: el.data('href'),
rel: el.data('rel') || 'stylesheet',
media: el.data('media') || 'screen'
});
arr.push(link);
});
$(document.head).append(arr);
}
$(function(){
loadCssAsync();
});
Additionally I distinguish in SCSS between above the fold CSS and backgrounds, fonts, print, ...
If you really want to put an effort in it, the above the fold CSS can go inline. But I find it rather tricky to pull this off on a larger project. So I'm fine with async loading backgrounds and fonts. However, for fonts it's now clear they're loaded afterwards, similar to a FOUC or call it "Flash of Loading Font". It's good to do some research on a solid substitute font so it doesn't change your layout too much.
What are good ways to detect whether a style sheet has loaded using vanilla JavaScript? I understand they do not have the same load event that images and scripts fire.
Loading as packed into a .js file (like with WebPack 'loaders') is not an option.
2022 update: All major browsers have now supported onload= on <link rel=stylesheet> tags for years, so that would be the obvious way to detect when CSS has loaded. Not also that external stylesheets in the head are blocking during page load, but can be added later with JS to make them asynchronous. It’s that scenario in which my question is relevant.
Test page: https://alanhogan.com/files/async-css/head-async-test-with-js.html
<link> elements have load and error events, but they are garanteed only for Chrome, Firefox and Opera. If you don't need to support IE or Safari, I think this is just enough:
<link rel="stylesheet" href="some_style.css" onload="anounceReady()">
EDIT: Just tested with IE11 and IE8, onload is supported but onerror isn't. I have no Mac at hand so I don't know how Safari handles them.
If you are going to support browsers don't have load event for <link> elements, or very old Chrome/Firefox, there is a commonly used easy dirty but working solution. Add a piece of probing rule set at the end of your CSS file, and detect the computed style of a certain probing element (usually invisible) via JavaScript.
HTML:
<div id="probe"></div>
CSS:
#probe {
position: absolute;
z-index: -1000;
}
JavaScript:
var probeStyle = getComputedStyle(document.getElementById('probe'));
probeStyle.zIndex; // expect "-1000" after CSS is loaded
Something like this:
function checkSheetLoaded (urlSpec) {
var ss = document.styleSheets;
for (var ii = 0, max = ss.length; ii < max; ii++) {
if (ss[ii].href.indexOf(urlSpec) >=0)
return true;
}
return false;
}
checkSheetLoaded('foo/bar.css');
Basically iterates over the stylesheet collection looking for a string match.
Say I'm embedding a bit of HTML code in an existing website. I'd like to know what CSS classes are already available. Currently I could do this as follows:
View the source for the page
Search for links that include .css files
Browse the contents of those until I find a useful class
That's tedious, and not exhaustive.
What's a better way?
EDIT You can also do this in Chrome:
Inspect Element
Select "Resources" tab
Navigate to Frames/../Stylesheets
View contents of individual stylesheets
I guess what I'm looking for is a higher level, interpreted view of the CSS styles available: not simply the contents of the CSS files. So if one style was defined identically in multiple places, I'd only want to see it twice. If two different styles applied to the same element, I'd want to see the two side by side.
Let's assume I can't do this by embedding code.
Press F12 in Chrome and select a magnifying glass.
In IE it's Also F12 and then select a little arrow.
Firefox has a similar feature or you can download Firebug which is great for web developers.
I think Web Developer plugin for firefox might be help you. You can add it from here.
The W3 CSS validator tool http://jigsaw.w3.org/css-validator/ will show all available css styles available to a webpage you specify, underneath a list of faulty styles.
copy this code immediately before the closing tag of the page's body :
I got code from here: http://snipplr.com/view/6488/
Tested in Chrome
//CODE
<div id="allclasses" style="text-align:left">
</div>
<script type="text/javascript">
var allTags = document.body.getElementsByTagName('*');
var classNames = {};
for (var tg = 0; tg< allTags.length; tg++) {
var tag = allTags[tg];
if (tag.className) {
var classes = tag.className.split(" ");
for (var cn = 0; cn < classes.length; cn++){
var cName = classes[cn];
if (! classNames[cName])
{
classNames[cName] = true;
}
}
}
}
var classList = [];
for (var name in classNames)
classList.push(name+'<br />');
document.getElementById('allclasses').innerHTML = classList.sort();
</script>
Apparently adding <link rel="stylesheet" ... in the document body is considered a bad practice by W3C standards. The same for adding <style> blocks in the body...
So are there any standard-compliant solutions to add CSS outside of the <head> tag? Like at the end of the document.
If you only want to include your CSS styles on a specific events, there's nothing stopping you from doing so at the head:
var linkElement = document.createElement("link");
linkElement.rel = "stylesheet";
linkElement.href = "path/to/file.css"; //Replace here
document.head.appendChild(linkElement);
This has the added benefit of adding your stylesheet in an async way, which doesn't block the browser from downloading anything else.
One way to solve that issue is to load the CSS with .get() and, appending it to the head tag only when needed:
JQUERY
var css = "foobar.css";
var callback = function() {
alert("CSS is now included");
// your jquery plugin for a navigation menu or what ever...
};
$.get(css, function(data){
$("<style type=\"text/css\">" + data + "</style>").appendTo(document.head);
callback();
});
The callback function is useful to allow script code that depends on the CSS file to be properly formatted, to run only after the CSS as been added!
Only HTML5 allows it with the scoped attribute, but make sure you declare the DOCTYPE correctly.
<style type="text/css" scoped>
.textbox {
color: pink
}
</style>
I think this standard gets largely ignored by most once you start doing things like server side programming or DHTML.
For static HTML files, you definitely can/should follow the rule of only including CSS within the HEAD tag but for conditional output and interactivity it can sometimes simplify things to have conditional styling as well. Consider that in the end, this convolutes the resulting document. Even though browsers may render it just fine, if you yourself were to look at the source, it's just plain easier to read if all the styles defining the layout/display were within the HEAD. There are, of course, a number of other examples and reasons as to why it's bad practice.
The HTML standard exists apart from things like server side scripting and DHTML i.e. it's not the HTML/SSS/JavaScript standard.
If you are talking about an external css sheet, then the correct way is as follows:
<link href="....link to your style...." rel="stylesheet">
If you want to include an inline css, then you just need to do as follows:
<style>
....Your style here...
</style>