7

I have a <select> on my HTML page with several <option>s; some options are disabled (The select is not disabled). I can style the disabled options:

select option:disabled
{ 
    color: red;
}

However, I would also like to style the selected item if it is disabled. It is not possible for the user to get to this state, but it is possible for the page to be served in this state.

How can I style a select if its selected item is disabled?

Gray
  • 7,050
  • 2
  • 29
  • 52
ctrl-alt-delor
  • 7,506
  • 5
  • 40
  • 52
  • You can't see the options when the select is disabled. You style the select in order to change the text in the select afaik. – Gray Apr 02 '14 at 17:48
  • 2
    @Gray the select is enabled, but some of the options are disabled. Re-read the question. – ANeves Apr 02 '14 at 17:50
  • Would you mind using js? – T J Apr 02 '14 at 17:52
  • @TilwinJoy I can use js, I am currently using a lot of knockout, I tried the optionsAfterRender binding, this set a class, but needed to be re-evaluated (and was not) when I selected another option. – ctrl-alt-delor Apr 02 '14 at 18:03
  • @richard if i understood you correctly, i've shared a possible solution.. – T J Apr 02 '14 at 18:10

7 Answers7

2

This option makes use of the selected attribute, and it also uses jQuery. Here is a fiddle to show an example: JsFiddle

HTML

<select>
    <option>test1</option>
    <option selected disabled>test2</option>
    <option>test3</option>
    <option>test4</option>
</select>

jQuery (onLoad)

$('select > option:selected:disabled').each(function(){
    $(this).parent().css("color","red");
});

$('select').change(function(){
    $(this).css("color", "black");
});

CSS

/*reset color for options*/
select option:not(:disabled) {color:black;}
Gray
  • 7,050
  • 2
  • 29
  • 52
  • Instead of setting the colour to `initial`, why not simply [removing the colour property](http://stackoverflow.com/questions/208105/how-to-remove-a-property-from-a-javascript-object)? – ANeves Apr 03 '14 at 10:08
  • @ANeves I didn't do that... maybe you meant to reply to a different question? I set it to black, and I figured I'd leave it as an exercise to the reader to set it to the proper color. What property would I remove? The Style property? Maybe you could update the fiddle to show what you mean. – Gray Apr 03 '14 at 13:18
  • Derp. :( I meant "black" instead of "initial", yes. And I meant like this: http://jsfiddle.net/nx23C/1/ – ANeves Apr 03 '14 at 13:53
  • @ANeves Ah, I see... so not using `.css()` at all. Maybe a dumb question, but what is the advantage if I am already using jQuery? I understand... kind of... doing this if I can avoid using jQuery altogether, but that wasn't what you suggested. I think setting it to initial is probably a better solution than using black, but I imagined this being used as a validation error... in which case, I would have toggled a class (with jQuery probably) :P – Gray Apr 03 '14 at 14:24
  • If you have it initially pink on CSS, and set it from red back to black (and not pink), it does not work properly; if you set it to pink, maybe it is blue! (You can't easily guess the CSS value.) I agree that toggling a class is the ideal way. – ANeves Apr 03 '14 at 18:39
  • +1 thanks this answer inspired my solution (added as an answer). – ctrl-alt-delor Apr 04 '14 at 14:51
2

If using js is not a problem,

You can do something like this on page load event:

var elem = document.getElementById('idOfYourSelect');
  var selectedOption= elem[elem.selectedIndex];
  if(selectedOption.disabled == true){
   elem.style.color='red'; // apply the styles
}

and change it back to normal on selecting it (if you want to)

elem.onclick= function(){
elem.style.color='initial'; // revert back to normal style
}

check this fiddle

T J
  • 42,762
  • 13
  • 83
  • 138
  • Instead of setting the colour to `initial`, why not simply [removing the colour property](http://stackoverflow.com/questions/208105/how-to-remove-a-property-from-a-javascript-object)? – ANeves Apr 03 '14 at 10:07
  • +1 thanks this answer inspired my solution (added as an answer). – ctrl-alt-delor Apr 04 '14 at 14:52
1

I propose you add a class to the select, and style it in CSS. Then, when the user changes the selection to something valid, you remove the class.

Example

Here is a trivial implementation using jQuery:

HTML

<select>
    <option>test1</option>
    <option selected disabled>test2</option>
    <option>test3</option>
    <option>test4</option>
</select>

jQuery (onLoad)

$('select > option:selected:disabled').each(function() {
    var select = this.parentNode;
    select.classList.add("select-with-disabled-selected-option");
    $(select).change(function() {
        this.classList.remove("select-with-disabled-selected-option");
    });
});

CSS

.select-with-disabled-selected-option {
    color: red;
}

You might not need jQuery

I used jQuery to make it simpler.
But http://youmightnotneedjquery.com/

ANeves
  • 6,219
  • 3
  • 39
  • 63
1

Thanks everyone. This is what I eventually did, with help from lots of the answers and comments.

<script type="text/html" id="fkeyByName-template">
  <select data-bind="optionsCaption: 'Choose...',
             optionsText:  function(item){ return item.value.name;},
             optionsValue: function(item){ return item.id;},
             valueAllowUnset: true, 
             options: (function(){return $root.foreignKeys.values(col.ftype);})(),
             value: value,
             optionsAfterRender:function(option,item){
               $root.setOptionDisable(option,item,value,$element,$data);
             }
             ">
  </select>
  {{! <p data-bind="text: value"></p> }}
</script>

<script type="text/javascript">
  model.setOptionDisable = function (option, item, value, select, data) {
    if (item) {
      ko.applyBindingsToNode(option, {disable: item.value.removed}, item);
      if (value() == item.id) {
        ko.applyBindingsToNode( select,{css: {disabledSelected: item.value.removed}}, data); 
      }
      select.onchange = function() { 
        ko.applyBindingsToNode( select,{css: {disabledSelected: false}}, data); 
      };
    } 
  }
</script>

<style>
select option:disabled, select.disabledSelected
{ 
  color: red;
} 

/*reset color for options*/
select option:not(:disabled) 
{
  color:initial;
}
</style>
ctrl-alt-delor
  • 7,506
  • 5
  • 40
  • 52
  • What is `ko`? what does this do..?! Assume that you're posting this as an answer for somebody elses question, will they understand anything..? BTW posting your own answer by collecting all the answers instead of selecting an answer that helped you to come up with the solution is really **discouraging**. I don't think this is how SO works. Good to know that the answers inspired you though ~ ! – T J Apr 04 '14 at 15:49
  • ko is the knockout.js library. – ctrl-alt-delor Apr 07 '14 at 13:24
  • I would not normally, but a summary answer (this is the only time I have done it.), however there was no one correct answer. Just 3 that helped a lot, to I up-voted them all. – ctrl-alt-delor Apr 07 '14 at 13:26
1

There is a pure CSS solution, with the CSS :has() selector now widely adopted in web browsers.

select option {
  color: black;
}
select option:disabled {
  color: grey;
}
select:has(option:checked:disabled) {
  color: red;
}
<select>
  <option value="1">apples</option>
  <option value="2">oranges</option>
  <option value="3" disabled selected>bananas</option>
</select>
gwyn
  • 111
  • 2
0

It is posible with jquery.

Imagine you have this:

<select class="sel">
   <option disabled="true">one</option>
   <option>two</option>
   <option disabled="true">three</option>
   <option>four</option>
</select>

onload function you can put this:

$('.sel option[disabled="true"]').each(function () {
    $(this).attr('style', 'color:red');
});
Newton
  • 47
  • 9
  • That only styles the option, right? You'd want to do `$(this).parent.css("color","red")`, I think... – Gray Apr 02 '14 at 18:09
0

The Selectors Level 4 draft introduces the Subject of a Selector, which allows you to use

!select option:disabled
{ 
  color: red;
}

But browsers don't support it yet.

Oriol
  • 274,082
  • 63
  • 437
  • 513
  • Interesting: will it when implemented select a `select` that has at least one disabled `options`, as opposed to a select that has selected a disabled option. – ctrl-alt-delor Apr 02 '14 at 18:08
  • 1
    @richard You could do something like... `!select option:selected:disabled`, I believe (assuming your option has the selected attribute). – Gray Apr 02 '14 at 18:12