4

I have a button, which when clicked loads an additional CSS file, that overrides a great part of the basic CSS files. (this is for accessibility purposes if you wonder)

Let's say I have a background and background-color properties used in multiple selectors for input[type='text']. I want to reset/delete those. I DON'T want to set a new value for those background properties, I want to remove them, so that the browser will render everyting as it would by default.

The reason for this is because in high contrast mode with black background color to the body in Firefox, any background set to input or button will override it with a value equal to the text color which will make the value of the input or the button unreadable. But that's another story...

EDIT: Since everybody so far is telling me to set some new property to those, I'm writing it in bold big letters - I DON'T NEED TO SET NEW PROPERTY FOR background. :) The reason behind that if that property is present Firefox defaults it to black if the background set in the high contrast mode is black as well. To test this, go to Preferences -> Content -> Colors and check Allow pages to choose their own colors, instead of my selections above. Here's how my options look.

abpetkov
  • 884
  • 5
  • 11
  • 29
  • You can use the `initial` keyword for most properties; it resets the value to browser default. – Salman A Dec 10 '14 at 15:28
  • Tried already, won't work. As I said I don't want to set new values for existing properties, I want to remove them completely. – abpetkov Dec 10 '14 at 15:29
  • http://stackoverflow.com/questions/4036857/jquery-remove-style-added-with-css-function – epascarello Dec 10 '14 at 15:30
  • 1
    Can't you reload the page with the new stylesheet, instead of dynamically loading it? Personally I think that's reasonable if you are doing this for accessibility reasons. – BuddhiP Dec 10 '14 at 15:33
  • Set it it to "". That will remove the property from the element. Follow @epascarello's link. – ialphan Dec 10 '14 at 15:34
  • 1
    Instead of adding or removing properties, the better way to do it is to put these extra properties in a CSS class and then add or remove this extra class. And if you need override, then use !important. Now it's just about add/removing classes. – frenchie Dec 10 '14 at 15:36
  • Yes, don't be lazy, you cannot remove them, you can only override them using another css or js. This means you **have to set new properties** one way or another. – skobaljic Dec 10 '14 at 15:39
  • Are you trying to remove all the styles or just certain elements? If all: Remove the style attributes and disable the stylesheet. – epascarello Dec 10 '14 at 15:46
  • You can manipulate stylesheets via [StyleSheet interface](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet). It provides a method to remove a rule too. – Teemu Dec 10 '14 at 15:46
  • @skobaljic, no it doesn't mean that. I don't want to set this property at all, kind of set it to `null` (if it existed). At the end I'll just load the stylesheet by itself, rather than on top of the existing, but wanted to make sure if it's possible. – abpetkov Dec 10 '14 at 15:56
  • @epascarello only certain properties for certain elements. For example all `background` properties for `input` – abpetkov Dec 10 '14 at 15:56
  • 1
    I am sure it is not possible. Best you can do is to load same page with other styles, other theme if [website](http://icpdr.org/). – skobaljic Dec 10 '14 at 15:57

5 Answers5

0

Do a css reset/normalize at the beginning in your first css file. Then at the beginning of the second one do it again. You can leave out the first reset, but this will give you consistent results.

g_uint
  • 1,903
  • 3
  • 17
  • 30
0

You can remove the original stylesheet. Just assign it an id and use jQuery.remove(...).


The alternate solution is to alter the first stylesheet to use some kind of namespace+, for example:

/* these are the rules that you want to be removed */
.stylesheet1       { }
.stylesheet1 h1    { }
.stylesheet1 p     { }
.stylesheet1 a     { }
.stylesheet1 input { }
/* these rules can co-exist with the next stylesheet */
nav                { }
article            { }
aside              { }
section            { }

Inside your HTML add the stylesheet1 class to body. When you load the other CSS file (presumably via JavaScript) then you remove this class. All namespaced rules will become ineffective.

* CSS preprocessors e.g. SASS and LESS make it easier for you to manage these rules.

Salman A
  • 262,204
  • 82
  • 430
  • 521
  • Removing the original stylesheet might be my only and best solution. Though your alternate solution won't do the trick, because it will just override the property with another value, which is not what I want. – abpetkov Dec 10 '14 at 16:02
  • Re. alternate solution: no, it does not suggest that you add another class on body and create another set of namespaced rules. Just remove the class and the first stylesheet rules will match no more. – Salman A Dec 10 '14 at 16:29
0

It sounds like the best solution for you is to have two different CSS classes targeting a single input, and toggle back and forth between the two. There are several ways to do this:

CSS:

input[type="text"].a {...}
input[type="text"].b {...}

Here we have two different classes, a and b. When defining the input initially, set class="a". We'll then swap that with b when the button is clicked. Again, there are several ways of doing this:

jQuery:

$('.a').click(function(){
    $(this).removeClass('a').addClass('b');
});

Plain JS

var button = document.querySelector('.a');
button.addEventListener('click', function(){
    button.classList.remove('a');
    button.classList.add('b');
});

This is the generally preferred method for achieving this kind of behaviour. It adheres strictly to standards, in that it separates logic, markup, and presentation into their respective pieces.

Note: The plain JS method listed above uses some pretty modern native JS code. Take a look at You Might Not Need jQuery to find suggestions for making this functionality cross-browser.

Jordan Foreman
  • 3,848
  • 7
  • 40
  • 65
  • That's a good idea actually, but since my styles are set to inputs directly, this won't work for me. – abpetkov Dec 10 '14 at 15:45
  • That doesn't make any sense. Even if you aren't able to add `class="a"` in your markup (which is fair, there might be a ton of inputs). Just remove the `a` class entirely from the example above. Have a set of styles that target `input[type="text"]` and a *separate* set targeting `input[type="text"].b`. Then just add or remove `b` when necessary. You just need to have the styles defined. – Jordan Foreman Dec 10 '14 at 15:54
  • I think I'm just going to remove the existing stylesheets and load new ones, rather than loading the new ones on top of the main ones. – abpetkov Dec 10 '14 at 15:59
0

Instead of adding or removing properties to elements, I think the better way to do it is to put these extra properties in a CSS class and then add or remove this extra class to the elements as needed. And if you need override, then use !important. Now it's just about add/removing classes.

Here's an example in jQuery

.MyControl{background: blue;}
.MyControlAccessibility{background: red !important;}

$(SomeControl).click(function () { $(this).addClass('MyControlAccessibility'); }
$(SomeControl).click(function () { $(this).removeClass('MyControlAccessibility'); }
frenchie
  • 51,731
  • 109
  • 304
  • 510
  • Please don't ever use `!important`. If you find yourself using it, then you're probably doing CSS wrong. – Jordan Foreman Dec 10 '14 at 15:42
  • @JordanForeman: no man, the people who created the functionality didn't do so because they're wrong. Some people misuse it, and others don't understand it. But it's actually designed for such edge cases. – frenchie Dec 10 '14 at 18:46
  • I suppose you're right in that it exists for a reason. While your approach is one of the **very** few instances where using `!important` does make sense, given OPs goal I don't believe this is the correct *approach* to take. I'm biased, since its not my answer :p but also, best practices are best practices for a reason. There are very few instances where I'd consider this the *best* approach (in regards to adherence to web standards, simplicity to read, separation of concerns, etc.) Also, I'll leave this here: http://css-tricks.com/when-using-important-is-the-right-choice/ – Jordan Foreman Dec 10 '14 at 18:53
0

Using a global class on the body is good as mentioned.

Another way could be to put your light and dark "theme"-specific styles into separate stylesheets from the common CSS and then disable the one you do not want. This will avoid conflicts and needing to use !important, and you can keep things clean without having to hack away at various bits of jquery.css().

For example

base.css

a { text-decoration:none; }

dark.css

body { background-color:#000; }
a {color:#fff; font-size:1.2em;}

light.css

a {font-size:1.5em;}

Note that light.css has no properties for background-color etc. so when they switch from dark to light, the defaults will be used again.

To do the switch, you can do something along these lines:

for (var i = 0; i < document.styleSheets.length; i++) {
    var ss = document.styleSheets[i];

    // some browsers store in url, others in href
    if((ss.href || ss.url || '').indexOf('dark.css') > -1) {
        ss.disabled = true;
    }
}

By disabling instead of removing the current one, it should be easier to switch between the two.

Rhumborl
  • 16,349
  • 4
  • 39
  • 45