skip to Main Content

In HTML and (S)CSS, I made a form as part of my homework. (see https://codepen.io/quokka-wiki/pen/BavqrQL)

I added the following HTML/SCSS to add a red asterisk to the labels of required fields:

<html>
    <!-- ... -->
    <body>
        <!-- ... -->
        <label for="username">Username</label>
        <input type="text" name="username" required />

        <label for="password">Password</label>
        <input type="password" name="password" required />

        <!-- ... -->
        <input type="checkbox" name="tos" required />
        <label for="tos">I agree to sell my soul to the Devil for this app</label>
        
    </body>
</html>

But it only works for some of them for some reason.

Can somebody help me figure it out/help me find a better CSS selector?


Update:

I do not know why it doesn’t work at all in the code snippet above, just go to the codepen.

2

Answers


  1. As per the above comment, your selector is incorrect. As the label element in your code is before the input element ( & the required attribute is assigned to that input element ) using the plus + within your css rule will fail to find the label you are actually hoping for – instead, if there happens to be a following label ( will be for different element ) that selector will match and apply styles there.

    The first snippet is essentially as per your code with the same / similar selector and you will see the following label is coloured yellow rather than the one that is supposed to be.

    :required + label{background:yellow}
    :required + label:after{content:'*';color:red}
    <label for="username">Username</label>
    <input type="text" name="username" required />
    
    <label for="password">Password</label>
    <input type="password" name="password" required />

    Instead, if you change the order of the label & input element you get the text below the input element which is probably not the required layout but you see how the selector is now correctly applying the styles to the correct element.

    :required + label{background:yellow}
    :required + label:after{content:'*';color:red}
    <input type="text" name="username" required />
    <label for="username">Username</label>
    
    <input type="password" name="password" required />
    <label for="password">Password</label>

    As a fudge you could play about with positioning the pseudo content above the input by using a negative margin – it’s not elegant but sort of works.

    :required + label:after{
      content:"*";
      color:red;
      position:relative;
      top:-2.5rem;
      margin:0 0 0 0.5rem;
    }
    
    label:before{
      content:attr(for);
      position:relative;
      top:-2.5rem;
      z-index:2;
      text-transform:capitalize;
    }
    
    label{display:block}
    
    input{margin:2rem 0 0 0}
    <input type="text" name="username" required />
    <label for="username"></label>
    
    <input type="password" name="password" required />
    <label for="password"></label>
    Login or Signup to reply.
  2. The selector you are using, :required + label::after reads as "A required field, immediately followed by a label." In other words, your CSS code requires the label to be after the input element. This is why it works on the password field, because that label comes after the required field for username.

    If you want to keep the element order, the simple fix is to use a class and apply it to the labels for the required inputs.

    You could also accomplish this using the :has selector instead, with the rule:
    label:has(+ :required)::after. This selector is not currently supported by Firefox however, so using a class is the better option.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search