12

I need to check if a CSS rule exists because I want to issue some warnings if a CSS file is not included.

What is the best way of doing this?

I could filter through window.document.styleSheets.cssRules, but I'm not sure how cross-browser this is (plus I notice on Stack Overflow that object is null for styleSheet[0]).

I would also like to keep dependencies to a minimum.

Is there a straightforward way to do this? Do I just have to create matching elements and test the effects?

Edit: If not, what are the cross-browser concerns of checking window.document.styleSheets?

Marco Bonelli
  • 48,251
  • 16
  • 95
  • 101
George Mauer
  • 103,465
  • 117
  • 349
  • 581

5 Answers5

9

I don't know if this is an option for you, but if it's a single file you want to check, then you can write your error message and toggle the style to hide it in that file.

<span class="include_error">Error: CSS was not included!</span>

CSS file:

.include_error {
    display: none;
    visibility: hidden;
}
Smamatti
  • 3,882
  • 3
  • 29
  • 42
  • Yeah, this was similar to my current tactic. Best I could do for now is `.css-file-loaded-marker { z-index: -98256; }` and `$('

    ').addClass('css-file-loaded-marker').css('z-index') == -98256` I have no idea how cross browser that really is, do all browsers support z-indicies like that? Do all apply css to a detached element?

    – George Mauer Nov 01 '11 at 20:03
  • 1
    Yes, I think so. http://www.w3schools.com/cssref/pr_pos_z-index.asp I like my solution more since it has less overhead and works even when JavaScript is disabled or jQuery couldn't load. – Smamatti Nov 01 '11 at 20:09
  • Yeah, I think its a fine solution, you got my upvote. In my case I need to know from JS as I have no control over the html (this is a jquery Ui widget) – George Mauer Nov 01 '11 at 20:11
4

I test for proper CSS installation using javascript.

I have a CSS rule in my stylesheet that sets a particular id to position: absolute.

#testObject {position: absolute;}

I then programmatically create a temporary div with visibility: hidden with that ID and get the computed style position. If it's not absolute, then the desired CSS is not installed.


If you can't put your own rule in the style sheet, then you can identify one or more rules that you think are representative of the stylesheet and not likely to change and design a temporary object that should get those rules and test for their existence that way.

Or, lastly, you could try to enumerate all the external style sheets and look for a particular filename that is included.

The point here is that if you want to see if an external style sheet is included, you have to pick something about that style sheet that you can look for (filename or some rule in it or some effect it causes).

jfriend00
  • 580,699
  • 78
  • 809
  • 825
  • The problem is this solution requires control over the css file. What if you don't have that? I want to test for example that a developer remembered to include the css required for a third-party widget. I could of course pick one of the rules in there but fragile fragile fragile. – George Mauer Nov 01 '11 at 20:19
  • You're going to have to look for something! You can either look for an included style sheet with a particular filename or you can look for the existence of a particular rule. Pick what you want to look for. You have to look for something. I made one suggestion, but you can look for a particular rule that's already in the style sheet if you want. Yes, it's slightly brittle if the implementation changes a lot, but you have to look for something so if the entire file can change, then you have to accept some possibility that you detection method might break in the future. – jfriend00 Nov 01 '11 at 20:22
  • Yeah, I'm not against looking for rules, but looking for the *effects* of those rules is far more fragile because you have to balance "something they're not likely to change" versus "effect that is unlikely to originate in some other rule". If you can just test for the presence of a rule directly you will eliminate half of that equation. – George Mauer Nov 01 '11 at 21:17
  • @George Mauer - If you want to examine the stylesheet directly, you can though it's a bit of a pain to do cross-browser. But, examining the effect on a custom created div is no more fragile and a lot simpler to do cross browser. You create the div with only the targeted id or class and if you aren't getting the effect you want, then the desired rule must not be active. – jfriend00 Nov 01 '11 at 21:24
3

I would use a css selector like this from within your jquery widget.

$('link[href$="my-app.css"]')

If you get a result back it means there is a link element that has a href ending with "my-app.css"

Next use this function to validate a specific css property on an element you are depending on. I would suggest something specific to you styles like the width of a container rather something random like -9999 zindex

var getStyle = function(el, styleProp) {
    var x = !!el.nodeType ? el : document.getElementById(el);
    if (x.currentStyle)
        var y = x.currentStyle[styleProp];
    else if (window.getComputedStyle)
        var y = document.defaultView.getComputedStyle(x, null).getPropertyValue(styleProp);
    return y;
}

Like this

getStyle($('#stats-container')[0], "width") 

or

getStyle("stats-container", "width")
Matthew.Lothian
  • 1,994
  • 15
  • 21
  • Good idea actually. It wasn't mentioned so far in this thread but "simply check that link exists on the page" is a perfectly valid approach. Though I would always recommend providing a setting to suppress that check in case that css got renamed or combined. – George Mauer Dec 20 '13 at 15:26
  • @GeorgeMauer If i were building a js plugin that relied of css, I would make the js dynamically load the linked css into the page and run a callback on load. This way you control the file name and when it is loaded / available. – Matthew.Lothian Jan 02 '14 at 05:47
  • We're discussing minutiae here but I would be furious if I found a component that did that with no override since it breaks the entire point of combining your js – George Mauer Jan 02 '14 at 14:18
2

Here is what I got that works. It's similar to the answers by @Smamatti and @jfriend00 but more fleshed out. I really wish there was a way to test for rules directly but oh well.

CSS:

.my-css-loaded-marker { 
  z-index: -98256; /*just a random number*/
}

JS:

$(function () { //Must run on jq ready or $('body') might not exist

    var dummyElement = $('<p>')
                  .hide().css({height: 0, width: 0})
                  .addClass("my-css-loaded-marker")
                  .appendTo("body");  //Works without this on firefox for some reason

    if (dummyElement.css("z-index") != -98256 && console && console.error) {
        console.error("Could not find my-app.css styles. Application requires my-app.css to be loaded in order to function properly");
    }
    dummyElement.remove();
});
George Mauer
  • 103,465
  • 117
  • 349
  • 581
0

If you are worried about not being able to edit other people's stylesheets, you can proxy them through a stylesheet of your own, using import

@import url('http://his-stylesheet.css');
.hideErrorMessage{ ... }

This is enough if you just want to know if your code is trying to load the stylesheet but won't help if you need to know if the foreign stylesheet was then loaded correctly.

hugomg
  • 63,082
  • 19
  • 144
  • 230
  • I don't get it, how does this tell me if his-stylesheet.css was loaded? The specific concern is that I have a jQuery widget that has css dependencies and I want to console.error a message if they are not loaded – George Mauer Nov 01 '11 at 23:32
  • The idea is that you would change all references in your code from "his-StyleSheet.css" to "myProxyStylesheet.css". As I originaly mentioned, this is probably not very useful in your case (since you actually want to detect the foreign stylesheet) but it is useful if you think the problem might come from just forgetting to include the stylesheet in the first place. – hugomg Nov 01 '11 at 23:40