Anyway to have a label respond to :focus CSS
Asked Answered
T

6

30

Is there any way to have a label respond to focus. I have some code where the textfield has a different style on focus. The label also however needs a slightly different style. I tried this but it did not effect the label.

#header .search label {
    background:url(http://www.golfbrowser.com/images/icons/search.png) left top no-repeat;
    padding-left:20px;
    height:20px;
    float:right;
}
#header .search label:focus {
    background:url(http://www.golfbrowser.com/images/icons/search-z.png) left top no-repeat;
    padding-left:20px;
    height:20px;
    float:right;
}
#header .search input {
    padding:0px;
    border:0px;
    width:140px;
    height:20px;
    float:left;
    padding-right:10px;
    background:url(http://www.golfbrowser.com/images/icons/searchbar.png) right top no-repeat;
}
#header .search input:focus {
    padding:0px;
    width:190px;
    height:20px;
    float:left;
    padding-right:10px;
    background:url(http://www.golfbrowser.com/images/icons/searchbar-z.png) right top no-repeat;
}

The label contains an image and the other part of a round corner and it too must change colour in order for the field to look correct.

Any ideas,

Marvellous

Thief answered 12/5, 2011 at 12:51 Comment(2)
The label cannot have :focus since it cannot receive user input. Only elements with which the user can interact (links, input fields, buttons) can have focus.Grajeda
Quick (& modern) answer is :focus-within (supported on all major browsers: caniuse.com/?search=focus-within). Read milehighsi's answer for more detail.Implicatory
E
37

You can't actually give focus to a label. It's not a focusable form element. Besides, even if you could do that, then whatever previously had focus (that means your input) would lose it to the label anyway.

You may have to restructure your HTML (and modify your CSS accordingly) so that you can select input:focus and then that input's corresponding label. For instance, if you moved your label after your input and used the following CSS selector for your label, you should be able to accomplish what you want.

#header .search input:focus + label
Endodontist answered 12/5, 2011 at 12:56 Comment(3)
this was super useful to me. I have a fieldset of invisible radios with labels styled as buttons. the user had no feedback that a button was focussed until now. .radio-set input:focus + label {box-shadow: 0 0 2px $brand-primary;}Blomquist
Can anybody confirm if doing this reduces accessibility of the label for the screen readers? Both in case where visually the label will be placed above (or to the left of) the field using CSS positioning and in the case where it really is to the bottom/right.Strickler
This solution doesn't work for me because the problem came up in the context of checkbox styling, and the only working solution I found to style checkboxes is to hide the input element and place an additional element (span) after the input elementy and style that span, and then wrap everything in a label. It works beautifully, but it forces me to have the label surrounding the input element so this solution doesn't work here. I'd be grateful if anyone can figure out a solution that addresses both issues.Scorch
E
27

BoltClock's answer is the more semantic, lightweight way of achieving this functionality. However it's not always possible to have a specific HTML structure (especially to facilitate a minor feature like this) and CSS lacks the ability to traverse up the HTML hierarchy. To get around that, here are two alternatives. The first is coming soon (CSS spec 4) and the second is our old mate Javascript.

First up, CSS4's :focus-within pseudo selector. This does exactly what it says on the tin (scopes based on any child element's active focus state). Read more about the spec here. So assuming you have a HTML structure of:

<div class="input-wrapper">
    <label for="elem">Label Text
      <input name="elem" id="elem" type="text" />
    </label>
</div>

you could scope the 'focussed' label by simply:

label:focus-within{}

by the same token, you could also scope the parent div with:

div.input-wrapper:focus-within{}

Magical. But not for use today :(

Second up, if you're already using a JS selector engine (i.e. jQuery, Sizzle, etc.), you could also do something along the lines of:

$('input').on("focus", function(){
  var input = $(this);
  // assuming label is the parent, i.e. <label><input /></label>
  var label = $(this).parent();
  label.addClass('focussed');
  input.on("blur", function(){
    label.removeClass('focussed');
    input.off("blur");
  });
});

This is untested but the essence of what this achieves is using a class rather than the :focus pseudo selector. So you can add your focussed styles to label.focussed{}. I've added (and self-removed) the blur handler to facilitate removing the class.

Eloign answered 9/2, 2017 at 2:18 Comment(1)
:focus-within is currently supported in all major / modern browsers developer.mozilla.org/en-US/docs/Web/CSS/:focus-withinNuriel
K
4

Now using Flex box will solve this. Have the label element follow the input element in the HTML. Then use flex-direction: column-reverse to change its position to appear above the input element. You can then use the input:focus + label: {} to target the label.

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

  .input-container > input {
  /* your input styles */
}

 .input-container > input:focus + label {
  /* targets the label when the input receives focus */
  color: red;
 }
<div class="input-container">
  <input type='email' />
  <label>Email</label>
</div>
Knudsen answered 20/11, 2020 at 10:5 Comment(0)
A
2
use:checked instead of :focus and you must give id,name,value into 'input'.
Allergist answered 15/3, 2022 at 16:35 Comment(0)
A
1

Found a good solution - order property made a trick:

input:focus {
        background-color: #F2FFF0;
    }
    
    * {
        font-family: "Arial";
        font-size: 13px;
    }
    
    div.settings {
        display:grid;
        grid-template-columns: max-content max-content;
        grid-gap: 7px
    }
    div.settings label {
        text-align:right;
        padding-top: 3px
    }
    
    div.settings label:after {
        content: ":";
    }
    
    div.settings input:focus  + label:before  {
        content: "\25B6  ";
        font-size: 12px;
        color: red;
    }
    
    input {
        border: 1px solid #ccc;
        padding: 2px 4px;
        font-size: 13px;
    }
<div class="settings">
<input style="order:2" type="text" title="(vardas, pavardė ir pan.)" autocomplete="off" id="name" name="name" required minlength="4" maxlength="128" size="50"><label style="order:1" for="name">Pirkėjas</label>
<input style="order:4" type="text" title="" autocomplete="off" id="company" name="company" required minlength="4" maxlength="128"><label style="order:3" for="company">Įmonės pavadinimas</label>
<input style="order:6" type="text" title="" autocomplete="off" id="companyCode" name="companyCode" required minlength="4" maxlength="128"><label style="order:5; min-width: 160px" for="companyCode">Įmonės (asmens) kodas</label>
</div>
Adalie answered 14/11, 2021 at 9:59 Comment(0)
R
0

I think I have a simpler answer to this and that is just to add tabindex="0".

Rubino answered 16/12, 2023 at 15:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.