Change entire CSS file on refresh - javascript

All other questions I've found relating to this are about changing specific elements, or changing the CSS file with a button, but what I'm looking to find out is:
Is there a script that will swap an entire CSS file whenever the page is refreshed?
I.e. I've got my core style.css and supplementary {color}.css files which replace certain elements in style.css, and I'd like those supplementary CSS files to be loaded randomly on refresh.
Sorry, I don't even know where, to begin with this. Hopefully, someone can offer some pointers?
Thank you.

Fundamentally this is just a matter of picking something at random, e.g.:
<head>
<!-- ... -->
<script>
var sheets = ["sheet1.css", "sheet2.css", "sheet3.css"];
var sheet = sheets[Math.floor(Math.random() * sheets.length)];
document.write('<link rel="stylesheet" href="' + sheet + '">');
</script>
<noscript>
<link rel="stylesheet" href="sheet1.css">
</noscript>
<!-- ... -->
(One of the rare cases where document.write isn't actually a bad solution.) Note the noscript fallback will always use the same stylesheet on browsers with JavaScript disabled.

All you need to do to load a CSS-file with Javascript is to add a <link> element to the DOM/body and it will be loaded automatically.
So in your <head> section you could include a <script> tag that just randomly selects a color.css from an array and generate the link tag, preferably as early as possible in the file to prevent flickering.
<script>
var colors = ['red.css', 'blue.css', 'green.css'];
var colors_idx = Math.floor(Math.random()*colors.length);
document.write('<link href="'+colors[ colors_idx ]+'" rel="stylesheet" type="text/css" />');
</script>
(PS. There are cleaner ways to inject HTML, keeping it concise to focus on the solution. Use your favorite approach, document.write can be a bit fickle.)

Related

Setting href for .less stylesheet through JS

I'm using cookies to find out if the user is in light or dark mode onload of body. I always use the light.less as the fallback/default if a cookie can't be found. So in my <head> I have
<link rel="stylesheet" type="text/css" href="../assets/main.css">
<link rel="stylesheet/less" type="text/css" id="colorMode" href="../assets/light.less">
<script src="../assets/less.js/dist/less.min.js" type="text/javascript"></script>
and my body tag is as follows:
<body onload="checkNav(); checkCookies();" onresize="checkNav()">
The checkCookies() is the function to review the cookie and act accordingly, it is shown below.
function checkCookies() {
var style = getCookie("style");
if (style == 'dark') {
document.getElementById("colorMode").href = "../assets/dark.less";
document.getElementById("switchIcon").innerHTML = "toggle_on";
document.cookie = "style=dark; path=/~sam.walker";
}
else {
//Already set by default
}
}
The getCookie() function simply returns the relevant style cookie
The colorMode stylesheet with href = ../assets/light.less does change as expected to ../assets/dark.less as I've checked with inspector but the style itself does not physically change. I've checked cache and its nothing to do with that. Any help would be greatly appriciated.
Including the stylesheet as a .less format won't work unless you have <script src="less.js" type="text/javascript"></script> added within the <head> section of your page.
Check out the usage information from Less.js here
less.min.js will find references to LESS files and generates CSS from them when it loads.
You are creating a new reference to a LESS file after that, by which time it is too late for less.js to notice.
You need to call checkCookies(); after you have linked to the LESS stylesheet but before you load the less.js script.
Thanks for your help,
Through your info I have found the following (botch) fix:
var elem = document.getElementById('NameOfOriginalLessGeneratedStyle'); //REQUIRES CHANGE ON SERVER CHANGE
elem.parentNode.removeChild(elem);
//Deleted previous styles
less.refresh();
//Loads new style
Should run after stylesheet href change.

Load css file before js

I had a internal style followed by a external style. I noticed the page was blank till the external css didn't load. So i changed it to the below code. Now the external css request is made after the js.
Why for both above and how do i make css request before js. Are there any advantages to it(css before js in below code).
<body>
<style>
body {
background: #333;
}
</style>
<script>
var headHTML = document.getElementsByTagName('head')[0].innerHTML;
headHTML += '<link type="text/css" rel="stylesheet" href="build/main.css">';
document.getElementsByTagName('head')[0].innerHTML = headHTML;
</script>
<!-- The polyfills js is generated during the build process -->
<script src="build/polyfills.js"></script>
Use setTimeout in a function which is called when the body loads.
<body onload="loadPage()">
JS
function loadPage() {
//code to load css
setTimeout(function() {
//code to load js
}, 1);
}
I think that would work. Hope it helps.
This happends because a page is rendered from top to bottom. So I suppose that browser renders you inline styles and goes executing inlines script which uppends link to a style. Then it goes further and executes external script. And after that it loads your newly appended stylesheet.
So, I'd be too naive to ask but why don't you just put your stylesheet link into the head?
Of course you should just put your css files like normal people do :). but if you really want to make it happen, it's gonna get as ugly as this code gets:
<script>
var head = document.getElementsByTagName('head')[0],
link = document.createElement('link');
link.setAttribute('rel', 'stylesheet');
link.setAttribute('href', 'style.css');
var sheet = "sheet", cssRules = "cssRules";
if (!('sheet' in link)) {
sheet = "styleSheet";
cssRules = "rules";
}
var waitForCSS = setInterval(function() {
if (link[sheet]) {
// now you can load your javascript files here like I did with CSS
// or just use any js code you want.
clearInterval(waitForCSS);
}
}, 10);
head.appendChild(link);
</script>
The way to do this is
<head>
<link type="text/css" rel="stylesheet" href="build/main.css">
<style>
body {
background: #333;
}
</style>
</head>
<body>
<!--
Rest of your code in body
//-->
<!--Body is going to end after the below //-->
<script>
window.addEventListener("DOMContentLoaded",function(){
var sc=document.createElement('script');
sc.src="build/polyfills.js";
document.head.appendChild(sc);
});
</script>
</body>
A webpage is parsed from top to bottom.
So, try put the style in your head tag and place the scripts in just before end of body tag
In the script,
add an eventlistener to window when the Dom content Loaded, make a script tag, append src and append it to Head.
It's important to load the style before anything because it's the visual of your page. It's the first thing the user see.
You change css too along with DOM using javascript. So it is preferred to load css first.
Adding a preload mostly did the trick
<link rel="preload" href="build/main.css" as="style">
The browser now made the request for css. Then it makes a call for js. Then it adds CSS tag to the head. Finally, tries to remakes the call to get CSS but since the call is in progress or done it just loads it. There is an issue of FOUC though if CSS takes times.

Find a script in head with jquery based on it's data-attribute

In my content editor you can change custom webfonts on the fly. If you change a font, it deletes all scripts and styles using the data-attribute as an identifier and the new ones then get appended after an ajax call. Now after some testing i realised it work's very well with css files but it ignores the < script >'s. Any ideas? Here is my Script:
$('head').find('[data-fontset-id=ce-fontset]').each(function() {
$(this).remove();
});
For example this is how the head section looks like:
<link data-fonset-id="ce-fontset" rel="stylesheet" href="..........">
<script data-fonset-id="ce-fontset" type="text/javascript" src="//use.typekit.net/xxxxx.js"></script>
<script data-fonset-id="ce-fontset" type="text/javascript">try{Typekit.load();}catch(e){}</script>
In this example, the css file gets removed but the javascript files didnt, any ideas why they are being ignored?
Thanks a lot in advance,
Michael

ASP.NET MVC Inserting CSS file in header via JavaScript depending on screen size

Im working on a MVC3 application, with a masterpage which renders the views in the body.
Now I have 2 css files (different layouts), and I want to select the CSS depending on the screen size of the client.
Everything works with the code below, however, only for the index page, whenever I go to a second page, whatever it is, no CSS is rendered at all.
The code below is placed in the HEAD section of the masterpage.
<script type="text/javascript">
var css = './Content/SiteWide.css'
if ($(window).width() < 1140) {
css = './Content/SiteNarrow.css';
}
var tempcss = '<link href="TEMPCSS" rel="stylesheet" type="text/css" />';
var cssLink = tempcss.replace("TEMPCSS", css);
document.write(cssLink);
</script>
So somehow the css doesnt load again when you go to a second page (all using the same masterpage), do you guys have any ideas?
thanks
Use CSS media queries instead of Javascript.
<!-- dropped rel attribute -->
<link media="only screen and (max-width:1139px)" href="SiteNarrow.css" />
<link media="only screen and (min-width:1140px)" href="SiteWide.css" />
Ideally you create one CSS file for one state, and have another override that when conditions are met.
<!-- dropped rel attribute -->
<link href="base.css" />
<link media="only screen and (min-width:1140px)" href="override.css" />
I believe you need to use Url.Content(). I.e.
#Url.Content("~/Content/SiteWide.css");
The pathing may be incorrect when you navigate from your Index page if you use
./Content/SiteWide.css
I've usually found Url.Content() to be the right thing to do when pathing to files in the project
Pro-tip: Don't use static file locations. Make use of Url.Content.
Your code would look like:
var css = '#Url.Content("~/Content/SiteWide.css")';
Try this out and see if it works. From experience I've had static locations sometimes not work as expect, whereas Url.Content did the trick for me.
I recommend implementing Responsive Web Design
http://www.sitepoint.com/responsive-web-design/#fbid=UhFHwQrRwnn
You can use what are called "Media Queries" to dynamically apply different css files or properties as the screen size changes, in real time. Very cool!

Jquery to merge all referenced pages into root page?

This sounds a little obscure, but...
Is there a technique in Jquery (or just straight javascript) to step thru all the external CSS and JS file references in an HTML file and replace the references with the contents of the files.
So instead of:
<link rel='stylesheet' id='style-css' href='http://domain.com/style.css' type='text/css' media='all' />
<script type='text/javascript' src='http://domain.com/js/domain.js'></script>
..it takes all the stuff from those files and sticks it into the rendering html to make one big html doc...?
<head>
...
<style type="text/css">
hr {color:sienna}
p {margin-left:20px}
body {background-image:url("images/back40.gif")}
.etc {color:red}
.etc {color:red}
.etc {color:red}
</style>
<script type="text/javascript">
function message()
{
alert("This is an alert");
}
etc
etc
</script>
</head>
<body>
...
</body>
Add this script..
$("script").each(function() {
var script = $(this);
script.load(script.attr("src"));
script.removeAttr("src");
});
$("link[rel='stylesheet']").each(function() {
var link = $(this);
link.after("<style type='text/css'></style>").next().load(link.attr("href"));
link.remove();
});
..and you can test it with..
alert($("head").html());
..when it's all done.
(And I don't see any reason in doing this ;)
The only place I can imagine that makes sense is if you run Javascript on the server, using Rhino or similar.
You can do as Sverre suggests and load the files yourself from the browser instead of letting the browser do it, but I can't see any scenario where that would be useful - you have the same number of background requests and end up with the same result, so the only thing you gain is extra work for yourself and probably some extra delay in rendering the page. Or do I misunderstand your goal?
On the server, on the other hand, it can make sense, as the browser can save a load of requests by getting all the external resources in the same document. Is this what you want to achieve?

Categories