1

I want the selection (:checked) to have a different background colour.

Here my example code:

label {
  display: block;
  background: gray;
  border:1px solid black;
  margin-bottom:5px;
  padding:10px;
  cursor: pointer;
}

label + [type="checkbox"]:checked {
  background: yellow;
}
<div class="poll">
  <label class="a"><input type="checkbox" /> Yes</label>
  <label class="a"><input type="checkbox" /> No</label>
</div>

My question is related to: Design survey form

Also take into account the situation where the input is preset in the DOM, but hidden, so the label is still clickable and toggles it.

vsync
  • 118,978
  • 58
  • 307
  • 400
Max Pattern
  • 1,430
  • 7
  • 18
  • This question was closed as duplicate to "similar" questions but they are unhelpful for the situation of the OP. This is a specific case for `input` of type `checkbox`. I've re-opened it. – vsync Jan 17 '23 at 15:29

1 Answers1

6

You can use the :has pseudo selector for that:

enter image description here

label {
  display: block;
  background: gray;
  border:1px solid black;
  margin-bottom:5px;
  padding:10px;
  cursor: pointer;
  user-select: none;
}

label:has([type="checkbox"]:checked) {
  background: yellow;
}
<div class="poll">
  <label class="a"><input type="checkbox" /> Yes</label>
  <label class="a"><input type="checkbox" /> No</label>
</div>

If you need browser backward-compatibility support, here's a trick:

label {
  display: block;
  background: gray;
  border:1px solid black;
  margin-bottom:5px;
  padding:10px;
  cursor: pointer;
  overflow: hidden; /* Important so the outline won't overflow */
  user-select: none;
}

label :checked {
  outline: 9999px solid yellow;
}
<div class="poll">
  <label><input type="checkbox" /> Yes</label>
  <label><input type="checkbox" /> No</label>
</div>

OP asked me in the comments for a solution tailored for a hidden checkbox.

All that is needed is to use the hidden attribute on the input.
Never use CSS display: none to not render an input element. It is preferable to use the designated attribute.

Note that this also has a bug in Firefox. Below is a Firefox-hack to overcome it.

label {
  display: block;
  background: gray;
  border:1px solid black;
  margin-bottom:5px;
  padding:10px;
  cursor: pointer;
  user-select: none;
}

label:has([type="checkbox"]:checked) {
  background: yellow;
}
<div class="poll">
  <label><input type="checkbox" hidden /> Yes</label>
  <label><input type="checkbox" hidden /> No</label>
</div>

Firefox-supported solution:

Extract each input to be above the label element, and use a unique id attribute on each input element, and a matching for attribute on each label:

label {
  display: block;
  background: gray;
  border:1px solid black;
  margin-bottom:5px;
  padding:10px;
  cursor: pointer;
  user-select: none;
}

:checked + label {
  background: yellow;
}
<div class="poll">
  <input type="checkbox" id='poll-1' hidden/>
  <label for='poll-1'>Yes</label>

  <input type="checkbox" id='poll-2' hidden/>
  <label for='poll-2'>No</label>
</div>
vsync
  • 118,978
  • 58
  • 307
  • 400
  • 1
    Great! Thank you! I view minutes i will accept your answer. Have a nice day .. – Max Pattern Jan 17 '23 at 10:59
  • 1
    Your example codes don't seem to work on Firefox (v108). They do work on Chrome. – Martin Jan 17 '23 at 11:04
  • 1
    @Martin - sorry, forgot some people use Firefox. will take a look! – vsync Jan 17 '23 at 11:07
  • @vsync Firefox 108 requires the config setting `layout.css.has-selector.enabled` to be enabled `true`. I expect future versions will have it set by default. `:-)` – Martin Jan 17 '23 at 11:08
  • neither work in FX https://caniuse.com/css-has – mplungjan Jan 17 '23 at 11:08
  • ok even with that setting set and firefox restarted, the `:has` selector on your code still isn't setting the background to yellow `:-(` .. Sorry – Martin Jan 17 '23 at 11:09
  • Here is something interesting https://stackoverflow.com/questions/19145504/style-a-checkbox-in-firefox-remove-check-and-border – mplungjan Jan 17 '23 at 11:13
  • Seems like a Firefox new bug. I will report them – vsync Jan 17 '23 at 11:14
  • 1
    Fixed for Firefox - replaced malfunctioned `box-shadow` with `outline` and opened a [bug for Mozilla](https://bugzilla.mozilla.org/show_bug.cgi?id=1810708) – vsync Jan 17 '23 at 11:30
  • @vsync Thank you for your time! Your second solution will work on Firefox **but** for me doesnt work because i set `input {display: none}`. And then it dont work. Maybe you have an idea? Or i will use javascript and set a class. – Max Pattern Jan 17 '23 at 11:34
  • @vsync yep that works on my firefox now. Cheers! – Martin Jan 17 '23 at 12:11
  • 1
    @MaxPattern - You should have mentioned you are setting `display:none` in your question. I will update my answer now with another solution for such case. – vsync Jan 17 '23 at 13:35
  • Thank you very much @vsync! It works for safari too. I learned something today. that is great. Merci – Max Pattern Jan 17 '23 at 13:52