Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change an image on click using CSS alone?

Tags:

html

css

image

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?

like image 799
L84 Avatar asked Jul 25 '11 08:07

L84


6 Answers

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!

like image 83
Eliran Malka Avatar answered Oct 09 '22 02:10

Eliran Malka


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/

like image 39
evilpenguin Avatar answered Oct 09 '22 03:10

evilpenguin


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

like image 28
pleasedontbelong Avatar answered Oct 09 '22 04:10

pleasedontbelong


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.

like image 37
daleyjem Avatar answered Oct 09 '22 04:10

daleyjem


Try this (but once clicked, it is not reversible):

HTML:

<a id="test"><img src="normal-image.png"/></a>

CSS:

a#test {
    border: 0;
}
a#test:visited img, a#test:active img {
    background-image: url(clicked-image.png);
}
like image 37
nfechner Avatar answered Oct 09 '22 04:10

nfechner


You can use the different states of the link for different images example

You can also use the same image (css sprite) which combines all the different states and then just play with the padding and position to show only the one you want to display.

Another option would be using javascript to replace the image, that would give you more flexibility

like image 40
jasalguero Avatar answered Oct 09 '22 03:10

jasalguero