I have an image element that I want to change on click.

<img id="btnLeft">

This works.

#btnLeft:hover {
    width:70px;
    height:74px;
}

But what I need is.

#btnLeft:onclick {
    width:70px;
    height:74px;
}

It doesn't work Is it possible at all to have onclick behavior in CSS (i.e. without using JavaScript)?

Best Answer


Answer as of 2020:

The best way (actually the only way*) to simulate an actual click event using only CSS (rather than just hovering on an element or making an element active, where you don't have mouseUp ) is to use the checkbox hack. It works by attaching a label to an <input type="checkbox"> element via the label's for="" attribute.

This feature has broad browser support (the :checked pseudo-class is IE9+).

Apply the same value to an <input> 's ID attribute and an accompanying <label> 's for="" attribute, and you can tell the browser to re-style the label on click with the :checked pseudo-class, thanks to the fact that clicking a label will check and uncheck the "associated" <input type="checkbox"> .

* You can simulate a "selected" event via the :active or :focus pseudo-class in IE7+ (e.g. for a button that's normally 50px wide, you can change its width while active : #btnControl:active { width: 75px; } ), but those are not true "click" events. They are "live" the entire time the element is selected (such as by Tab bing with your keyboard), which is a little different from a true click event, which fires an action on - typically - mouseUp .


Basic demo of the checkbox hack (the basic code structure for what you're asking):

label {
    display: block;
    background: lightgrey;
    width: 100px;
    height: 100px;
}

#demo:checked + label {
    background: blue;
    color: white;
}
<input type="checkbox" id="demo"/>
<label for="demo">I'm a square. Click me.</label>

Here i've positioned the label right after the input in my markup. This is so that I can use the adjacent sibling selector (the + key) to select only the label that immediately follows my #demo checkbox. Since the :checked pseudo-class applies to the checkbox, #demo:checked + label will only apply when the checkbox is checked.

Demo for re-sizing an image on click, which is what you're asking:

#btnControl {
    display: none;
}

#btnControl:checked + label > img {
    width: 70px;
    height: 74px;
}
<input type="checkbox" id="btnControl"/>
<label class="btn" for="btnControl"><img src="https://placekitten.com/200/140" id="btnLeft" /></label>

With that being said, there is some bad news. Because a label can only be associated with one form control at a time, that means you can't just drop a button inside the <label></label> tags and call it a day. However, we can use some CSS to make the label look and behave fairly close to how an HTML button looks and behaves.

Demo for imitating a button click effect, above and beyond what you're asking:

#btnControl {
    display: none;
}

.btn {
    width: 60px;
    height: 20px;
    background: silver;
    border-radius: 5px;
    padding: 1px 3px;
    box-shadow: 1px 1px 1px #000;
    display: block;
    text-align: center;
    background-image: linear-gradient(to bottom, #f4f5f5, #dfdddd);
    font-family: arial;
    font-size: 12px;
    line-height:20px;
}

.btn:hover {
    background-image: linear-gradient(to bottom, #c3e3fa, #a5defb);
}


.btn:active {
    margin-left: 1px 1px 0;
    box-shadow: -1px -1px 1px #000;
    outline: 1px solid black;
    -moz-outline-radius: 5px;
    background-image: linear-gradient(to top, #f4f5f5, #dfdddd);
}

#btnControl:checked + label {
    width: 70px;
    height: 74px;
    line-height: 74px;
}
<input type="checkbox" id="btnControl"/>
<label class="btn" for="btnControl">Click me!</label>

Most of the CSS in this demo is just for styling the label element. If you don't actually need a button , and any old element will suffice, then you can remove almost all of the styles in this demo, similar to my second demo above.

You'll also notice I have one prefixed property in there, -moz-outline-radius . Mozilla added this cool non-spec property to firefox a while back but webkit folks decided they're not going to add it unfortunately So consider that line of CSS just a progressive enhancement for people who use Firefox.