How to make an addon to an existing style
I've noticed quite a few styles that are basically duplicates of one style with minor changes to them, like changing colors or the font. Instead of making a copy of the style and modifying it, you can make an addon style by taking advantage of CSS specificity. What this means is that for all selectors that you want to modify, you simply make the selector more specific. For example:
Let's say the style you're modifying looks like this:
Now, for an addon style, let's say the only thing we want to do is modify the message class. We want to change it from red text to yellow. Here's what my new addon style will look like:
What I did was prefix "body " to the original selector. By doing this, you're being more specific about things, and the result is that you override the original selector. Notice though, in the addon style we only told it to override the color, but if you look at the original style, it specifies that the font-style is italic. When the original style and the addon style are both enabled, the text will be yellow AND it will still be italic. With that said, we can just as easily add to it; for example, you can change it normal yellow text using the Verdana font:
So, for pretty much every selector that you want to override, you can just prefix it with "body " (that's the word "body" followed by a space character). This isn't the only way to increase specificity, but I would say it's the easiest way, especially if you don't care to look at the original HTML code.
Hmm, but what if you want to modify the body element? We can't use "body body", 'cause the body element will never be a descendant of another body element. Instead, we'll prefix it with "html " since body is always a descendant of the html element:
And what about overriding the html element? Well, I'm not certain of this, but I've been told that "html:root" works, and with a few quick tests of my own, I can confirm that it does.
Just for fun, here are a few more ways to increase specificity. Basically each line adds more to the specificity:
.message
div.message // assuming the original html code was <div class="message">
body .message // same as what I talked about above
body div.message
html body .message
html body div.message
All of these select the exact same thing, but each one is being more specific about things.
I guess that's it. I hope all this helps to prevent people from unnecessarily duplicating styles with minor changes. Feel free to ask questions or make correction if what I say is wrong (I don't claim to be a CSS guru). Thanks for reading.
Let's say the style you're modifying looks like this:
@-moz-document domain(example.com) {
body {
background-color: #000 !important;
color: #fff !important;
}
.message {
color: red !important;
font-style: italic !important;
}
.anotherMessage { color: #6699cc !important; }
// tons more code after this
}
Now, for an addon style, let's say the only thing we want to do is modify the message class. We want to change it from red text to yellow. Here's what my new addon style will look like:
@-moz-document domain(example.com) {
body .message { color: yellow !important; }
}
What I did was prefix "body " to the original selector. By doing this, you're being more specific about things, and the result is that you override the original selector. Notice though, in the addon style we only told it to override the color, but if you look at the original style, it specifies that the font-style is italic. When the original style and the addon style are both enabled, the text will be yellow AND it will still be italic. With that said, we can just as easily add to it; for example, you can change it normal yellow text using the Verdana font:
@-moz-document domain(example.com) {
body .message {
color: yellow !important;
font-style: normal !important;
font-family: Verdana, sans-serif !important
}
}
So, for pretty much every selector that you want to override, you can just prefix it with "body " (that's the word "body" followed by a space character). This isn't the only way to increase specificity, but I would say it's the easiest way, especially if you don't care to look at the original HTML code.
Hmm, but what if you want to modify the body element? We can't use "body body", 'cause the body element will never be a descendant of another body element. Instead, we'll prefix it with "html " since body is always a descendant of the html element:
html body { background-color: #ccc !important; }
And what about overriding the html element? Well, I'm not certain of this, but I've been told that "html:root" works, and with a few quick tests of my own, I can confirm that it does.
Just for fun, here are a few more ways to increase specificity. Basically each line adds more to the specificity:
.message
div.message // assuming the original html code was <div class="message">
body .message // same as what I talked about above
body div.message
html body .message
html body div.message
All of these select the exact same thing, but each one is being more specific about things.
I guess that's it. I hope all this helps to prevent people from unnecessarily duplicating styles with minor changes. Feel free to ask questions or make correction if what I say is wrong (I don't claim to be a CSS guru). Thanks for reading.
Comments
It's also important to know that while you're writing such a style, to overlay another one, with the original style loaded (obviously!), stylish's load order can lie to you about wether or not you've actually gotten the selector specificity right. Stylish.rdf reads from top to bottom, so new styles have natural priority over older ones.
Can we add this to the tutorial?
Example:
existing style:
.nav a { background-image(example1.jpg) !important; } .nav .red { background-image(example2.jpg) !important; }
addon style:
.nav * { background-image(example3.jpg) !important; }
The addon style would just overwrite all of the above, I just want the addon style to come before the existing style.
How would I go about doing that?
addon style:
.nav a[class]:not(.red) { background-image(example3.jpg) !important; }
If my assumption is correct, that will avoid unclassed <a>, and <a class="red">, otherwise, you'll need to use some other property of the anchor, or the anchors' parents.
*
isn't worth anything for specificity, so both.nav a
and.nav .red
beat.nav *
.body .nav a {...}
body .nav red {...}
.nav * would select any element that's nested inside another element with the "nav" class, so that's probably not what you want to do.
Really good tutorial Valacar!
I have no problem using specificity (although for this addon purpose I'd rather not) but I think there are a lot of users that can do simple editing but wouldn't want to deal with modifying all the selectors as well as the rules. In order to create a style with no options (to allow auto-update) but allow user customization, I would like them to just be able to copy some of my code into an addon and modify a rule(s) and have it work.
If the load order can be set to load theirs after mine, specificity wouldn't be an issue, right? I'm wondering if there is a way to set the load order (not in 2008, I know, but now in 2012...)