External CSS file load order - html

Is there any way to ensure a specific load order for external CSS files? Normally, multiple external stylesheets can be loaded asynchronously for performance, but I want to allow individual users to override the default stylesheet for a project's documentation (a colleague is color-blind, but it seems like it would be handy for other users of the library) with personal preferences.
For example, let's say I've got this in the docs:
<link rel="stylesheet" type="text/css" href="https://foo.bar/project_stylesheet.css">
<link rel="stylesheet" type="text/css" href=".localprefs.css">
The desired outcome is that .localprefs.css (if it exists) should always override the global project stylesheet.
Is there a guarantee for evaluation order independent of load order? If not, is there a simple way to force the issue?
On edit: The assumption is that .localprefs.css only overrides selected styles from the global stylesheet.

The way you have it guarantees load order. Files or CSS loaded last take precedence.
That said, load order doesn't speak to specificity of the rules in the CSS.
So say you have an element <h1 id="foo" class="bar">. If the first stylesheet has #foo { color: red; } and the last stylesheet has .bar { color: blue; } then the color of the h1 will be red, due to specificity of an ID having precedence over a class. You can't force specificity through the order CSS is loaded. To force specificity, you can use !important.

Yes. It loads in the order it is in the file. So .localprefs.css will load second.
Note that if a selector in the first file is more specific, it will still take precedence(ie, #id vs .class). Any ties will be won by the later file, though (ie, .class vs .class)

Related

Why doesn't #import work when at the end of the main CSS file?

Here's a minimal working example of what I'm experiencing:
index.html
<head> <link rel="stylesheet" href="main.css"> </head>
<p> This is a test </p>
main.css
p {color:purple;}
#import "background.css";
background.css
p {background-color:yellow;}
Trying this in Vivaldi and Firefox, the style in background.css isn't applied. Shouldn't it be though? If I swap the two lines in main.css, #importing background.css first, it does get applied. But why would this matter? Shouldn't background.css be applied in either case?
Note this is the same issue being described in this question and this question, but the answers there don't get at the heart of the question—they recommend importing in the correct order in the HTML file, bypassing this issue altogether.
As already defined in CSS1:
In CSS1, all '#import' statements must occur at the start of a style
sheet, before any declarations. This makes it easy to see that rules
in the style sheet itself override rules in the imported style sheets.
A style sheet that is imported into another one has a lower ranking in the cascading order: the importing style sheet overrides the imported one. Programmers may recognize this as the same model as in Java, Modula, Object-Pascal, Oberon and other modular programming languages.
In CSS1 you should put the #import function at the top of the document (but after any #charset declaration).
The css syntax should be:
#import url|string list-of-mediaqueries;
This can all be found here: https://www.w3schools.com/cssref/pr_import_rule.php

What does "<style>" refer to in Chrome developer tools "Styles" tab?

I can't find any references to this anywhere, in fact Google seems to be willfully ignoring my use of quotes to force its inclusion -- "<style>". In the area where it would usually indicate which CSS file was providing the style on an element, instead it shows <style>:
This is on an element that clearly has no styles defined on itself:
So what does that mean? What is it referring to?
To make the comment an answer:
It means there's a <style> element on the page with those rules, e.g.
<style>
.edit-action-dialog ... { ... }
</style>
You can use e.g. document.querySelectorAll("style") to enumerate those.

Localize entire stylesheet to one div?

On my laravel app, I'm using a forum package called "chatter".
This forum is injected into my master layout, so it looks like this:
nav bar
chatter package
footer
It's injected into a container called <div id="chatter">, and its styles are found in the style sheet chatter.css, which is separate from my main sheet.
The problem is, some of the styles in this sheet are conflicting with my nav and footer. Furthermore, some of the styles in my main sheet are affecting the forum (albeit minimally, so I don't mind making the changes manually).
I can't change the markup, but I can edit the styles.
So how could I make it so that all the styles found in chatter.css ONLY apply to what's inside of <div id="chatter">?
Add #chatter to every style in chatter.css like this
#chatter table{...}
#chatter tr{...}
#chatter td{...}
etc.
If style is for level above the chatter div then add after like this:
html #chatter{..}
body #chatter div{...}
You will have to namespace your CSS as user Nawed Khan pointed out but there is a much simpler way to do that than changing each of your styles manually. This method uses less to handle it for you.
Drop this in a file called chatter.less.
#chatter {
#import (less) 'chatter.css';
}
Then you need to include it on your page...
<link rel="stylesheet/less" type="text/css" href="chatter.less" >
Then you need to include less.js AFTER you've included your .less file.
<script src="https://cdnjs.cloudflare.com/ajax/libs/less.js/2.7.2/less.min.js"></script>
In your .less file you might have to mess with the path to chatter.css, I believe it's going to be relative to whatever file you are including the .less file on.

Efficient way to store and return custom CSS for personalised page visuals

I have a web app that needs to display pages whose CSS values are set via a form. To be clear: not the CSS parameters, just their values are user-defined.
I'm using a framework (jquery mobile). My css file is about 700 lines (the sass file is a little longer but full of comments and variables for colors, margins, etc). There are about a dozen variables inteded to be defined by the user (eg $pageBackgroundColor, $borderWidth, $spanColor), but each variable is used several times in the sass file.
Let's say I now have these dozen variables safely stored in my database, and a user requests a page. How do I provide the necessary CSS?
I could:
compile a minified css file at the time of form submission and link
it when a page is requested (downside: I'm likely to have several thousand CSS files sitting on my server)
compile a minified css text string and dump it between two <style> tags in the <head> (downside: ugliness, no caching, and request handling time increases)
Are there any other options? I looked at one site that does custom visuals for each user and they went for a separate CSS file for each person.
I'm using a Django+Postgres backend, if it's relevant.
You could move the style declarations in which these variables are used to inline CSS, in the <head>. Additionally, you could do this with just a few styles, but it does require you to add more classes to your HTML:
<style type="text/css">
.user-background-color {
background-color: #abc123;
}
.user-color {
color: #abc123;
}
.user-border-color {
border-color: #abc123;
}
</style>
Then your HTML gets additional classes:
<div class="style-1 style-2 user-border-color"></div>
So I went the giant composite heredoc external file route, with the file name saved in the db. It works well enough, but is obviously not fun to edit.

CSS cascade order in Header

Is there a way to force a css link to a file to be the one that is used without relying on cascading order to determine what gets overwritten?
I am using a CMS where I can add new css links but cannot change the cascading order in the header tag:
<link rel="stylesheet" href="new.css" type="text/css" />
<link rel="stylesheet" href="old.css" type="text/css" />
I need "new.css" to overide "old.css" without overwriting the code of old.css. I do not have access to simply change the order of the header code, I so wish I could!
There's no way what you're looking for.
Your last stylesheet would override the previous stylesheet rules.
But if you can use javascript or jquery then you may shift the order like this:
jQuery:
$('link[ref="old.css"]').insertBefore($('link[ref="new.css"]'));
Actually you can if you make the selector more specific. You can do this by simply adding "body" before the actual selector.
Example:
.button {
color: blue;
}
Would be ignored by using
body .button {
color: green;
}
Quick fiddle: http://jsfiddle.net/4cbs5por/
If your CMS allows you to add new CSS links, it should be smart enough to put the new one the bottom. If it's putting it on the top and you don't want to mess with jQuery, you can just copy the content from the "old.css" and paste that into the "new.css" file and vise-versa. That way you'll have the correct content in the bottom file which will override the top link.