Explain Codes LogoExplain Codes Logo

Use images instead of radio buttons

web-development
responsive-design
css-transitions
accessibility
Alex KataevbyAlex Kataev·Sep 18, 2024
TLDR

To morph images into clickable radio buttons, hide the actual <input type="radio"> elements and visually represent them with <label> elements. Each label is set with a background-image. When the image is clicked, it triggers the associated radio button thanks to the for attribute. Give users feedback by styling the selected image with CSS's :checked selector.

<style> .image-radio { display: none; } /* Peekaboo, I see you? No, not yet */ .radio-label { cursor: pointer; background-size: cover; width: 100px; height: 100px; /* Your image's dimension goes here */ } .image-radio:checked + .radio-label { border: 2px solid #f00; } /* Highlight selected */ </style> <form> <input type="radio" id="img1" class="image-radio" name="choice" /> <label for="img1" class="radio-label" style="background-image: url('img1.jpg');"></label> <input type="radio" id="img2" class="image-radio" name="choice" /> <label for="img2" class="radio-label" style="background-image: url('img2.jpg');"></label> </form>

Resize the .radio-label to match your images. Clicking the image updates the radio button's state, just like magic.

Improved interaction with enhanced accessibility

Boosting visual cues during user interaction can improve user experience with your radio buttons. Add some flair with CSS transitions or animations:

.radio-label { transition: transform 0.2s ease; } .image-radio:checked + .radio-label { transform: scale(1.1); /* Becomes larger when selected because why not? */ }

Accessibility isn't just a buzzword, it's essential. Screen readers should be able to understand the options even when the actual radio buttons are hidden. Ensure to include alternative text:

<input type="radio" id="img3" class="image-radio" name="choice" /> <label for="img3" class="radio-label" aria-label="Dog Shirt" style="background-image: url('img3.jpg');"></label>

Now, you're not hiding anything from the screen readers.

Across all browsers

Providing a consistent experience across different browsers is a key in web development. Each browser has its own default styles and may not always be cooperative. Fight this inconsistency using appearance property with vendor prefixes:

.image-radio { -webkit-appearance: none; /* Because Chrome needs extra love */ -moz-appearance: none; /* And Firefox too */ appearance: none; }

Don't forget about good ol' feature detection libraries like Modernizr for extra browser compatibility.

Styling the focus and selection

Paying attention to smaller details like form interactions enhances the overall experience. Use CSS to style states like :focus and :checked:

.radio-label:focus-within { box-shadow: 0 0 0 2px #5b9dd9; /* Blue shadow for focused, because blue is cool */ .image-radio:focus + .radio-label { outline: none; } /* Removes the odd focus ring, it's ugly anyway */

For a responsive layout, you may want to use relative units like em or vw for sizes and positioning. Your radio images would now gracefully adapt to different screen sizes.

Seamless integration with added customization

Ensure radio buttons within the same group share the same name attribute. When you select an image, .image-radio:checked kicks in, and with ::after pseudo-element, you can add custom icons or checkmarks to your images:

.image-radio:checked + .radio-label::after { content: url('checkmark-icon.png'); /* That's right, it's checked! */ position: absolute; top: 10px; right: 10px; }

To pre-select a radio option, just add the checked attribute:

<input type="radio" id="img1" class="image-radio" name="choice" checked />

Stop text selection on clickable images by using user-select: none. No accidental highlighting ever.

Troubleshoot like a pro

Seeing selection highlights during interaction? Here's how you fight it off using user-select property set to none:

.radio-label { user-select: none; } /* No more accidental selection */

Another enemy is improper image scaling: ensure no stretching or pixelation with the right background properties:

.radio-label { background-size: contain; /* Your image won't act weird anymore */ background-position: center; /* Stay in the center, image! */ }