21

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?

5
  • no. click is an event and CSS can't help you with this. you can change the image on hover. Commented Jul 25, 2011 at 9:01
  • 1
    Do you want to reveal the image while it is clicked, or toggle the image every time it is clicked? Commented Jul 25, 2011 at 9:31
  • check out my suggested solution, i think you'll like it. Commented Jul 24, 2013 at 20:54
  • Im not sure this 4 year old post will get ressurected. But how do you reveal when an image only on mouseover? Commented Nov 1, 2015 at 5:31
  • 1
    @Sidhartha - You could do something like img:hover { background: url(/path-to-image/img.jpg); } or use sprites as noted in the answer below. You can read more about hover here, here, and here Commented Nov 2, 2015 at 1:10

7 Answers 7

23

TL;DR!

input[type="checkbox"] {
    content: url('http://placekitten.com/150/160');
    appearance: none;
    display: block;
    width: 150px;
    height: 150px;
}

input[type="checkbox"]:checked {
    content: url('http://placekitten.com/170/180');
}
<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

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!

Sign up to request clarification or add additional context in comments.

5 Comments

The CSS Ninja uses a similar approach for his Futurebox. That is a lightbox in CSS. +1 for the input idea.
thanks, @feeela, and pleased to meet, CSS Ninja (wow, he has really taken this to the next level, great stuff. did you see the bootstrap plugins?).
Quite easy to make cross browser when you use a label for the input: jsfiddle.net/01cwd1wq
The fact that the first part of the answer works on webkit related browsers is only a non-standard deviation. An input cannot have a after or before pseudo since it's not an element with a closing tag, needed to contain said pseudo element. So it's basically incorrect.
To remove the "Submit Query" flashing text: • HTML: <span id="checkbox-image"><input type="checkbox"></span> • CSS: #checkbox-image:checked {…}. I.e., no need for the [type="checkbox"] in the CSS.
11

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/

2 Comments

Thanks, that seems to be the best way for using a CSS only solution.
this doesn't allow for toggling a state (how to change the image back on an additional click?), as visited will persist until the browser cache is cleaned.
5

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

1 Comment

the OP has requested a CSS only solution.
4

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.

6 Comments

huh? please demonstrate.
Sure... So take a look at this page: daleyjem.com/sandbox/css-playground.html ... Don't mind the clock, but the 4th menu item is actually an <input/>
interesting, though it still poses some issues, e.g. what about keyboard navigation? this won't look too hot as in some engine implementations text is highlighted on keyboard focus to an input.
True. You could also use the method used on the actual <a> tags, which is... set the a:target {} selector in css, and make sure your href (minus the hash tag) matches the id of the <a> tag.
The url above is dead. Try this instead for an example: codepen.io/daleyjem/pen/PLBZXO
|
4

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);
}

Comments

2

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

Comments

1

No, you will need scripting to place a click Event handler on the Element that does what you want.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.