Matt Thalman
Matt Thalman

Reputation: 293

CSS selector to get deepest element of specific class in the HTML tree

I've got a a bunch of DIV elements in my HTML, several of which have their class attribute set to "rowsLayout". Some of these rowsLayout DIVs can be nested inside one another. I want to define a CSS selector that only targets the deepest DIVs in those nestings. That is, I don't want any of the rowsLayout DIVs that contain any other rowLayout DIVs.

<div id="a" class="rowsLayout">
  <div id="b" class="rowsLayout" />
  <div id="c" class="rowsLayout">
    <div id="d" class="rowsLayout" />
  </div>
</div>
<div id="e" class="rowsLayout" />

With this structure, I want a selector that will target b, d, and e.

Can this be done?

Upvotes: 22

Views: 13586

Answers (9)

Cris Ward
Cris Ward

Reputation: 171

I realise this is an old question, but it's worth noting that the :has selector has now landed in browsers. So the JQuery solution can now be used as plain css

.rowsLayout:not(:has(.rowsLayout))

https://caniuse.com/css-has

Upvotes: 3

mjs
mjs

Reputation: 22409

MOST DOWNVOTES YET THE ONLY CORRECT ANSWER

It is not possible in CSS, unless you use this hack, which makes it possible using the :dir or :lang attribute.

Using the :lang is preferable in 2015 as it is supported by most browsers.

Note, it's a hack allowing you to do it, but if you care much about following some standard rather than getting the job done, then don't use this.

Example:

.container {
  padding:20px;
}

:lang(ar) {
  direction:rtl;
}

:lang(en) {
  direction:ltr;
}

.container:lang(en) {
  background-color:blue;
}

.container:lang(ar)  {
  background-color:red;
}

.container .a:lang(en)   {
  background-color:orange;
}

.container .a:lang(ar) {
  background-color:yellow;
}
<div id="searchHere">
  
    <div lang=en>      
      <div class="container">
          l t r
        <div class=a>
              a
         </div>
      </div>
      
      <div lang=ar>
          <div class="container">
             r t l
            <div class=a>
              a
              </div>
          </div>        
        
          <div>
            <div class="container">
                r t l 
              <div class=a>
              a
              </div>
            </div>  
            
            <div lang=ar>
                <div class="container">
                   r t l
                  <div class=a>
                    a
                    </div>
                </div>  
            </div>
            
            <div lang=en>      
              <div class="container">
                  l t r
                <div class=a>
              a                  
              </div>
                
                <div lang=ar>
                  <div class="container">
                     r t l
                    <div class=a>
                      a                      
                      <div lang=en>      
                        <div class="container">
                          l t r
                          <div class=a>
                            a                  
                          </div>
                          <div>
                            <div>
                            
                              <div lang=en>      
                                <div class="container">
                                  l t r
                                  <div class=a>
                                    a                  
                                  </div>
                                </div>                      
                              </div>
                              
                              <div lang=ar>      
                                <div class="container">
                                  r t l
                                  <div class=a>
                                    a                  
                                  </div>
                                </div>                      
                              </div>
                              
                            </div>
                            
                          </div>
                        </div>                      
                      </div>
                  </div> 
                </div>
              </div>            
            </div>
            
          </div>
        
      </div>
      
    </div>
  
</div>

Although the example demonstrates this with ltr and rtl, the :lang could in theory be made to behave as a deepest match, using for instance :lang(my-special-selector) although that is probably not how lang attribute is supposed to be used.

Upvotes: -3

yassin laclass
yassin laclass

Reputation: 1

Take a look at this:

div#b:first-of-type {
style here
}

Upvotes: -3

Matt Lambert
Matt Lambert

Reputation: 3665

select them by ID

#b, #d, #e {
 /* styles here */
}

any reason for all the repeat class names btw? You could wrap the whole thing in div of #layout or something then do...

#layout div {
 /* styles */
}

instead of adding that class name to ever div.

Upvotes: -2

josh.trow
josh.trow

Reputation: 4901

Why not use :empty?

JQuery Empty

EDIT: It also works as a CSS Selector:

:empty { background-color: black; }

MORE EDITS:

:last-of-type almost works, but it gets 'a' for some reason. See my fiddle.

http://jsfiddle.net/DUdVR/3/

Upvotes: -3

SLaks
SLaks

Reputation: 888203

You can use the jQuery selector .rowsLayout:not(:has(.rowsLayout)).

However, for performance reasons, this is not possible in CSS.

Your selector depends on the children (or lack thereof) of the elements that you target.
CSS is designed so that an element's selectors can always be resolved before the element's children exist; this allows CSS to be applied as a document loads.

Upvotes: 16

Collin White
Collin White

Reputation: 680

Depending on the number of divs you have you could either do something like:

div#b.rowsLayout,div#d.rowsLayout,div#e.rowsLayout {}

Maybe there is a better way to solve your problem, what are you trying to apply to all these divs?

Upvotes: -1

Marcin
Marcin

Reputation: 49886

No.

Your options are: select them by id; add a second class for those leaves, and select by that class; use a javascript-based solution to set the appropriate styling (possibly using the second class).

Upvotes: 0

jackJoe
jackJoe

Reputation: 11168

can you consider an option of adding an extra class such as "parent" to the parent items? it would be easier and is the "standard"

Upvotes: -1

Related Questions