1

I'm trying to customize the radio and checkboxes using only css. I'm almost there except 2 little details: here is a markup sample:

    <section>
    <label class="cbox radio">
        <input name="how" type="radio" checked="checked" /> My first radio box
    </label>

    <label class="cbox radio">
        <input name="how" type="radio" /> My second radio box
    </label>

    <label class="cbox radio">
        <input name="how" type="radio" /> My third radio box
    </label>
</section>

<section>
    <label class="cbox box">
        <input name="check1" type="checkbox" checked="checked" /> My first box
    </label>

    <label class="cbox box">
        <input name="check2" type="checkbox" /> My second box
    </label>
</section>

Every thing works fine but i can't make it work when the box is checked. I'm trying to use this pseudo class:

*::before, *::after {
    box-sizing: border-box;
}

.cbox {
    display: block;
    position: relative;
    margin: 10px 0;
    padding-left: 35px;
    cursor: pointer;
}

.cbox > input {
    position: absolute;
    left: -9999px;
}

.cbox::before, .cbox::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
}

.cbox.radio::before, .cbox.radio::after {
    border-radius: 50%;
}

.cbox::before {
    display: block;
    width: 20px;
    height: 20px;
    border: 1px solid #c1caca;  
}

.cbox::after {
    display: none;
    width: 12px;
    height: 12px;
    margin: 4px;
    background-color: #2e4a5d;
    box-shadow: inset 0 15px 23px -10px rgba(187,230,240,.3),0 2px 2px rgba(0,0,0,.1);
}

/*input:checked + .cbox::before, input:hover + .cbox::before, */
.cbox.on::before, .cbox:hover::before {
    background-color: #eaf1f6;
    border-color: #a0afbb;
}

/* input:checked + .cbox::after, */
.cbox.on::after {
    display: block;
}

And here the jquery

$(".cbox input").change(function() {
        if($(this).is(':checked')) $(this).parent('label').toggleClass('on');
});

1- is there a way to make this css work?

2- since the selector :checked is only supported on IE9+, is it recommended to use selectivizr ? or is there a better fallback solution?

Thanks a lot

5
  • ::after can`t have descendants, what you want to do exactly?
    – user4994625
    Commented May 26, 2016 at 9:50
  • Thanks for your reply. with the ::after I'm trying to add the bullet for the checked boxes, while keeping the exact structure i have
    – Websphere
    Commented May 26, 2016 at 9:57
  • whithout javascript and the input inside the label is not posible (there is not parent selector in CSS). The best solution was one that has been deleted with the label after the input.
    – user4994625
    Commented May 27, 2016 at 9:52
  • Ok, if you can use javascript see my answer below
    – user4994625
    Commented May 27, 2016 at 10:14
  • Cool, thanks. I'll improve and optimise the code and will post it when i'm done ;)
    – Websphere
    Commented May 27, 2016 at 10:30

3 Answers 3

1

Just ditch the ::after pseudo class:

.cbox.radio input:checked { display: none; }
<label class="cbox radio">
    <input name="how" type="radio" checked="checked" /> My first box
    <input name="how2" type="radio" /> My first box
</label>

Fiddle: https://jsfiddle.net/84x66oux/

Btw, you won't be able to customize radios/checkboxes without hiding them in the first place, and adding the whole style yourself. Check this codepen for example

2
  • Thanks for your answer. I actually don't really understand your example. I should keep the visual of boxes that are checked!!
    – Websphere
    Commented May 26, 2016 at 9:59
  • Yes, but none of the properties would reflect a working example. Try to border: 1px solid red; on an input[type=radio] and it won't show a red border ;). I put display:none so that you'd see it actually works.
    – soyuka
    Commented May 26, 2016 at 10:01
1

You can try this one

    <style>
    /*****************************************
      RADIO BUTTONS
    ******************************************/
    input[type="radio"] {
      display: none;
    }
    input[type="radio"] + span {
      background-color: #fefefe;
      border: 1px solid;
      border-color: #ccc #fff #fff #ccc;
      border-radius: 50px;
      box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15);
      display: inline-block;
      float: left;
      margin-right: 7px;
      padding: 7px;
      position: relative;
      -webkit-appearance: none;
    }
    input[type="radio"]:checked + span {
      color: #f00;
    }
    input[type="radio"]:checked + span:after {
      background: #f00;
      border-radius: 50px;
      box-shadow: inset 1px 1px 1px rgba(255, 255, 255, 0.75), inset -1px -1px 1px rgba(0, 0, 0, 0.75);
      content: " ";
      height: 10px;
      left: 2px;
      position: absolute;
      top: 2px;
      width: 10px;
    }
    label:hover input[type="radio"] + span {
      border-color: #900 #f00 #f00 #900;
    }
</style>
<label>
  <input type="radio" name="radio" value="1" checked> <span></span> Option first
</label>
1
  • Thanks again for your code. I'm really bothered to have to add a <span> tag, that means i have to change it in all the pages... :/ I'm trying to find a solution to keep the exact markup i mentioned in my initial code. I think the solution would be to use jquery if it's not possible in pure CSS...
    – Websphere
    Commented May 26, 2016 at 10:05
0

$(".radio input").click(function() {
  if ($(this).is(':checked')) {
    $(".radio ").removeClass('on')
    $(this).parent('label').addClass('on');
  }
});

$(".box input").click(function() {
  if ($(this).is(':checked')) {
    $(this).parent('label').addClass('on');
  } else {
    $(this).parent('label').removeClass('on');
  }
});
*::before,
*::after {
  box-sizing: border-box;
}

.cbox {
  display: block;
  position: relative;
  margin: 10px 0;
  padding-left: 35px;
  cursor: pointer;
}

.cbox > input {
  position: absolute;
  left: -9999px;
}

.cbox::before,
.cbox::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
}

.cbox.radio::before,
.cbox.radio::after {
  border-radius: 50%;
}

.cbox::before {
  display: block;
  width: 20px;
  height: 20px;
  border: 1px solid #c1caca;
}

.cbox::after {
  display: none;
  width: 12px;
  height: 12px;
  margin: 4px;
  background-color: #2e4a5d;
  box-shadow: inset 0 15px 23px -10px rgba(187, 230, 240, .3), 0 2px 2px rgba(0, 0, 0, .1);
}


/*input:checked + .cbox::before, input:hover + .cbox::before, */

.cbox.on::before,
.cbox:hover::before {
  background-color: #eaf1f6;
  border-color: #a0afbb;
}


/* input:checked + .cbox::after, */

.cbox.on::after {
  display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section>
  <label class="cbox radio">
    <input name="how" type="radio" /> My first radio box
  </label>

  <label class="cbox radio">
    <input name="how" type="radio" /> My second radio box
  </label>

  <label class="cbox radio">
    <input name="how" type="radio" /> My third radio box
  </label>
</section>

<section>
  <label class="cbox box">
    <input name="check1" type="checkbox" /> My first box
  </label>

  <label class="cbox box">
    <input name="check2" type="checkbox" /> My second box
  </label>
</section>

Not the answer you're looking for? Browse other questions tagged or ask your own question.