Access CSS file contents via JavaScript
you could load the content with a simple ajax get
call, if stylesheet is included from the same domain
Edit after your update:
I tried this code (on FX10) as a proof of concept that uses only one request to the CSS but it seems a bit hacky to me and should be tested and verified. it also should be improved with some fallback if javascript is not available.
CSS (external file test.css)
div { border: 3px solid red;}
HTML/jQuery
<!doctype html >
<html>
<head>
<!-- provide a fallback if js not available -->
<noscript>
<link rel="stylesheet" href="test.css" />
</noscript>
</head>
<body>
<div></div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.js"></script>
<script>
$(document).ready(function() {
$.when($.get("test.css"))
.done(function(response) {
$('<style />').text(response).appendTo($('head'));
$('div').html(response);
});
})
</script>
</body>
</html>
You should see the CSS code inside the div with a red border all around :)
Enjoy.
Is it possible to get the contents of an external css file using javascript to add to an svg file?
If you are able to use JavaScript you can get the contents of your stylesheet as follows:
[].slice.call(document.styleSheets[1].cssRules).forEach(function(rule){
console.log('rule:', rule.cssText)
})
Where document.styleSheets[1]
is your stylesheet.
How do $.get multiple css file contents?
A problem with your code is that $.when()
does not accept an array of deferreds/promises as an argument. From the jQuery doc:
If a single argument is passed to jQuery.when() and it is not a Deferred or a Promise, it will be treated as a resolved Deferred and any doneCallbacks attached will be executed immediately.
So, passing an array of deferreds, just gives you the array right back.
Instead, it needs them passed as separate arguments and it provides the results as separate arguments to .done()
as in:
$.when(d1, d2, d3).then(function(r1, r2, r3) {
console.log(r1, r2, r3);
});
If you have the deferreds in an array as you do in your code, you can use .apply()
to pass them. And, then the results are again not given to you in an array, but in a series of separate arguments to .done()
(again, really inconvenient).
So, you can change this code:
// jQuery get each of the css links
for (var i = 0; i < arrLinks.length; i++) {
var link = arrLinks[i];
arrDeferreds.push($.get(link));
}
// Fetch the css documents
$.when(arrDeferreds).done(function (response) {
var result = response; // response here is an array of Deferred objects
}
to this:
// jQuery get each of the css links
for (var i = 0; i < arrLinks.length; i++) {
var link = arrLinks[i];
arrDeferreds.push($.get(link));
}
// Fetch the css documents
$.when.apply($, arrDeferreds).done(function() {
// copy arguments object into an actual array
let results = Array.prototype.slice.call(arguments);
console.log(results);
}
Or, in ES6, you can just use Promise.all()
which uses arrays:
// Fetch the css documents
Promise.all(arrDeferreds).then(function(results) {
console.log(results);
});
To make a long story short, in any sort of modern Javascript environment, use Promise.all()
instead of $.when()
.
FYI, if you can't use Promise.all()
or a polyfill for it, then I developed this $.all()
implementation awhile ago that lets you use arrays:
// jQuery replacement for $.when() that works like Promise.all()
// Takes an array of promises and always returns an array of results, even if only one result
$.all = function(promises) {
if (!Array.isArray(promises)) {
throw new Error("$.all() must be passed an array of promises");
}
return $.when.apply($, promises).done(function () {
// if single argument was expanded into multiple arguments, then put it back into an array
// for consistency
var args = Array.prototype.slice.call(arguments, 0);
if (promises.length === 1 && arguments.length > 1) {
// put arguments into an array for consistency
return [args];
} else {
return args;
}
});
};
How do you read CSS rule values with JavaScript?
Adapted from here, building on scunliffe's answer:
function getStyle(className) {
var cssText = "";
var classes = document.styleSheets[0].rules || document.styleSheets[0].cssRules;
for (var x = 0; x < classes.length; x++) {
if (classes[x].selectorText == className) {
cssText += classes[x].cssText || classes[x].style.cssText;
}
}
return cssText;
}
alert(getStyle('.test'));
Replacing css file on the fly (and apply the new style to the page)
You can create a new link, and replace the old one with the new one. If you put it in a function, you can reuse it wherever it's needed.
The Javascript:
function changeCSS(cssFile, cssLinkIndex) {
var oldlink = document.getElementsByTagName("link").item(cssLinkIndex);
var newlink = document.createElement("link");
newlink.setAttribute("rel", "stylesheet");
newlink.setAttribute("type", "text/css");
newlink.setAttribute("href", cssFile);
document.getElementsByTagName("head").item(cssLinkIndex).replaceChild(newlink, oldlink);
}
The HTML:
<html>
<head>
<title>Changing CSS</title>
<link rel="stylesheet" type="text/css" href="positive.css"/>
</head>
<body>
<a href="#" onclick="changeCSS('positive.css', 0);">STYLE 1</a>
<a href="#" onclick="changeCSS('negative.css', 0);">STYLE 2</a>
</body>
</html>
For simplicity, I used inline javascript. In production you would want to use unobtrusive event listeners.
Convert CSS file to string in Javascript/Node.js
You just have to load the contents of the CSS file using NodeJS fs.readFileSync
.
const fs = require('fs');
try {
const documentStyles = fs.readFileSync('styles/style.css');
const document = `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
${documentStyles}
</style>
</head>
<body>
<p>Here's the test</p>
</body>
</html>
`;
} catch(e) {
console.log('Error:', e.stack);
}
How to load up CSS files using Javascript?
Here's the "old school" way of doing it, which hopefully works across all browsers. In theory, you would use setAttribute
unfortunately IE6 doesn't support it consistently.
var cssId = 'myCss'; // you could encode the css path itself to generate id..
if (!document.getElementById(cssId))
{
var head = document.getElementsByTagName('head')[0];
var link = document.createElement('link');
link.id = cssId;
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = 'http://website.example/css/stylesheet.css';
link.media = 'all';
head.appendChild(link);
}
This example checks if the CSS was already added so it adds it only once.
Put that code into a JavaScript file, have the end-user simply include the JavaScript, and make sure the CSS path is absolute so it is loaded from your servers.
VanillaJS
Here is an example that uses plain JavaScript to inject a CSS link into the head
element based on the filename portion of the URL:
<script type="text/javascript">
var file = location.pathname.split( "/" ).pop();
var link = document.createElement( "link" );
link.href = file.substr( 0, file.lastIndexOf( "." ) ) + ".css";
link.type = "text/css";
link.rel = "stylesheet";
link.media = "screen,print";
document.getElementsByTagName( "head" )[0].appendChild( link );
</script>
Insert the code just before the closing head
tag and the CSS will be loaded before the page is rendered. Using an external JavaScript (.js
) file will cause a Flash of unstyled content (FOUC) to appear.
Related Topics
JavaScript Function to Add X Months to a Date
Why Does String to Number Comparison Work in JavaScript
Jquery $(Document).Ready and Updatepanels
Angularjs Routing Without the Hash '#'
I Keep Getting "Uncaught Syntaxerror: Unexpected Token O"
Converting a Js Object to an Array Using Jquery
Best Way to Detect When a User Leaves a Web Page
How to Highlight Text Using JavaScript
Display Data Streamed from a Flask View as It Updates
Indexof Method in an Object Array
Evaluating a String as a Mathematical Expression in JavaScript
JavaScript - Track Mouse Position
How Does This Object Method Definition Work Without the "Function" Keyword
JavaScript: Object Literal Reference in Own Key'S Function Instead of 'This'
Why Don't Logical Operators (&& and ||) Always Return a Boolean Result
Advantages of Using Prototype, VS Defining Methods Straight in the Constructor