17

On input focus I want to change the color of the label element. How can I achieve this in less?

.control-label{
      color: @gray-light;
}
.controls{
  input,
  textarea{
    background-color:red; 
    &:focus{
      .control-label &{
        color: red;  //HERE
      }

    }
}

HTML:

<div class="control-group">
    <label class="control-label" for="inputEmail">Firstname</label>
    <div class="controls">
        <input type="text" id="inputEmail" placeholder="Firstname">
    </div>
</div>
Ganesh Yadav
  • 2,607
  • 2
  • 29
  • 52

7 Answers7

30

One solution would be to use the :focus-within selector.

So, you'd do something like the below. Assuming that you always have an input of some description inside of a control-group, it will style the label whenever the input is focused on.

control-group {
    &:focus-within {
        control-label {
            color: red; 
        }
    }
}

More information can be found here: https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-within

  • 6
    This should be the accepted answer. It does the job without messing with the ordering of elements. – Steve Jul 22 '19 at 21:09
  • With almost complete (no IE) browser support, this is excellent. Thanks for sharing. – brad Aug 12 '20 at 15:09
  • Saved me a lot of work and restructuring! Also better readable than the alternatives - Thx!! – Sarah Sep 08 '20 at 06:29
26

I don't think you can without changing your HTML, see also: Is there any way to hover over one element and affect a different element?, your elements should be direct siblings. (LESS don't help to solve your problem here, LESS generate CSS and it seems impossible to do in CSS)

Possible suggestion:

input:focus + .control-label
{
    background-color:purple;
    color: red;
}
.controls > input
{
    float:right;
} 
<div class="controls">
    <input type="text" id="inputEmail" placeholder="Firstname">
    <label class="control-label" for="inputEmail">Firstname</label>
</div>

Or solve your problem with javascript: https://stackoverflow.com/a/20226218/1596547

Gleb Kemarsky
  • 10,160
  • 7
  • 43
  • 68
Bass Jobsen
  • 48,736
  • 16
  • 143
  • 224
10

Use Flexbox

CSS is cascading, i.e. affected by the order that elements appear in the DOM. To be able to select the label only when the input is focused (input:focus + label), the label needs to come after the input, so;

Put the input before the label in the DOM and then use flexbox to reverse the order that they appear on the page.

.input-group {
    display: flex;
    flex-direction: column-reverse;
}

input:focus + label {
    color: green;
}
<div class="input-group">
    <input value="Input" />
    <label>Label</label>
</div>
brad
  • 1,407
  • 19
  • 33
8

One solution would be to move the label below the input in the DOM but position them absolutely (to the parent) so the label looks to be above the input field:

<div>
  <input type="text"/>
  <label>Text</label>
</div>

In CSS move the label to the top, the input to the bottom:

label {
  position: absolute
  top: 0
}

input {
  position: absolute
  bottom: 0
}

And use the :focus state to change the style of the label:

input:focus + label {
    color: red
}

See example:

http://codepen.io/robcampo/pen/zGKLgg

On focus, the label turns red. No JS required.

Rob Campion
  • 1,359
  • 13
  • 26
1
control-group {
    &:focus-within {
        control-label {
            color: red; 
        }
    }

}

loads of hearts to this person. Nothing was working and this worked in ion-label too . Accepted answer. Stack overflow does not allow to comment (below 50 reputation). So writing seperately <3

1

I hope I am not too late to answer this. With the new :has psudo-class we can achieve it without changing the HTML,

HTML:

<div class="control-group">
    <label class="control-label" for="inputEmail">Firstname</label>
    <div class="controls">
        <input type="text" id="inputEmail" placeholder="Firstname">
    </div>
</div>

CSS:

.control-group:has(input:focus) label{
 color: red;
}

This approach is simple and cleaner.

Note: it is not supported by firefox yet.

Harsh Behl
  • 41
  • 5
  • I think this is the most accessible solution as screen readers prefer labels to appear before inputs in the DOM. – patrickzdb Nov 22 '22 at 11:47
0

The easy way is to use :focus-within check developer mozilla

.control-group:focus-within .control-label {
   color: red;
}

Or

.control-group:focus-within label {
   color: red;
}
ayobami john
  • 111
  • 2
  • 5