skip to Main Content

Sass or CSS select element only if sibling does not exists. I feel like I am really close, but I keep missing the mark. I need to have all <p> tags red, but if it is the last <p> tag && the next element is not a <ul> – make it blue.

Live example: https://jsfiddle.net/xt0qaL6g/1/
Possible other solution not using not and changing the mentality of the question – https://jsfiddle.net/s06ex4vg/

Example 1:

    <p> - red
    <ul>
    <p> - red
    <ul>
    <p> - blue
 ... nothing or anything can be directly after as long as it's not a `<ul>`

Example 2:

<p> - red
<ul>
<p> - red
<ul>
<p> - red
<ul>
p {
  margin-bottom: 15px;
  background-color: red;
}

.text p:last-of-type+ :not(ul) {
  background-color: blue;
}
<div class="text">
  <p>Testssssss</p>
  <ul>
    <li>item 1</li>
    <li>item 2</li>
  </ul>
  <p>Test 2</p>
  <p>Test3</p>
  <ul>
    <li>item 1-1</li>
    <li>item 2-2</li>
  </ul>
  <p>
    Again
  </p>
  <ul>
    <li>asdf</li>
  </ul>

  <p>sadf</p>
  <span>sadf</span>

</div>

2

Answers


  1. You can use CSS :not pseudo selector to make the last p blue if contains something other than a ul

    .text p:last-of-type:has( + :not(ul)){background-color: blue;}
    

    or you could make the last p blue by default and set it to red if it does contains a ul:

    .text p:last-of-type {background-color: blue;}
    .text p:last-of-type:has(+ ul){background-color: red;}
    

    At the time of writing all major browsers support :has except for Firefox. 😞 Here’s a CSS solution anyway but you will need a different approach if you want to support Firefox.

    p {
      background-color: red;
    }
    
    .text p:last-of-type:has( + :not(ul)) {
      background-color: blue;
    }
    <div class="text">
      <p>Para 1</p>
      <ul>
        <li>ul</li>
      </ul>
      <p>Para 2</p>
      <p>Para 3</p>
      <ul>
        <li>ul</li>
      </ul>
      <p>para 4</p>
      <span>not a ul</span>
    </div>
    Login or Signup to reply.
  2. Have all <p> tags red, but if it is the last <p> tag & the next element is not a <ul> – make it blue.

    p:last-of-type:not(:has(+ ul))

    Related Stackoverflow question: "Is there a "previous sibling" selector?"

    p { 
      color: red 
    }
    
    p:last-of-type:not(:has(+ ul)) { 
      color: blue 
    }
    <p>Testssssss</p>
    <ul>
      <li>item 1</li>
      <li>item 2</li>
    </ul>
    <p>Test 2</p>
    <p>Test3</p>
    <ul>
      <li>item 1-1</li>
      <li>item 2-2</li>
    </ul>
    <p>
      Again
    </p>
    <ul>
      <li>asdf</li>
    </ul>
    
    <p>sadf</p>
    <span>sadf</span>

    If you don’t want (or can’t) use :has selector you can write your HTML in reverse and then reverse it back with CSS:

    body {
      display: flex;
      flex-flow: column-reverse;
    }
    
    p { color: blue; }
    ul ~ p { color: red; }
    <span>sadf</span>
    <p>sadf</p>
    <ul>
      <li>asdf</li>
    </ul>
    <p>
      Again
    </p>
    <ul>
      <li>item 2-2</li>
      <li>item 1-1</li>
    </ul>
    <p>Test3</p>
    <p>Test 2</p>
    <ul>
      <li>item 2</li>
      <li>item 1</li>
    </ul>
    <p>Testssssss</p>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search