Theo
Theo

Reputation: 1433

Styling a Label Attached to Text Inputs

I am trying to style all labels that precede input fields, except for checkboxes and radio buttons.

Using the ~ selector I've gotten everything working except "text" input tags--every other type I try will apply the style, but the text does not, and I've been staring at it for too long.

HTML

<form>
  <label for="MyText">Text Field</label>
  <input id="MyText" type="text" /><br />

  <label for="MyUrl">Url Field</label>
  <input id="MyUrl" type="url" /><br />

  <label for="MyCheck">Checkbox</label>
  <input id="MyCheck" type="checkbox" /><br />
</form>

CSS

INPUT:not([type="radio"]):not([type="checkbox"]) ~ LABEL {
  width: 100px;
}

INPUT:not([type="radio"]):not([type="checkbox"]) {
  width: 200px;
}

LABEL { display: inline-block; }

I would like to avoid specifying the text input labels by ID or class to keep my code clean.

I have a JSFiddle for this as well: http://jsfiddle.net/buzzsurfr/GWk96/1/

EDIT: This screenshot is from JSFiddle. I tried it using FF & Chrome. Text Input Label is not lined up with one below it (a "url")

Upvotes: 3

Views: 5761

Answers (5)

Antony Booth
Antony Booth

Reputation: 51

A solution for a basic Material Design type label where a placeholder is replaced by a label.

HTML

<div class="input-container">
    <input name="email" type="email" placeholder="Enter Email Address">    
    <label for="email">Email Address</label>
</div>

CSS

.input-container {
  position: relative;
}

.input-container > label {
  opacity: 0;
  position: absolute;
  left: .5em;
  top: -1.2em;
  font-size: smaller;  
  transition: opacity 1s ease-in;
}

.input-container > input:not(:placeholder-shown) + label {
  opacity: 1;
}   

You can add the attribute 'type' selectors to exclude input types. I.E: checkbox or radio

input:not(:placeholder-shown):not([type="radio"]):not([type="checkbox"]) + label

Upvotes: 1

Antonio Ooi
Antonio Ooi

Reputation: 1828

If you can change your naming convention for your id attribute of each input, for example:

  • input type="text": txtSomething
  • input type="checkbox": chkSomething
  • input type="radio": optSomething etc.

Then your label will become:

<form>
  <label for="txtMyText">Text Field</label>
  <input id="txtMyText" type="text" /><br />

  <label for="txtMyUrl">Url Field</label>
  <input id="txtMyUrl" type="url" /><br />

  <label for="chkMyCheck">Checkbox</label>
  <input id="chkMyCheck" type="checkbox" /><br />
</form>

As such, you can use Regular Expression for your CSS Selector like this without swapping your label with input and float it:

label[for^="txt"] {
    width: 100px;
}

More about CSS Attribute Selectors here.

Upvotes: 0

DannyB
DannyB

Reputation: 14776

If you are looking for a "preceding" CSS selector, there is none as far as I know.

So, your best option, assuming you have control over the HTML and not only the CSS, is to add classes to the labels you want to style. This would be the simplest, cleanest and cross browser solution.

Now, in case you want to style all the labels in the form, except the labels that follow some other elements (say, checkboxes), perhaps this approach would work for you:

  1. Style all labels
  2. Override labels that follow checkboxes / radios

Like so:

label {
    width: 100px;
    background:#ccc;
}

input[type="checkbox"] + label {
    background:#eee;
    display:inline;
}

And the mandatory fiddle.

Upvotes: 2

Fico
Fico

Reputation: 2407

Your code is working as it should Your label attached to the text input is not targeted becouse there is not an input tag as preceding element

This code you are using:

INPUT:not([type="radio"]):not([type="checkbox"]) ~ LABEL {
  width:300px;
}

says:

Target all labels that are preceded by an input AND THIS INPUT etc,etc As there is not input preceding the text label it will not be targeted

Note: I suppose you are targeting the label.,,,,,

Upvotes: 0

Vadim
Vadim

Reputation: 8789

You can swap input and label in the HTML, that will allow you to use + that means "immediately followed by" in order to apply styles. To swap them back visually you can use float. Something like this:

HTML

<form>
    <input id="MyText" type="text" />
    <label for="MyText">Text Field</label>
    <br />
    <input id="MyUrl" type="url" />
    <label for="MyUrl">Url Field</label>
    <br />
    <input id="MyCheck" type="checkbox" />
    <label for="MyCheck">Checkbox</label>
    <br />
</form>

CSS

INPUT:not([type="radio"]):not([type="checkbox"]) + LABEL {
    width: 100px;
}

INPUT:not([type="radio"]):not([type="checkbox"]) {
    width: 200px;
}

LABEL { 
    display: inline-block;
    float: left;
}

BR {
    clear: both;
}

Fiddle http://jsfiddle.net/G3FED/3/

More info about + CSS selector you can find here http://www.w3.org/TR/selectors/#adjacent-sibling-combinators

Upvotes: 2

Related Questions