skip to Main Content

So if I have a list like this:

<ul>
 <li><button disabled/></li>
 <li><button disabled/></li>
 <li><button /></li>
 <li><button /></li>
 <li><button /></li>
</ul>

And the amount of disabled buttons is never known – but will always be consecutive and appear before the enabled buttons, how do I select the second enabled button?

Right now I have:

  • “ul li:nth-of-type(2) button:not([disabled])”

but this only selects the second <li> with a child button that is not disabled – if it is disabled, it doesn’t select anything.
In other words it doesn’t ‘find’ the second enabled button, it just checks if the second button is enabled or not and selects it accordingly.

I’ve tried

  • “ul li button:not([disabled]):nth-of-type(2)”

but the problem with that is the button is the only child of <li>, so nth-of-type(2) doesn’t have anything to select.

What I think I need to be able to write is something like this:

  • “ul (li button:not([disabled])):nth-of-type(2)”

but I don’t think that’s the correct syntax 🙁

Any help would be greatly appreciated! If it helps anyone, I’m writing a UDF test to find (and select) the second available time slot for a time picker component in React.

2

Answers


  1. Here’s a way you can do it using :has() which now looks to have support in all updated browsers (thanks FF for catching up):

    button {
      width: 100px;
      height: 50px;
    }
    
    
    /* Second */
    
    li:has(button[disabled])+li:has(button:not([disabled]))+li:has(button:not([disabled])) button {
      background: red;
    }
    
    
    /* first */
    
    li:has(button[disabled])+li:has(button:not([disabled])) button {
      background: blue;
    }
    
    
    /* third */
    
    li:has(button[disabled])+li:has(button:not([disabled]))+li:has(button:not([disabled]))+li:has(button:not([disabled])) button {
      background: green;
    }
    
    
    /* no disabled buttons per comment by haolt */
    
    li:first-child:has(button:not([disabled]))+li:has(button:not([disabled])) button {
      background: purple;
    }
    <ul>
      <li><button disabled/></li>
      <li><button disabled/></li>
      <li><button /></li>
      <li><button /></li>
      <li><button /></li>
    </ul>
    
    <ul>
      <li><button /></li>
      <li><button /></li>
      <li><button /></li>
      <li><button /></li>
      <li><button /></li>
    </ul>

    It’s not very elegant, as we are chaining next sibling + selectors, but it works.

    Login or Signup to reply.
  2. Here is an easier selector where you only have to update one number to select the needed button

    li:nth-child(2 of :has(button:not([disabled]))) button {
      color: red;
    }
    li:nth-child(3 of :has(button:not([disabled]))) button {
      color: blue;
    }
    <ul>
     <li><button disabled>button</button></li>
     <li><button disabled>button</button></li>
     <li><button >button</button></li>
     <li><button >button</button></li>
     <li><button >button</button></li>
    </ul>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search