Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save matt-daniel-brown/59c1875740a3eea2c9176ba79a2a1210 to your computer and use it in GitHub Desktop.
Save matt-daniel-brown/59c1875740a3eea2c9176ba79a2a1210 to your computer and use it in GitHub Desktop.
Custom radio/checkbox buttons with perfect alignment
<div class="container max-width-xs padding-y-md">
<form>
<fieldset class="margin-bottom-md">
<legend class="form-legend">Custom Radio Buttons</legend>
<ul class="flex flex-column gap-xxxs">
<li>
<input class="radio" type="radio" name="radio-button" id="radio-1" checked>
<label for="radio-1">Choice 1</label>
</li>
<li>
<input class="radio" type="radio" name="radio-button" id="radio-2">
<label for="radio-2">Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatem, vero. Dolore et eveniet maxime hic tempora neque explicabo eaque doloremque!</label>
</li>
</ul>
</fieldset>
<fieldset class="margin-bottom-md">
<legend class="form-legend">Custom Checkboxes</legend>
<div class="flex flex-column gap-xxxs">
<div>
<input class="checkbox" type="checkbox" id="checkbox-1" checked>
<label for="checkbox-1">Option 1</label>
</div>
<div>
<input class="checkbox" type="checkbox" id="checkbox-2">
<label for="checkbox-2">Option 2</label>
</div>
</div>
</fieldset>
<fieldset class="margin-bottom-md">
<legend class="form-legend">Different Text Size</legend>
<div class="flex flex-column gap-xxxs">
<div>
<input class="checkbox" type="checkbox" id="checkbox-1b" checked>
<label class="text-md" for="checkbox-1b">Option 1</label>
</div>
<div>
<input class="checkbox" type="checkbox" id="checkbox-2b">
<label class="text-md" for="checkbox-2b">Option 2</label>
</div>
</div>
</fieldset>
<fieldset>
<legend class="form-legend">Inline Buttons</legend>
<div class="flex flex-wrap gap-md">
<div>
<input class="checkbox" type="checkbox" id="checkbox-1c" checked>
<label for="checkbox-1c">Option 1</label>
</div>
<div>
<input class="checkbox" type="checkbox" id="checkbox-2c">
<label for="checkbox-2c">Option 2</label>
</div>
</div>
</fieldset>
</form>
</div>
/* --------------------------------
Custom radio and checkbox buttons
Tutorial: https://codyhouse.co/blog/post/custom-accessible-radio-checkbox-buttons-vertical-alignment
-------------------------------- */
:root {
// radios and checkboxes
--checkbox-radio-size: 18px;
--checkbox-radio-gap: var(--space-xxxs); // gap between button and label
--checkbox-radio-border-width: 2px;
--checkbox-radio-line-height: var(--body-line-height);
// radio buttons
--radio-marker-size: 8px;
// checkboxes
--checkbox-marker-size: 12px;
--checkbox-radius: 4px;
}
// hide native buttons
.radio,
.checkbox {
position: absolute;
margin: 0 !important;
padding: 0 !important;
opacity: 0;
height: 0;
width: 0;
pointer-events: none;
}
// label
.radio + label,
.checkbox + label {
display: inline-flex;
align-items: flex-start;
line-height: var(--checkbox-radio-line-height);
user-select: none;
cursor: pointer;
}
// custom buttons - basic style
.radio + label::before,
.checkbox + label::before {
content: '';
display: inline-block;
position: relative;
top: calc((1em * var(--checkbox-radio-line-height) - var(--checkbox-radio-size)) / 2);
flex-shrink: 0;
width: var(--checkbox-radio-size);
height: var(--checkbox-radio-size);
background-color: var(--color-bg);
border-width: var(--checkbox-radio-border-width);
border-color: var(--color-contrast-low);
border-style: solid;
background-repeat: no-repeat;
background-position: center;
margin-right: var(--checkbox-radio-gap);
transition: transform .2s, border .2s;
}
// :hover
.radio:not(:checked):not(:focus) + label:hover::before,
.checkbox:not(:checked):not(:focus) + label:hover::before {
border-color: lightness(var(--color-contrast-low), 0.7);
}
// radio only style
.radio + label::before {
border-radius: 50%;
}
// checkbox only style
.checkbox + label::before {
border-radius: var(--checkbox-radius);
}
// :checked
.radio:checked + label::before,
.checkbox:checked + label::before {
background-color: var(--color-primary);
box-shadow: none;
border-color: var(--color-primary);
transition: transform .2s;
}
// :active
.radio:active + label::before,
.checkbox:active + label::before {
transform: scale(0.8);
transition: transform .2s;
}
// :checked:active
.radio:checked:active + label::before,
.checkbox:checked:active + label::before {
transform: none;
transition: none;
}
// radio button icon
.radio:checked + label::before {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cg class='nc-icon-wrapper' fill='%23ffffff'%3E%3Ccircle cx='8' cy='8' r='8' fill='%23ffffff'%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");
background-size: var(--radio-marker-size);
}
// checkbox button icon
.checkbox:checked + label::before {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpolyline points='1 6.5 4 9.5 11 2.5' fill='none' stroke='%23FFFFFF' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'/%3E%3C/svg%3E");
background-size: var(--checkbox-marker-size);
}
// :focus
.radio:checked:active + label::before,
.checkbox:checked:active + label::before,
.radio:focus + label::before,
.checkbox:focus + label::before {
border-color: var(--color-primary);
box-shadow: 0 0 0 3px alpha(var(--color-primary), 0.2);
}
// --radio--bg, --checkbox--bg -> variation with background color
.radio--bg + label, .checkbox--bg + label {
padding: var(--space-xxxxs) var(--space-xxxs);
border-radius: var(--radius-md);
transition: background .2s;
}
.radio--bg + label:hover, .checkbox--bg + label:hover {
background-color: var(--color-contrast-lower);
}
.radio--bg:active + label,
.checkbox--bg:active + label,
.radio--bg:focus + label,
.checkbox--bg:focus + label {
background-color: alpha(var(--color-primary), 0.1);
}
<link href="https://unpkg.com/codyhouse-framework/main/assets/css/style.css" rel="stylesheet" />
<link href="https://codepen.io/codyhouse/pen/oNxLjqp" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment