Skip to content

Instantly share code, notes, and snippets.

@elstgav
Last active March 11, 2025 01:16
Show Gist options
  • Save elstgav/503d860a120b043a5058 to your computer and use it in GitHub Desktop.
Save elstgav/503d860a120b043a5058 to your computer and use it in GitHub Desktop.
Pure SCSS Radio Buttons

Pure SCSS Radio Buttons

SASS component for enabling larger, custom radio buttons. Unfortunately it doesn't work in Firefox (but does fall back to native radios). Completely customizable with SASS variables

A Pen by Gavin Elster on CodePen.

License.

h1 SCSS Radio Buttons
p Overrides the browser&rsquo;s native presentation of a radio button <em>without relying on the radio's label element.</em>
p Every effort should be made to avoid overriding its native <em>behavior</em> however; accessibility and native states should be unaltered.
p
strong Play around with the variables at the top of the SCSS to customize.
label
input> [type='radio' name='q1' checked]
| Checked
label
input> [type='radio' name='q1']
| Unchecked
label
input> [type='radio' name='q1' disabled]
| Disabled
h4 Multiple
input> [type='radio' name='q2']
input> [type='radio' name='q2']
input> [type='radio' name='q2']
input> [type='radio' name='q2']
input> [type='radio' name='q2' checked]
input> [type='radio' name='q2']
input> [type='radio' name='q2']
input> [type='radio' name='q2']
input> [type='radio' name='q2']
$color-light-blue: dodgerblue;
// Gray Scale
$color-gray: lighten(black, 50% ) !default;
$color-light-gray: lighten(black, 80% ) !default;
$color-lighter-gray: lighten(black, 91.8%) !default;
$custom-radio-size: 32px;
$custom-radio-transition-speed: 100ms;
$custom-radio-inset-shadow: inset 0 .1em 1px -.1em rgba(0,0,0,.3);
$custom-radio-pip-color: $color-light-blue;
$custom-radio-pip-size: round($custom-radio-size * .4);
$custom-radio-unchecked-bg: white;
$custom-radio-unchecked-border: transparentize($color-gray, .6);
$custom-radio-checked-bg: mix($custom-radio-unchecked-bg, $custom-radio-pip-color, 60%);
$custom-radio-checked-border: $color-light-blue;
$custom-radio-active-inset-shadow: inset 0 0 2px 3px rgba(0,0,0,.1);
$custom-radio-focus-shadow: 0 0 0 2px transparentize($color-light-blue, .5);
$custom-radio-disabled-bg: $color-lighter-gray;
$custom-radio-disabled-pip-color: $color-light-gray;
// Override the browser's native presentation of a radio button. Every effort should be made to
// avoid overriding its native *behavior* however; keyboard access, accessibility, and native states
// should be unaltered.
@if ($custom-radio-size % 2 == 1) { @error '$custom-radio-size must be even'; }
// round to nearest even number
@if ($custom-radio-pip-size % 2 == 1) { $custom-radio-pip-size: $custom-radio-pip-size - 1; }
input[type="radio"] {
$border-width: 1px;
position: relative;
display: inline-block;
width: $custom-radio-size - 2;
height: $custom-radio-size - 2;
border-radius: 100%;
outline: none !important;
// Radio
// -----
&::before {
position: relative;
top: -$border-width;
left: -$border-width;
display: block;
content: '';
background: $custom-radio-unchecked-bg;
border: $border-width solid $custom-radio-unchecked-border;
border-radius: 100%;
box-shadow: $custom-radio-inset-shadow;
width: $custom-radio-size;
height: $custom-radio-size;
}
&:active::before {
box-shadow: $custom-radio-inset-shadow,
$custom-radio-active-inset-shadow;
}
&:focus::before {
box-shadow: $custom-radio-inset-shadow,
$custom-radio-focus-shadow;
}
&:checked::before {
background: $custom-radio-checked-bg;
border-color: $custom-radio-checked-border;
}
&:disabled::before {
cursor: not-allowed;
background-color: $custom-radio-disabled-bg;
border-color: transparentize($custom-radio-unchecked-border, .2);
}
// Radio Pip
// ---
&::after {
position: relative;
top: -($custom-radio-size / 2) - $border-width;
left: ($custom-radio-size / 2) - $border-width;
display: block;
content: '';
background: $custom-radio-pip-color;
border-radius: 100%;
box-shadow: 0 1px 1px rgba(0,0,0,.1);
width: 0;
height: 0;
}
&:checked::after {
transition: all ease-in-out $custom-radio-transition-speed 0;
top: floor(
- ($custom-radio-size / 2)
- ($custom-radio-pip-size / 2)
- $border-width
);
left: floor(
+ ($custom-radio-size / 2)
- ($custom-radio-pip-size / 2)
- $border-width
+ 1
);
width: $custom-radio-pip-size;
height: $custom-radio-pip-size;
}
&:disabled::after {
background: $custom-radio-disabled-pip-color;
}
}
// Demo CSS
body {
font-family: Avenir Next, Helvetica Neue, sans-serif;
padding: 2em;
}
label {
font-size: 2.5em;
display: block;
}
input + input {
margin-left: .5em;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment