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>
Related
I am using angular ui router to do my routing for my application. I am essentially doing a collection of d3 visualizations, with each state/partial being it's own visualization.
Something like this
/#/line_graph?dataset=foo
/#/heat_map?dataset=foo&month=December
This worked fine when I just had to worry about the line graph.. "state" I guess we can call it.
Now, I am introducing a heatmap visualization into the mix. I found one that I liked and just copied the css directly from the example.
However, I now am finding that this css is conflicting with the styling for the line graph. I tried to put the link tag inside my partial, like so
index.html
<body ng-controller="ParentCtrl">
<main class='container-fluid' ui-view></main>
</body>
heatmap.html (the partial)
<link href='/path/to/my/stylesheet' rel='stylesheet' type='text/css'>
This did not work.
I then tried a more hackish take on this approach.
<div ng-if='loadHeatMapStylesheet'>
<link href='/path/to/my/stylesheet' rel='stylesheet' type='text/css'>
</div>
And my controllers
visualizationControllers.controller('ParentCtrl', [
'$scope',
function($scope) {
$scope.loadHeatMapStylesheet = false;
}
]);
visualizationControllers.controller('HeatMapCtrl', [
'$scope',
function($scope) {
$scope.loadHeatMapStylesheet = true;
}
]);
This also did not work, I am still seeing the conflicting styles. Now, I know that I could just go in and change the css so that things aren't conflicting, but I am simply going to run into this problem again the next time I want to try to add a new visualization.
So, given that I don't know a ton about CSS, is there a way to do what I am asking?
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.
I have this simple import of a stylesheet with media-query condition:
<style>#import url(/red.css) (min-width:400px) and (max-width:599px);</style>
I was assuming that browser will not use and not even download the stylesheet. However, stylesheet gets downloaded (tested in Chrome). Therefore I want to ask, if there is simple pure-CSS way how to make browsers not covered by media query to ignore and forbid them downloading the stylesheet.
Thank you for any help.
EDIT: I will re-phrase my question. Can I by using CSS3 specify stylesheet which should be loaded by browser depending on media-query condition (viewport width) ?
Well as #BoltClock and #Wesley Murch already mentioned, the browser will download the CSS even if is not able to supported or even if is not going to use it at that time, cause he needs to be prepared for the time he will be able to do so.
So if you really do not want to download the CSS file until something happens, the you can try to validate when the page loads if certain conditions are meet and if so, then you can do a "lazy load" and store the commented code (type 8 element, that would be in this case your style tag) inside a newly created style tag child, and that will make the browser to validate the newly created content and will download the CSS file for the style to work.
Any question you may face trying to implement it, do not hesitate in asking some clarification, maybe i can help you with your problem.
UPDATE:
I already tested it and IT WORKS :D, so you can use this code to start, hope it helps
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>TEST CODE</title>
<script type="text/javascript">
function test(){
var elems = document.body.childNodes;
alert(elems);
for (var i = 0, il = elems.length; i < il; i++) {
var el = elems[i];
alert(el.nodeType);
if (el.nodeType == 8) {
var style = document.createElement('style');
style.innerHTML = el.nodeValue;
document.getElementById("css").appendChild(style);
break;
}
}
}
</script >
<style id="css">
</style>
</head>
<body onload="test()">
<!--#import url(red.css) (min-width:400px) and (max-width:599px);-->
</body>
</html>
NOTE:
I have not tried this on a style tag, just in images and stuffs like that, but i am sure (i have tried) that if you comment your style tag the browser do not download the CSS file, so maybe this is the way to go to accomplish what you want.
I have a messaging tool within the website I am currently working on. The idea is to have a header div and a details div (display="none") for each message.
Ideally, if javascript enabled, I have just the header showing and when the user clicks on it, the details div slide open.
This is fine but how should I work it if javascript is disabled? I was thinking of expanding all messages if disabled, but I don't want a flicker briefly when the page loads of all images open and, if javascript enabled, they collapse.
I'm using ASP.NET and was thinking of checking javascript status of the browser server side but i found out that it can't be done cleanly.
Any suggestions on how to achieve this?
One option is to place this in your head (after the defined styles):
<noscript>
<style type="text/css">
#mydivid {display: block;}
</style>
</noscript>
EDIT: Ive actually posted a better answer, which works off a correct default state.
Actually, the most semantically correct way that you could do this is to append another stylesheet to the head via javascript containing styles that will be implemented if javascript is enabled.
In your example, you will retain the default display for the elements in question.
Then you will create an additional stylesheet (js-enabled-styles.css for example), and place your display:none within that.
Then, in a script tag in your head you will append an additional stylesheet. Using jquery this would be:
$('head').append('<link rel="stylesheet" href="js-enabled-styles.css" type="text/css" />');
You are right the server can only tell you if the browser has JavaScript, it has no clue if it is enabled or not.
Things you can try is do not use onready or onload, just put the lines at the bottom of your JavaScript to hide the content. You might even want to place it directly after the elements on the page.
<div id="foo">
asdf
</div>
<script type="text/javascript">
jQuery("#foo").css("display","none");
</script>
One side note, sounds like you should be using a definition list instead of two divs. Would make probably more sense to a person using a screen reader.
I believe you're looking for the <noscript> tag.
You could achieve the result you describe in one of several ways, but here's a fairly straightforward one. Define your default style for the divs to be the following:
<style type="text/css">
div.details
{
display: none;
}
</style>
And after this style tag, use a noscript block to override the default (JavaScript enabled) style, as such:
<noscript>
<style type="text/css">
div.details
{
display: block;
}
</style>
</noscript>
There is a portion of my website where I am using a country's flag as an icon for a list element.
For instance, I have:
<ul>
<li id="at">Austria</li>
<li id="de">Germany</li>
</ul>
The accompanying CSS looks like this:
#at {
list-style-image: url('at.png');
}
#de {
list-style-image: url('de.png');
}
Is it possible to replace this with a macro so that I don't need to redefine the CSS for each country? Something like a C-style macro would be awesome, but I'm not sure if CSS supports this sort of thing.
ie
#_country {
list-style_image: url('_country.png');
}
CSS itself doesn't do this, but you can always serve the CSS from a PHP script or similar, doing the macro processing server-side to generate the separate rules from a list of countries.
Since CSS itself does not have itself a macro system, you always have to write all the rules explicitly. Hence you may choose the server side solution (which adds an extra overhead to the loading), or using your text editor's macro or snippet facilities, you can easily generate the rules by yourself.
An interesting thing would be, if CSS had support for string concatenation and the attr() function to be used outside the content property, so someone could write:
.languages {
background-image: attr(id) ".jpg";
}
Short answer: No.
Longer Answer:
You should not rely on JavaScript for such a feature, since not everyone has JavaScript enabled and it would be like breaking a fly on a wheel...
Except for generating it via PHP, Perl, Python (live on serverside, or just once on your PC and save the file as *.css) or something there isn't anything you can do to save you the hassle of copy / pasting this 3 lines and changing them for each country.
So, just do it the annoying way ;)
If it's only those three lines i think you'll have your list put together very fast.
One of the possible solutions:
<!-- our lovely list-style-image function -->
<script>
function set_list_country(list, country) {
list.style.list-style-image = 'url("'+country+'.png")';
}
</script>
<!-- country list -->
<ul>
<li id="at">Austria</li>
<li id="de">Germany</li>
</ul>
<!-- country list styling -->
<!-- note: this goes below your list, or else create onload function -->
<script>
set_list_country(document.getElementById('at'), 'at');
set_list_country(document.getElementById('de'), 'de');
</script>
Regards.
No, you can't do this in plain CSS because the CSS language hasn't control structures or anything like that wich will allow you to dinamically generate CSS code.
Instead, you can use a javascript solution as Andrejs pointed or a solution based on CSS variables coded in PHP.
Whilst generating the CSS server side in script is an option. I prefer simple javascript here.
Some commenters have pointed out that if JS is not available then users wont see the flags....but what else wont work if js is disabled - just about every '2.0' web site!
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Untitled Page</title>
<script type="text/javascript">
function initFlags() {
var flagListItems = document.getElementsByTagName("li");
for (var i = 0; i < flagListItems.length; i++ )
{
var li = flagListItems[i];
// use any prop you want to build the url - i used an expando one
// just because i thought it made the code more readable.
var f = li.getAttribute("flag");
if (f == "" || f == null) continue;
li.style.listStyleImage = 'url(' + f + '.png)';
}
</script>
</head>
<body onload="initFlags()">
<ul>
<li id="at" flag="au">Austria</li>
<li id="de" flag="de">Germany</li>
</ul>
</body>
</html>
You can use CSS for simple macros. Here's the CSS coding for "version" that is referenced several times in one of my documents...
.version::after {
content: "42";
}
...then, anywhere in the document I want to use the current version, this...
<span class="version"></span>
...which results in 42.
Here's one where I set up the "lock" emoji. This might be usable for the country flag, inasmuch as they are mostly available as emojis. CSS requires hex coding of a unicode code-point here, sadly, but still, it's doable...
.lockicon::after {
content: "\01F512";
}
...same kind of invocation...
<span class="lockicon"></span>
...which results in π.
Because the text within the content: ""; is straight unicode, not HTML, things like character entities and HTML tags don't work.
In many cases, however, you can use the unicode code-point for a character entity. For instance, while you can't put β in there, you can put the unicode code-point for it, as in "\0000A0". Be sure to use all six HEX digits, otherwise interpretation by CSS may be incorrect, depending on what else you have in the "content" value.
You can use images, too, but to scale them, you have to use transform: scale(n);
div::before {
content: url(image.jpg);
transform: scale(0.75);
}