Pure semantic HTML/CSS solution
This is easy to implement on your own, no pre-made solution necessary. Also it will teach you a lot as you don’t seem too easy with CSS.
This is what you need to do:
Your checkboxes need to have distinct id
attributes. This allows you to connect a <label>
to it, using the label’s for
-attribute.
Example:
<input type="checkbox" id="myCheckbox1" /> <label for="myCheckbox1"><img src="http://someurl" /></label>
Attaching the label to the checkbox will trigger a browser behaviour: Whenever someone clicks the label (or the image inside it), the checkbox will be toggled.
Next, you hide the checkbox by applying for example display: none;
to it.
Now all that is left to do is set the style you want for your label::before
pseudo element (which will be used as the visual checkbox replacement elements):
label::before { background-image: url(../path/to/unchecked.png); }
In a last tricky step, you make use of CSS’ :checked
pseudo selector to change the image when the checkbox is checked:
:checked + label::before { background-image: url(../path/to/checked.png); }
The +
(adjacent sibling selector) makes sure you only change labels that directly follow the hidden checkbox in the markup.
You can optimize that by putting both images in a spritemap and only applying a change in background-position
instead of swapping the image.
Of course you need to position the label correctly and apply display: block;
and set correct width
and height
.
Edit:
The codepen example and snippet, which I created after these instructions, use the same technique, but instead of using images for the checkboxes, the checkbox replacements are done purely with CSS, creating a ::before
on the label that, once checked, has content: "✓";
. Add some rounded borders and sweet transitions and the result is really likable!
Here is a working codepen that showcases the technique and doesn’t require images for the checkbox:
Here is the same code in a snippet:
ul { list-style-type: none; } li { display: inline-block; } input[type="checkbox"][id^="cb"] { display: none; } label { border: 1px solid #fff; padding: 10px; display: block; position: relative; margin: 10px; cursor: pointer; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } label::before { background-color: white; color: white; content: " "; display: block; border-radius: 50%; border: 1px solid grey; position: absolute; top: -5px; left: -5px; width: 25px; height: 25px; text-align: center; line-height: 28px; transition-duration: 0.4s; transform: scale(0); } label img { height: 100px; width: 100px; transition-duration: 0.2s; transform-origin: 50% 50%; } :checked+label { border-color: #ddd; } :checked+label::before { content: "✓"; background-color: grey; transform: scale(1); } :checked+label img { transform: scale(0.9); box-shadow: 0 0 5px #333; z-index: -1; }
<ul> <li><input type="checkbox" id="cb1" /> <label for="cb1"><img src="https://picsum.photos/seed/1/100" /></label> </li> <li><input type="checkbox" id="cb2" /> <label for="cb2"><img src="https://picsum.photos/seed/2/100" /></label> </li> <li><input type="checkbox" id="cb3" /> <label for="cb3"><img src="https://picsum.photos/seed/3/100" /></label> </li> <li><input type="checkbox" id="cb4" /> <label for="cb4"><img src="https://picsum.photos/seed/4/100" /></label> </li> </ul>