Search code examples
htmlcsscss-selectors

CSS no sibling selector


Consider the following html:

<div>
    <div class="iwant" />
    <div class="idontwant" />
</div>
 <div>
    <div class="iwant" />
</div>

I'm interested in a selector (for crawling content so I can't modify html) that would select all iwant that DO NOT have sibling with class idontwant.


Solution

  • If anyone still needs this, I found this answer . Based on it and on :not pseudo-class, the initial requirement can be accomplished using something like:

    div:not(:has(+ .idontwant)) .iwant { 
      ... 
    }
    

    This approach has an advantage over the general sibling combinator: It also matches backwards, meaning something like:

    <div>
        <div class="idontwant" />
        <div class="iwant" />
    </div>
    

    (so if you have the .idontwant element first -> case which would be ignored by the general sibling combinator)


    Explanation:

    1. div:has(+ .idontwant) would match any div that has a direct sibling with the class idontwant
    2. div:not(:has(+ .idontwant)) matches any div that doesn't have a direct sibling with class idontwant
    3. All is left to do is search in the div that doesn't have a direct sibling with the class idontwant for the class we want.

    The selector is quite weird and big, but it does the job, and I think there are (specific) cases where it is quite needed.


    Edit (from comments): If anyone needs to style an element only if it has a specific sibling (or if it doesn't) you can still use the :has Pseudo-class to accomplish it (check snippet):

    const toogleHasClassEl = document.getElementById("toogleHasClass")
    toogleHasClassEl.onclick = () => toogleHasClassEl.classList.toggle("specificclass")
    div:has(.specificclass) .stylethis { 
      background: orange
    }
    div:not(:has(.specificclass)) .stylethis { 
      background: yellow
    }
    
    
    div:has(.stylethis) .specificclass { 
      background: red
    }
    <div>
      <div class="stylethis">style this</div>
        <div id="toogleHasClass" class="specificclass">if this has `specificclass` class (click to toggle)</div>
    </div>
    <hr/>
    <div>
      <div class="stylethis">style this different</div>
      <div class="thisdoesnthaveclass">if this doesn't have specific class</div>
    </div>
    <hr/>
    <div>
      <div class="stylethis">style this different (if alone and therefore doesn't have specific sibling)</div>
    </div>