skip to Main Content

I have this HTML structure

.sectionLabel {
  display: block;
  padding: 0.25em 1.1em;
  margin: 0 0 .1875em 0;
  cursor: pointer;
  background: #888888;
  border-radius: 0.2em;
  color: #FFFF;
  transition: ease .5s;
  position: relative;
  /* ADDING THIS IS REQUIRED */
}

.control:has(:invalid) {
  color: red;
}
<form>
  <label id="mylabel" class="sectionLabel">Section Header</label>
  <div>
      <br>
      <div class="control">
       <label for="nodeName">Node Name</label>
       <input id="nodeName" name="nodeName" pattern="^([A-Za-z_][A-Za-z0-9_]*(.[A-Za-z0-9_]+)*)+[.:]([A-Za-z_][A-Za-z0-9_]*)$" value="test" />
      </div>
    </div>
    <br>
    <button class="submitButton" type="submit">Submit</button>
</form>

Please take a look at: https://jsfiddle.net/e17sgxm2/1/

You will see that an invalid pattern in the text field turns the label red. But I would also like the Section Header to turn red too.

In the actual implementation there are other input fields too. So if any field has an invalid value, I would like the Section Header to turn red.

2

Answers


  1. Chosen as BEST ANSWER

    I ended up adding a wrapper div around the outer one and then use :has with it to kind of solve the issue.

    <form>
      <div class="wrapper">
        <label id="mylabel" class="sectionLabel">Section Header</label>
        <div>
          <br>
          <div class="control">
            <label for="nodeName">Node Name</label>
            <input id="nodeName" name="nodeName" pattern="^([A-Za-z_][A-Za-z0-9_]*(.[A-Za-z0-9_]+)*)+[.:]([A-Za-z_][A-Za-z0-9_]*)$" value="test" />
          </div>
        </div>
      </div>
      <br>
      <button class="submitButton" type="submit">Submit</button>
    </form>
    
    .sectionLabel {
      display: block;
      padding: 0.25em 1.1em;
      margin: 0 0 .1875em 0;
      cursor: pointer;
      background: #888888;
      border-radius: 0.2em;
      color: #FFFF;
      transition: ease .5s;
      position: relative;
      /* ADDING THIS IS REQUIRED */
    }
    
    .wrapper:has(:invalid)>.sectionLabel {
      color: red;
    }
    
    .control:has(:invalid) {
      color: red;
    }
    

    https://jsfiddle.net/0y1fp5dv/1/


  2. We can use :has() on the bounding div and work from there

    Updated Solution

    .sectionLabel {
      display: block;
      padding: 0.25em 1.1em;
      margin: 0 0 .1875em 0;
      cursor: pointer;
      background: #888888;
      border-radius: 0.2em;
      color: #FFFF;
      transition: ease .5s;
      position: relative;
      /* ADDING THIS IS REQUIRED */  
    }
    
    /*Adding selector to style the header*/
    .control:has(:invalid), div:has(.control > :invalid) > .sectionLabel  {
      color: red;
    }
    <form>  
      <div>
         <label id="mylabel" class="sectionLabel">Section Header</label>
        <div class="control">
          <label for="nodeName">Node Name</label>
          <input id="nodeName" name="nodeName" pattern="^([A-Za-z_][A-Za-z0-9_]*(.[A-Za-z0-9_]+)*)+[.:]([A-Za-z_][A-Za-z0-9_]*)$" value="test" />
        </div>
      </div>
    
      <button class="submitButton" type="submit">Submit</button>
    </form>

    Original Answer
    As I mentioned in a comment CSS is linear and works in one direction. You can style something based on preceding elements, but not subsequent elements.

    Taking that in mind we can achieve what you want in a somewhat hacky manor by moving the "Section Header" after the content. Then CSS Grid will be used to style it above the content.

    However I suspect this may interfere with the reason you have /* ADDING THIS IS REQUIRED */. Also this is pretty hacky and I’d probably not actually use this InTheRealWorld

    form {
      /*Set the form as a grid*/
      display:grid;
      grid-template-columns: 1fr;
      grid-row-gap: 0.5em;
    }
    
    .sectionLabel {
      display: block;
      padding: 0.25em 1.1em;
      margin: 0 0 .1875em 0;
      cursor: pointer;
      background: #888888;
      border-radius: 0.2em;
      color: #FFFF;
      transition: ease .5s;
      position: relative;
      /* ADDING THIS IS REQUIRED */
      /*Move to the first row of the grid*/
      grid-row-start: 1;  
    }
    
    /*Adding selector to the header*/
    .control:has(:invalid), div:has(.control > :invalid) + .sectionLabel  {
      color: red;
    }
    <form>  
      <div>
        <div class="control">
          <label for="nodeName">Node Name</label>
          <input id="nodeName" name="nodeName" pattern="^([A-Za-z_][A-Za-z0-9_]*(.[A-Za-z0-9_]+)*)+[.:]([A-Za-z_][A-Za-z0-9_]*)$" value="test" />
        </div>
      </div>
      <label id="mylabel" class="sectionLabel">Section Header</label>
      <button class="submitButton" type="submit">Submit</button>
    </form>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search