How to change an image on click using CSS alone?
I have an image and when the image is clicked I want to reveal another image below it. I am looking for a simple CSS only solution.
Is that possible?
TL;DR!
input[type="checkbox"] {
content: url('http://placekitten.com/200/210');
appearance: none;
display: block;
width: 200px;
height: 200px;
}
input[type="checkbox"]:checked {
content: url('http://placekitten.com/210/220');
}
<input type="checkbox" />
A Pure CSS Solution
Abstract
A checkbox input is a native element served to implement toggle functionality, we can use that to our benefit.
Utilize the :checked
pseudo class - attach it to a pseudo element of a checkbox (since you can't really affect the background of the input
itself), and change its background accordingly.
Implementation
input[type="checkbox"]:before {
content: url('images/icon.png');
display: block;
width: 100px;
height: 100px;
}
input[type="checkbox"]:checked:before {
content: url('images/another-icon.png');
}
Demo
Here's a full working demo on jsFiddle to illustrate the approach.
Refactoring
This is a bit cumbersome, and we could make some changes to clean up unnecessary stuff; as we're not really applying a background image, but instead setting the element's content
, we can omit the pseudo elements and set it directly on the checkbox.
Admittedly, they serve no real purpose here but to mask the native rendering of the checkbox. We could simply remove them, but that would result in a FOUC in best cases, or if we fail to fetch the image, it will simply show a huge checkbox.
Enters the appearance
property:
The
(-moz-)appearance
CSS property is used ... to display an element using a platform-native styling based on the operating system's theme.
we can override the platform-native styling by assigning appearance: none
and bypass that glitch altogether (we would have to account for vendor prefixes, naturally, and the prefix-free form is not supported anywhere, at the moment). The selectors are then simplified, and the code is more robust.
Implementation
input[type="checkbox"] {
content: url('images/black.cat');
display: block;
width: 200px;
height: 200px;
-webkit-appearance: none;
}
input[type="checkbox"]:checked {
content: url('images/white.cat');
}
Demo
Again, a live demo of the refactored version is on jsFiddle.
References
:checked
-moz-appearance
/-webkit-appearance
Note: this only works on webkit for now, I'm trying to have it fixed for gecko engines also. Will post the updated version once I do.
Update: the appearance
property is now widely adopted, so the use of vendor prefixes is redundant. Horay!
You could use an <a>
tag with different styles:
a:link { }
a:visited { }
a:hover { }
a:active { }
I'd recommend using that in conjunction with CSS sprites: https://css-tricks.com/css-sprites/
some people have suggested the "visited", but the visited links remain in the browsers cache, so the next time your user visits the page, the link will have the second image.. i dont know it that's the desired effect you want. Anyway you coul mix JS and CSS:
<style>
.off{
color:red;
}
.on{
color:green;
}
</style>
<a href="" class="off" onclick="this.className='on';return false;">Foo</a>
using the onclick event, you can change (or toggle maybe?) the class name of the element. In this example i change the text color but you could also change the background image.
Good Luck
This introduces a new paradigm to HTML/CSS, but using an <input readonly="true">
would allow you to append an input:focus
selector to then alter the background-image
This of course would require applying specific CSS to the input
itself to override browser defaults but it does go to show that click actions can indeed be triggered without the use of Javascript.