Download Demo

In this tutorial we’re going to be making an accordion slide out image slider thing with just CSS. We’ll also be looking at the alternative to the CSS :target pseudo class. You can click the demo button to check it out.

Target

You may be familiar with the :target pseudo element which allows you to click on an anchor and activate CSS for whatever element that anchor is targeting. This is really useful, but has the downside of scrolling down to that element, which then has to be overrode with some Javascript.

The alternative isn’t particular semantic, and I can already hear people slamming this tutorial from miles away. However it’s perhaps the only way to accomplish this without using Javascript, assuming you don’t want the page to jump. As an example of how the current method works, lets take a look at this code.

<a href="#image-1">Click me!</a>
<div id="image-1">
   Some text or an image here.
</div>

The anchor here is targeting the div #image-1. We can then tell the CSS to do something when the div in question is targeted, i.e. when the user clicks on the link.

#image-1:target {
  /* Style #image-1 here */
}

The problem now is that the page will jump to this element, which can be bothersome if you want to maintain a unified experience.

The Alternative

The alternative is forms. When you create an input, button or anything form related you can add a :focus (or :checked) pseudo class which will activate when the user clicks on the form. We can style a form element in such a way that it will appear as though it isn’t a form element. That’s what we’re going to be doing in this article. Specifically, we’re going to be using :checked. Lets jump right in.

Compatibility

Percent of people who can see this
For The Full Demo 55.93%
Minus Transitions 70.58%

So in the newest version of each browser, this will work great, but in older versions of IE, because of lack of support for transitions, about 56% of people will be able to view this as it’s supposed to be viewed. You could do something like this to get transitions to work.

After transitions the next obstacle is 2D Transforms. These aren’t supported in IE8 or below. You could fix this by doing something like this.

Structure

The structure is pretty simple. We have a few divs filled with a label, a radio button and the content to display. This is all contained in another div, just so we don’t get the CSS for this mixed up with other form CSS.

<div id="image-expand">
	<div>
		<label for="button-1"><span>Some Title</span></label>
		<input id="button-1" name="button-set" type="radio" />
		<div class="content">
			<img src="1.jpeg" alt="" />
			<a class="read-more" href="/">Read More</a>
		</div>
	</div>
	<div>
		<label for="button-2"><span>Another!</span></label>
		<input id="button-2" name="button-set" type="radio" checked />
		<div class="content">
			<img src="2.jpeg" alt="" />
			<a class="read-more" href="/">Read More</a>
		</div>
	</div>
	<div>
		<label for="button-3"><span>News</span></label>
		<input id="button-3" name="button-set" type="radio" />
		<div class="content">
			<img src="3.jpeg" alt="" />
			<a class="read-more" href="/">Read More</a>
		</div>
	</div>
	<div>
		<label for="button-4"><span>Tutorials</span></label>
		<input id="button-4" name="button-set" type="radio" />
		<div class="content">
			<img src="4.jpeg" alt="" />
			<a class="read-more" href="/">Read More</a>
		</div>
	</div>
</div>

CSS

The CSS, of course, is what makes this all work. Lets style some of the main elements first:


#image-expand div {
	float: left;
	position: relative;
}

#image-expand div .content {
	position: absolute;
	top: 0;
	left: 0;
	width: 100px;
	height: 200px;
	box-shadow: 0px 0px 10px rgba(0,0,0,0.1);
	overflow: hidden;
	z-index: 500;
} 

#image-expand div label {
	width: 100px;
	height: 200px;
	display: block;
	background: #f6f6f6;
	box-shadow: inset -25px 0px 30px -10px rgba(0,0,0,0.05);
	cursor: pointer;
	border-right: 1px solid #ddd;
	color: #222;
	overflow: hidden;
	position: relative;
	z-index: 1000; /* So its above everything */
}

#image-expand div label span {
	width: 140px;
	display: block;
	position: relative;
	top: 70px;
	font-family: 'Myriad Pro', Arial, sans-serif;
	font-size: 26px;
	text-transform: uppercase;
	font-weight: bold;
	-webkit-transform: rotate(90deg);
	-moz-transform: rotate(90deg);
	-ms-transform: rotate(90deg);
	-o-transform: rotate(90deg);

}
#image-expand input[type=radio] {
	opacity: 0; /* Make the radio button invisible. */	
}

.content .read-more {
	position: absolute;
	bottom: 30px;
	right: 40px;
	text-decoration: none;
	padding: 10px 20px;
	font-family: Arial, sans-serif;
	text-transform: uppercase;
	box-shadow:  0px 4px 6px #132732, 0px 4px 0px #1d3846, inset 0px 15px 30px -10px rgba(255,255,255,0.2);
	background: #4e96ba;
	border-radius: 4px;
	font-weight: bold;
	color: #fff;
}

.content .read-more:active {
	box-shadow: 0px 2px 0px #1d3846, inset 0px 15px 30px -10px rgba(255,255,255,0.2);	
	bottom: 28px;
}

#image-expand .content, #image-expand label, #image-expand input { /* Transitions for fluidity */
	-webkit-transition: all 0.1s ease-in;
	-moz-transition: all 0.1s ease-in;
	-o-transition: all 0.1s ease-in;
	-ms-transition: all 0.1s ease-in;
}

This is a pretty basic setup, just some styling and positioning of things. The next bit might be new. We have to alter the CSS depending on what button is ‘checked’. I’ve added some comments to the CSS should you get confused.


#image-expand label:hover ~ input:checked + .content {
	width: 500px; /* When the user hovers on a checked item, override any CSS */
}

#image-expand label:hover ~ .content {
	width: 111px; /* The width of the content is increased when the user hovers */
}

#image-expand label:hover {
	margin-right: 10px; /* On hover expand a little bit, just to hint that the user can interact */
}

#image-expand input:checked {
	margin-right: 580px; /* When something is checked, ensure it's the full width by expanding the input */
}

And that’s it. Put it all together and you’ll have a functioning accordion style image slider thing! Click the demo or download button below if you want to do either (obviously). Also, don’t forget to have a good day!