1

I have to modify an existing HTML5 app that has two different types of themes.

For example, I have something like this:

<body class="theme1 theme2">
    <div id="div1">I'm happy with both themes</div>
    <div id="div2">I just want theme 2</div>
</body>

This example is overly simplified. I know that I could just apply theme2 to div2. But the point is that those themes classes are in the body and I cannot "easily" change that.

I naively thought that I could just do something like this in JS:

getElementById('div2').classList.remove('theme1');

But this does not seem to work. I think that this only work on classes directly applied to the element. I would prefer a "pure CSS" solution anyway.

The info that I find seems related to preventing inheritance of specific properties. In my case, I want to prevent inheritance of any property under the theme1 class for div2 and all its children.

7
  • 1
    You can only remove a class from the element that has it. In your case you should remove the class from the body element, or you should add the classes to your divs. Commented Mar 23, 2014 at 22:52
  • Use Jquery ! $('#div2').parent().removeClass('theme1'); Commented Mar 23, 2014 at 22:56
  • @4EACH — The goal is to stop a property being inherited into div2 while letting it apply to div1. Removing the class from the parent would stop it being applied to either. Commented Mar 23, 2014 at 22:58
  • The example provided is very simplistic. The actual app has many parent elements. I cannot remove classes from the body and body is not the direct parent of the element in question. Also, I am not using jQuery. Commented Mar 23, 2014 at 22:59
  • You set the HTML class attribute using Element.className = in JavaScript. Commented Mar 23, 2014 at 23:04

5 Answers 5

5

Properties are inherited, classes are not.

The only way to stop a property being inherited is to assign a value to that property for the given element.

Sign up to request clarification or add additional context in comments.

7 Comments

Right, so there is no way to tell CSS to stop inheriting all properties set by the class theme1? Using the wildcard (*) perhaps? When I look at the element using the WebKit Developer Tools, it is aware of which class each inherited property belongs to.
Correct. The property has to have some value, and it will be (at least for whatever properties you care about here) inherit if it isn't set to something else.
Okay. This is consistent with what I have been reading so far. Basically, I need to use some class associated to div2 to set a value to all properties that I do not want inherited. I was hoping for a solution that just takes theme2 completely out of the equation for div1 and all its children.
It doesn't have to be a class. You can use any kind of selector (or combination of selectors) for the ruleset.
I think that you understand the problem. However, I may not have the proper body of knowledge to fully appreciate your last comment. Could you illustrate in a sample class definition for div2 in my example? (#div2 { what ? })
|
0

The code doesn't work because 'theme1' is not a class of div 'div2'.

I don't know of a way to selectively remove the inheritance as you asked. The closest solution I can think of is to use nesting to create a more specific selector and override the undesired styles. Simple example:

.theme2 {
    font-style: italic;
}
.theme2 #div2 {
    font-style: normal;
}

This would "remove" the italic style from div2. You would have to redefine all the undesired styles. From a maintenance standpoint this may or may not be an acceptable solution. But it does solve the problem.

1 Comment

It solves the problem because the example provided is just a simplistic way to illustrate a concept. The app in question has thousands of elements. Thanks anyway.
0

No, that's not how CSS works. If properties are getting applied to a descendent because of a class on an ancestor, and you cannot change that class or the properties, then you have to override the properties (via a more specific selector) that you don't want inherited.

e.g.

body.theme2 div { background: #000; }
#div2 { background: transparent; } 

3 Comments

The selector doesn't have to be more specific, it just has to match the element you want to change. Specificity rules only apply when multiple rulesets are targeting the same element.
To be very technical, you're correct - the selector can have the same specificity as the one you are overriding, as long as it appears after said rule in the stylesheet (hence the C in CSS). However, I find your comment confusing because the multiple rules in my answer are in fact targeting the same element in the OPs original question.
In the OP's original question, the problem is that the selector is targeting the parent element and he wants to change the properties for one of the child elements (which are inheriting the values from the parent).
0

Let's start with some common.js:

//<![CDATA[
var doc = document, bod = doc.body, IE = parseFloat(navigator.appVersion.split('MSIE')[1]);
bod.className = 'js';
function gteIE(version, className){
  if(IE >= version)bod.className = className;
}
function E(e){
  return doc.getElementById(e);
}
function removeParentClassName(childId, removeClassName){
  var cn = new RegExp('(\s+)?'+removeClassName, 'i'), pn = E(childId).parentNode;
  pn.className = pn.className.replace(cn, '');
}
//]]>

Now on your current page:

removeParentClassName('div2', 'theme1');

1 Comment

This just seems like a very verbose way to do this: getElementById('div2').parent.classList.remove('theme1'); Of course this would work if my actual implementation was just the simplistic example provided to illustrate the concept. The actual app has many levels of elements between the body and the div that I am trying to reach. The example is not to be taken literally.
0

One way you could do this with pure CSS would be to set up you CSS rules like so

.theme1 .div1,
.theme2 .div1,
.theme1 .div2,
.theme2 .div2 {font-style:normal;} /* apply theme1 and theme2 styles here */

.theme1.theme2 .div2 {font-style:italic;} /* apply theme2 only rules here */

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.