tags:

views:

2336

answers:

7

Is it possible to have a CSS rule which basically "undoes" a prior rule?

An example:

<blockquote>
    some text <em>more text</em> other text
</blockquote>

and let's say there's this CSS:

blockquote {
    color: red;
}

...but I want the <em> to remain the normal text color (which you may not necessarily know).

Basically, would there be a way to do something like this?

blockquote em {
    color: inherit-from-blockquote's-parent
}


Edit: The code I'm actually trying to get this to work on is actually a bit more complicated. Maybe this would explain it better:

This text should be *some unknown colour*
<ul>
    <li>This text should be BLUE
        <ul>
            <li>Same as outside the UL</li>
            <li>Same as outside the UL</li>
        </ul>
    </li>
</ul>

ul {
    color: blue;
}
ul ul {
    color: ???;
}
A: 

Ok, the additional text with example clarifies the question a lot. And I'm affraid that what you want is not possible.

If you know the "unknown colour" you can of course repeat the color. But I think CSS needs some mechanism to add variables or references.

So you have to stick to the cumbersome:

ul {
  color: blue;
}
li ul {
  color: sameenvironment;  /* Sorry but you have to add the specific colour here */
}
Gamecat
A: 

My CSS is a bit rusty, but this should work:

blockquote {
    color: red;
}

blockquote em {
    color: inherit;
}

You are setting blockquotes to red, but all <em>'s that are contained in a blockquote should inherit... hmmm, should they inherit from the surrounding text, or from the blockquote?

If the above does not work as you want, then there is no way to do it with the current markup, I think. You would have to work with additional markup, or set the colour explicitltly, e.g.

blockquote em {
        color: Purple;
}
Treb
"inherit" rather than "inherited"
keparo
Oops - as I said, a bit rusty ;-)
Treb
A: 

If you can change your html you could try

<li><span>This text should be BLUE</span>
    <ul>
        <li>Same as outside the UL</li>
        <li>Same as outside the UL</li>
    </ul>
</li>

and the style

li span{
    color: blue;
}

EDIT another way to accomplish this without the extra span tag:

If we assume that we have a style class (or any other selector) that defines to parent of the outer ul. We can modify the css like this:

.parentStyle,
.parentStyle li li{
     color:red;
}
li{
     color:blue;
}
Gene
Adding meaningless anonymous spans isn't the solution to a CSS problem!
eyelidlessness
it's not meaningless if it does the job. CSS is far from perfect. If a pure css solution is not found to any give problem we can either go with js or html changes. My solution is not elegant, but if there's a deadline to reach it can be usefull.
Gene
@eyelidlessness If you can provide a pure css solution I'll give it my vote and bow out in shame. Until then I don't see that my answer is any worse than the other ones before mine (that wont even do what is required)
Gene
It is meaningless. HTML is meant to semantically structure the document, not to create more surface area for CSS. This is a failing in CSS, but can certainly be accomplished by correctly structuring the CSS according to the style logic that applies to a given element.
eyelidlessness
I sort of agree. I'll add another option into my answer.
Gene
+3  A: 

With CSS alone, you can't refer to a parent's parent.

The thing you can do is try a mix of specific CSS selectors and markup so that the desired effect appears.

<td>
  This is the enclosing element.
  <ul>
    <li>This is the first level UL, direct child of TD
      <ul>
        <li>This is the second level UL</li>
        <li>Same as outside the UL</li>
      </ul>
    </li>
  </ul>
</td>

CSS:

td > ul
  color: blue; /* this affects the "direct child" UL only */
}

You would limit the depth of style inheritance to one level, consequently the inner UL is unstyled in regard to color and gets its setup from the enclosing text.

Read more on the CSS Child Selector, and be aware that older browsers may have their quirks with them.


EDIT

For Internet Explorer 6, the child selector can be faked to some extend. Be sure to fasten seat belts (conditional comments or the like) before using this:

td ul {
  color: expression(/TD/.test(this.parentNode.tagName)? "blue" : "black");
}

This assumes "black" as the outer color. If this color value is subject to change, your are out of luck, I'm afraid. Unless you can define an expression() that is able to get the color value from the context (e.g. checking some other properties of parent elements). Or you give up and use a JS framework, as someone else has already suggested.

The wimpy solution without having to use JS would of course be:

td ul.first {
  color: blue;
}

But I can see why you want to avoid that.

Tomalak
Technically, you can't put a UL inside of a P.
Andy Ford
Oh, technically, I can. It's a matter of typing it and saving the file. :-) It's just that the HTML standard forbids it. For what it's worth, I'll change it to a TD.
Tomalak
by "older browsers", we all know that you mean IE6, and unfortunately, that's looking like about 45% of my users. :(
nickf
+1  A: 

Give up and use a snippet of javascript to detect the style of the parent and set it? :)

conny
Lol, but so true.
Gamecat
yep. Get jQuery and the problem is easy to solve.
rp
A: 

Use this to make sure the inherit overrides whatever else might have been setting the color:

blockquote em {
    color: inherit !important;
}
Kon
A: 

Rather than trying to force a selector to inherit font colour from its grandparent, I would suggest that you give the selector and its grandparent a shared declaration for the font colour.

Taking the blockquote example, assuming that body is the grandparent:

body, blockquote em {
       color:[whatever];
}


blockquote {
       color:red;
}

And in the case of the unordered lists, it would be:

body, ul ul {
       color:[whatever];
}


ul {
       color:blue;
}