0

I'm looking for a way to select, using pure CSS selectors, the "closest" descendant.

Basically, I have a hierachical structure of container/containee divs. When I put a specific CSS marker on the container, I want to apply some rules on its containee. But as its hierarchical, I don't want to apply the rules to containee in nested containers.

This could have been easily using the > operator, but I don't control the markup between the container and its containee, it may have several level of other markup.

To reproduce my issue, here is a jsfiddle : http://jsfiddle.net/stevebeauge/2xjh1jdf/

It includes this markup:

<div class="container">
    <div class="some">
        <div class="containee">Border should not be dotted</div>
    </div>
</div>
<div class="container marker">
    <div class="containee">Border should be dotted</div>
</div>
<div class="container marker">
    <div class="containee">
        <p>Border should  be dotted</p>
        <div class="container">
            <div class="containee">
                <p>Border should not be dotted</p>
                <div class="container marker">
                    <div class="some">
                        <div class="containee">Border should be dotted</div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

and using this CSS :

div {
    margin:3px;
    border: solid 3px;
}
.container {
    border-color: red
}
.containee {
    border-color : green;
    border-style: solid;
}
.marker .containee {
    border-style: dotted;
    border-color:blue;
}

The actual result is:

actual result

Whereas the expected result is:

expected

I known I could use a javascript solution (and it's actually my alternative), but I'd prefer a pure CSS solution to avoid polluting the application with such JS.

I also tried using some weird selectors :

.marker .containee, 
.marker > div:not(.container) > .containee, 
.marker > div:not(.container) > div:not(.container) > .containee {
    border-style: dotted;
    border-color:blue;
}

But not only this does not solve the problem, but I requires to create the rule for each expected depth level of containee...

Steve B
  • 34,941
  • 18
  • 92
  • 155
  • 2
    I think you highlighted the issue when you said "I don't control the markup between the container and its containee, it may have several level of other markup." – j08691 Nov 19 '14 at 14:29
  • @j08691: are you telling me that's it's impossible using CSS? I have to live with this unknown markup. I can fallback to JS though, even if I don't like this option. – Steve B Nov 19 '14 at 14:35
  • 3
    I can't say impossible, no. But this is one of those situations where because you say you don't control the markup, that the ambiguity leads me to believe that any potential CSS-only solution could be refuted with a new edge case. Personally I'd forgo the headache of looking for the CSS solution and use JS. – j08691 Nov 19 '14 at 14:38
  • @j08691: maybe you could answer in this way? This is not actually a technical answer, but I'll probably end with the alternative way (which is using JS) – Steve B Nov 19 '14 at 14:43

2 Answers2

0

Finally, I implemented my requirement using some javascript (with the help of jQuery).

As @j08691 said, even if it was possible, the solution would have been complex, and hard to avoid edge case traps.

Community
  • 1
  • 1
Steve B
  • 34,941
  • 18
  • 92
  • 155
-1

You can try below code:

Fiddle here

.marker .container > .containee:first-child{border-style:solid !important;}
Pradeep Pansari
  • 1,287
  • 6
  • 10
  • 1
    From the question: "This could have been easily using the > operator, but I don't control the markup between the container and its containee, it may have several level of other markup." – j08691 Nov 19 '14 at 14:34