0

In the example page for the floating label, there is a label selector for when the place holder is not shown:

.form-label-group input:not(:placeholder-shown) ~ label {
  padding-top: calc(var(--input-padding-y) / 3);
  padding-bottom: calc(var(--input-padding-y) / 3);
  font-size: 12px;
  color: #777;
}

this selector is based on this HTML structure:

<div class="form-label-group">
   <input type="email" id="inputEmail" class="form-control" placeholder="Email">
   <label for="inputEmail">Email</label>
</div>

I have a label with input which is in this structure:

<div id="" class="form-label-group ">
   <div class="form-before-field">
   </div>
   <div class="form-field">
      <div id="form-wrap" class="field-wrap" data-field-id="1">
         <div class="field-label">
            <label for="field-1" class="">Name </label>
         </div>
         <div class="field-element">
            <input type="text" value="" class="forms-field form-control" placeholder="Name" id="field-1" name="field-1" aria-invalid="false" aria-describedby="error-1">
         </div>
      </div>
   </div>
   <div class="after-field">
      <section>
      <div class="input-limit"></div>
      <div id="error-1" class="error-wrap error" role="alert"></div>
      </section>
   </div>
</div>

what selector should I use to target the label when the place holder is not shown?

Rain Man
  • 769
  • 1
  • 9
  • 36

1 Answers1

0

Specific question:

Due to your HTML structure, you would need to escape out of <div class="field-element"> and then find the previous <div class="field-label">. And sadly, there is neither a parent selector nor a 'previous' selector in CSS. Therefore it is impossible to target your <label> based off of your placeholder's <input> using pure CSS.

Having said all that, I'll leave the more generic approach on this answer as well, because this is actually a fairly common request, and I'm sure someone will stumble on this question with a more traditional structure :)


General targeting of <label>s based on <input> placeholders:

You might think that you could use the simple :empty pseudo-class for this, though unfortunately, that is not the case. This is because <input> is a void element, and as such, the content model is always empty.

The only pure CSS approach at the moment would be to make use of the :placeholder-shown pseudo-class. This can be combined with :not to target the <input> elements when the placeholder isn't present.

To target the corresponding <label>, you can combine this with the adjacent sibling combinator (+) to target the label that comes immediately after the input.

So in summation, you're looking for:

input(:placeholder-shown) + label

Which can be seen in the following:

input + label {
  display: none; /* Hidden by default for the sample */
}

input:not(:placeholder-shown) + label {
  display: block;
}
<input id="email" placeholder="Email">
<label for="email">Placeholder Not Shown!</label>

Note, however, that :placeholder-shown is currently not supported in either Internet Explorer or Edge. Until those browsers add support for :placeholder-shown, you'll be forced to resort to a JavaScript solution.

Community
  • 1
  • 1
Obsidian Age
  • 36,816
  • 9
  • 39
  • 58
  • fair enough, what if the label is before the input in your example? – Rain Man Feb 27 '18 at 03:45
  • The ` – Obsidian Age Feb 27 '18 at 03:52
  • so there is no way to target the label if it comes before the input? I was thinking of something like `label:has(input:not(:placeholder-shown))` but it doesnt work – Rain Man Feb 27 '18 at 03:58
  • It doesn't work because there is absolutely **no way of doing it**. Sorry, but it's true ;) – Obsidian Age Feb 27 '18 at 03:58
  • @RainMan Also see https://stackoverflow.com/questions/1014861/is-there-a-css-parent-selector and https://snook.ca/archives/html_and_css/css-parent-selectors. – wazz Feb 27 '18 at 07:50