Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Style <select> element based on selected <option>

Is it possible to style a select element based on what option is selected with CSS only? I am aware of existing JavaScript solutions.

I tried to style the option element itself, but this will give style only to the option element in the list of options, not to the selected element.

select[name="qa_contact"] option[value="3"] {
  background: orange;
}

http://jsfiddle.net/Aprillion/xSbhQ/

If not possible with CSS 3, will CSS 4 subject selector help in the future - or will this stay a forbidden fruit to CSS?

Update 2022: using :has pseudo-class can help to style the select itself (in browsers that support both the :has pseudo-class and styling of <select>), but it only works for HTML attributes, so only if the select has the option explicitly selected initially. It will not work dynamically without JS - after the user changes selection, that will only change DOM properties, but not the HTML attributes on which CSS attribute selectors depend:

select:has(option[selected][value="3"]) {
  background: orange;
}
like image 674
Aprillion Avatar asked May 02 '13 17:05

Aprillion


People also ask

How do you style an option element?

You can style the option elements to some extent. Using the * CSS selector you can style the options inside the box that is drawn by the system. That is true only because the all selector targets the shadow DOM innards, you can target those manually per browser.

How do I style a selection dropdown in CSS?

There are many ways to design a <select> dropdown menu using CSS. The Dropdown Menu is mainly used to select an element from the list of elements. Each menu option can be defined by an <option> element that can nested inside the <select> element.

How do I change the select CSS option?

To change the selected option background-color CSS style, we can set the style attribute of the select and option elements. to set the whole select element to background color 009966 and color FFF . Then we override the the styles in the option elements with style="background: white; color: black;" .


2 Answers

Impossible? Hold my beer.

Make the select element aware of the current option. CSS can handle the rest. For this, all we need is a value assignment in the onchange event. With a little more effort you can also initialize the <select> tag by its original value; not included below but it's super easy, just give it a "data-chosen" property when composing the markup.

    <select onchange=" this.dataset.chosen = this.value; ">
        ...
        ...
    </select>

And now you can easily target & style it:

select[data-chosen='opt3'] { 
    border: 2px solid red;
}

See on CodePen.

Side note: "chosen" is no magic word, just a descriptive name - it could be "SantaClaus". It would also look better that way.

like image 109
dkellner Avatar answered Oct 26 '22 12:10

dkellner


Unfortunately, yes - this is something not currently possible with only CSS. As mentioned in the answers and comments to this question, there is currently no way to make the parent element receive styling based on its children.

In order to do what you're wanting, you would essentially have to detect which of the children (<option>) is selected, and then style the parent accordingly.

You could, however, accomplish this with a very simple jQuery call, as follows:

HTML

<select>
  <option value="foo">Foo!</option>
  <option value="bar">Bar!</option>
</select>

jQuery

var $select = $('select');
$select.each(function() {
    $(this).addClass($(this).children(':selected').val());
}).on('change', function(ev) {
    $(this).attr('class', '').addClass($(this).children(':selected').val());
});

CSS

select, option { background: #fff; }
select.foo, option[value="foo"] { background: red; }
select.bar, option[value="bar"] { background: green; }

Here is a working jsFiddle.

Back to the question about the future of selectors. Yes - the "Subject" selectors are intended to do exactly what you mention. If/when they ever actually go live in modern browsers, you could adapt the above code to:

select { background: #fff; }
!select > option[value="foo"]:checked { background: red; }
!select > option[value="bar"]:checked { background: green; }

As a side-note, there is still debate about whether the ! should go before or after the subject. This is based on the programming standard of !something meaning "not something". As a result, the subject-based CSS might actually wind up looking like this instead:

select { background: #fff; }
select! > option[value="foo"]:checked { background: red; }
select! > option[value="bar"]:checked { background: green; }
like image 45
Troy Alford Avatar answered Oct 26 '22 10:10

Troy Alford