Can you style an html radio button to look like a checkbox?

Viewed 191606

I have an html form that a user will fill out and print. Once printed, these forms will be faxed or mailed to a government agency, and need to look close enough like the original form published by said agency that a government bureaucrat doesn't spot that this is a reproduction. The data entered in the form is not saved anywhere or even submitted back to a web server. All that matters is that our users can easily find these forms on our intranet site and type into the form for printing with their normal keyboard.

On the screen I want to leave the radio button as-is, to enforce and communicate radio button usage (choose only one option). However, when it prints out I need it to print with the square checkbox style rather than the round radio button style. I know how to use a media selector to set styles for print only, so that's not the issue. It's just that I don't know if I can style the radio button like I want at all.

If I can't get this working I'm gonna have to create a checkbox to shadow each radio button, use javascript to keep the checkboxes and radio buttons in sync, and css to show the one I care about in the proper medium. Obviously if I can just style them it would save a lot of work.

14 Answers

In CSS3:

input[type=radio] {content:url(mycheckbox.png)}
input[type=radio]:checked {content:url(mycheckbox-checked.png)}

In reality:

<span class=fakecheckbox><input type=radio><img src="checkbox.png" alt=""></span>

@media screen {.fakecheckbox img {display:none}}
@media print {.fakecheckbox input {display:none;}}

and you'll need Javascript to keep <img> and radios in sync (and ideally insert them there in a first place).

I've used <img>, because browsers are usually configured not to print background-image. It's better to use image than another control, because image is non-interactive and less likely to cause problems.

Yes it can be done using this css, i've hidden the default radio button and made a custom radio button that looks like a checkbox. Working Perfect in 2022.

.css-prp
{
  color: #17CBF2;
  font-family: arial;
}


.con1 {
  display: block;
  position: relative;
  padding-left: 25px;
  margin-bottom: 12px;
  cursor: pointer;
  font-size: 15px;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

/* Hide the browser's default radio button */
.con1 input {
  position: absolute;
  opacity: 0;
  cursor: pointer;
}

/* Create a custom radio button */
.checkmark {
  position: absolute;
  top: 0;
  left: 0;
  height: 18px;
  width: 18px;
  background-color: lightgrey;
  border-radius: 10%;
}

/* When the radio button is checked, add a blue background */
.con1 input:checked ~ .checkmark {
  background-color: #17CBF2;
}
<label class="con1"><span>Yes</span>
  <input type="radio" name="radio1" checked>
  <span class="checkmark"></span>
</label>
<label class="con1"><span>No</span>
  <input type="radio" name="radio1">
  <span class="checkmark"></span>
</label>

Pure Vanilla CSS / HTML solution in 2021. It uses the CSS appearance: none; property.

Seems to be compatible with all major browsers at this time:

https://caniuse.com/?search=appearance%3A%20none

input[type="radio"]{
   appearance: none;
   border: 1px solid #d3d3d3;
   width: 30px;
   height: 30px;
   content: none;
   outline: none;
   margin: 0;
   box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
}

input[type="radio"]:checked {
  appearance: none;
  outline: none;
  padding: 0;
  content: none;
  border: none;
}

input[type="radio"]:checked::before{
  position: absolute;
  color: green !important;
  content: "\00A0\2713\00A0" !important;
  border: 1px solid #d3d3d3;
  font-weight: bolder;
  font-size: 21px;
}
<input type="radio" name="radio" checked>
<input type="radio" name="radio">
<input type="radio" name="radio">

Simple and neat with fontawesome

input[type=radio] {
    -moz-appearance: none;
    -webkit-appearance: none;
    -o-appearance: none;
    outline: none;
    content: none;
    margin-left: 5px;
}

input[type=radio]:before {
    font-family: "FontAwesome";
    content: "\f00c";
    font-size: 25px;
    color: transparent !important;
    background: #fff;
    width: 25px;
    height: 25px;
    border: 2px solid black;
    margin-right: 5px;
}

input[type=radio]:checked:before {
    color: black !important;
}

You can hide de default radio appareance and then draw the check with clip-path in the pseudo-element, no javascript needed.

 label{
     display: block;
      margin-bottom: 10px;
  }

input[type=radio] {
    appearance: none;
    background-color: #fff;
    width: 15px;
    height: 15px;
    border: 2px solid #ccc;
    border-radius: 2px;
    display: inline-grid;
    place-content: center; 
  }

input[type=radio]::before {
    content: "";
    width: 10px;
    height: 10px;
    transform: scale(0);
    transform-origin: bottom left;
    background-color: #fff;
    clip-path: polygon(13% 50%, 34% 66%, 81% 2%, 100% 18%, 39% 100%, 0 71%);
}

input[type=radio]:checked::before {
    transform: scale(1);
}
input[type=radio]:checked{
    background-color:   #0075FF;
    border: 2px solid #0075FF;
}
<label>
    <input type="radio" name="fruit"> Apple
</label>
<label>
    <input type="radio" name="fruit"> Banana
</label>
<label>
    <input type="radio" name="fruit"> Orange
</label>
<label>
    <input type="radio" name="fruit"> Avocado
</label>

I don't think you can make a control look like anything other than a control with CSS.

Your best bet it to make a PRINT button goes to a new page with a graphic in place of the selected radio button, then do a window.print() from there.

Simple but optimal solution.

.custom-radio[type="radio"]{
   appearance: none;
   border: 1px solid #d3d3d3;
   width: 18px;
   height: 18px;
   content: none;
   outline: none;
   border-radius:100%;
   margin: 0;
   
}

.custom-radio[type="radio"]:checked {
  appearance: none;
  border-radius:100%;
  outline: none;
  padding: 0;
  content: none;
  border: none;
}

.custom-radio[type="radio"]:checked::before{
  position: absolute;
  background:#0c1332 ;
  accent-color:blue;
  border-radius:100%;
  color: white !important;
  content: "\00A0\2713\00A0" !important;
  border: 1px solid #d3d3d3;
  font-weight: bolder;
  font-size: 13px;
}
  <p>Please select your favorite Web language:</p>
  <input type="radio" id="html" class="custom-radio" name="fav_language" value="HTML">
  <label for="html">HTML</label><br>
  <input type="radio" id="css" name="fav_language" class="custom-radio" value="CSS">
  <label for="css">CSS</label><br>
  <input type="radio" id="javascript" name="fav_language" class="custom-radio" value="JavaScript">
  <label for="javascript">JavaScript</label>

So I have been lurking on stack for so many years. This is actually my first time posting on here.

Anyhow, this might seem insane but I came across this post while struggling with the same issue and came up with a dirty solution. I know there are more elegant ways to perhaps set this as a property value but:

if you look at lines 12880-12883 in tcpdf.php :

$fx = ((($w - $this->getAbsFontMeasure($tmpfont['cw'][`110`])) / 2) * $this->k);
$fy = (($w - ((($tmpfont['desc']['Ascent'] - $tmpfont['desc']['Descent']) * $this->FontSizePt / 1000) / $this->k)) * $this->k);
$popt['ap']['n'][$onvalue] = sprintf('q %s BT /F%d %F Tf %F %F Td ('.chr(`110`).') Tj ET Q', $this->TextColor, $tmpfont['i'], $this->FontSizePt, $fx, $fy);
$popt['ap']['n']['Off'] = sprintf('q %s BT /F%d %F Tf %F %F Td ('.chr(`111`).') Tj ET Q', $this->TextColor, $tmpfont['i'], $this->FontSizePt, $fx, $fy);

and lines 13135-13138 :

$fx = ((($w - $this->getAbsFontMeasure($tmpfont['cw'][`108`])) / 2) * $this->k);
$fy = (($w - ((($tmpfont['desc']['Ascent'] - $tmpfont['desc']['Descent']) * $this->FontSizePt / 1000) / $this->k)) * $this->k);
$popt['ap']['n']['Yes'] = sprintf('q %s BT /F%d %F Tf %F %F Td ('.chr(`108`).') Tj ET Q', $this->TextColor, $tmpfont['i'], $this->FontSizePt, $fx, $fy);
$popt['ap']['n']['Off'] = sprintf('q %s BT /F%d %F Tf %F %F Td ('.chr(`109`).') Tj ET Q', $this->TextColor, $tmpfont['i'], $this->FontSizePt, $fx, $fy);

Those widgets are rendered from the zapfdingbats font set... just swap the character codes and voila... checks are radios and/or vice versa. This also opens up ideas to make a custom font set to use here and add some nice styling to your form elements.

Anyhow, just figured I would offer my two cents ... it worked awesome for me.

Related