How to make css selectors with the same specificity be applied in order of HTML tags parenthood?
Asked Answered
T

4

6

There are a bunch of same-level CSS styles and an HTML code with nested blocks to which the styles are applied:

.style1 a {
  color: red;
}
.style2 a {
  color: green;
}
<div class="style2">
  <span>
    <a href="/">Style 2</a>
  </span>
  <div class="style1">
    <div>
      <a href="/">Style 1</a>
    </div>
    <div class="style2">
      <a href="/">Style 2</a>
    </div>
  </div>
</div>

As a result the second link («Style 1») becomes green. It happens because the link tag has the same specificity for both CSS selectors and .style2 a is declared later, so .style2 a is applied.

How to make the style be applied from the nearest style-class parent without preliminary information about the tags nesting (to make the second link be red)?

Code playground: http://codepen.io/anon/pen/zvXmOw

The HTML is able to be modified. But consider that links may be anywhere.

——————————

The best solutions I've found are based on limit nesting. First (link tag distance from style-parent is limited):

.style1 > a,
.style1 > :not(.style) > a,
.style1 > :not(.style) > :not(.style) > a {
  color: red;
}
.style2 > a,
.style2 > :not(.style) > a,
.style2 > :not(.style) > :not(.style) > a {
  color: green;
}
<div class="style style2">
  <span>
    <a href="/">Style 2</a>
  </span>
  <div class="style style1">
    <div>
      <a href="/">Style 1</a>
    </div>
    <div class="style style2">
      <a href="/">Style 2</a>
    </div>
  </div>
</div>

Second (style-divs nesting is limited):

.style1 a,
.style .style1 a,
.style .style .style1 a {
  color: red;
}
.style2 a,
.style .style2 a,
.style .style .style2 a {
  color: green;
}
<div class="style style2">
  <span>
    <a href="/">Style 2</a>
  </span>
  <div class="style style1">
    <div>
      <a href="/">Style 1</a>
    </div>
    <div class="style style2">
      <a href="/">Style 2</a>
    </div>
  </div>
</div>

I am trying to find out is there a better solution without limits.

Tanta answered 23/11, 2015 at 9:26 Comment(4)
use like .style1 > a { color: red; } .style2 > a { color: green; }Reverie
@KishoreSahas , it even won't color links (except the last one). Links can take any place in style-divs.Tanta
I agree, i misunderstood the questionReverie
@DanielTate Browser compatibility is required. I've updated my answer.Tanta
T
2

It can be achieved using CSS variables:

a {
  color: var(--link-color);
}
.style1 {
  --link-color: red;
}
.style2 {
  --link-color: green;
}
<div class="style2">
  <span>
    <a href="/">Style 2</a>
  </span>
  <div class="style1">
    <div>
      <a href="/">Style 1</a>
    </div>
    <div class="style2">
      <a href="/">Style 2</a>
    </div>
  </div>
</div>

This technology is supported by browsers widely already, and will get even wider support in future.

Tanta answered 28/2, 2018 at 3:45 Comment(0)
T
2

How to make css selectors with the same specificity be applied in order of HTML tags parenthood?

You can't. CSS simply doesn't work like that. If selectors have equal specificity then rules are applied in stylesheet order. You can't change that.

You might be able to achieve the effect you want with color: inherit on the links and setting the colours on the elements that are members of the classes.

It would probably be easier to set the classes on the anchors directly.

Thurber answered 23/11, 2015 at 9:29 Comment(5)
The idea is to apply style themes to cards without changing HTML. Theme affects set of tags and classes. And cards can be nested. So I try to find out are there any tricks to do it without applying classes to target elements.Tanta
@Tanta — As I said: No, there isn't.Thurber
There is but with limited nesting (see updated question).Tanta
@Tanta — Well, yes, but your original question excluded that possibility and it gets stupidly unwieldy very quickly.Thurber
I mentioned that you can modify HTML code. Is my english badly understandable?Tanta
T
2

It can be achieved using CSS variables:

a {
  color: var(--link-color);
}
.style1 {
  --link-color: red;
}
.style2 {
  --link-color: green;
}
<div class="style2">
  <span>
    <a href="/">Style 2</a>
  </span>
  <div class="style1">
    <div>
      <a href="/">Style 1</a>
    </div>
    <div class="style2">
      <a href="/">Style 2</a>
    </div>
  </div>
</div>

This technology is supported by browsers widely already, and will get even wider support in future.

Tanta answered 28/2, 2018 at 3:45 Comment(0)
D
0

That's a problem of definitions. It's better making a link .green that make a div with .green classname to apply his childrens. Good CSS practices said that it's better making this:

 <a href="" class="green">Green link</a>
 <a href="" class="red">Red link</a>

Doesn't matters where they are. If the specific styles are mading for links, why not write a good code for them?

Dieldrin answered 23/11, 2015 at 9:29 Comment(3)
The idea is to apply style theme to block without changing HTML. Theme affects set of tags and classes.Tanta
One theme is to apply only one theme, not two. If you need to apply two themes, then you haven't got a theme system.Heroic
There are nested blocks (for example, cards) that can be nested. Parent card has it's own content that need to be styled. And this card has child cards which contents are also need to be styled.Tanta
S
0

The best would probably be to remove the span and div like so:

<div class="style2">
    <a href="/">Style 2</a>
    <div class="style1">
        <a href="/">Style 1</a>
    <div class="style2">
        <a href="/">Style 2</a>
    </div>
</div>

And then use this CSS:

.style1 > a {
    color: red;
}
.style2 > a {
    color: green;
}

Fiddle: http://jsfiddle.net/09c6x5pp/

EDIT:

If you want to keep the span and div:

.style1 > a,
.style1 > div > a {
    color: red;
}
.style2 > a,
.style2 > span > a {
    color: green;
}
Slone answered 23/11, 2015 at 9:34 Comment(2)
Links can be anywhereTanta
Then I suggest putting the Class on the Link itself instead of the parents. Only way to do it.Slone

© 2022 - 2024 — McMap. All rights reserved.