2015-03-24:
CSS-Only onClick to Popup Div (no Javascript or HTML changes!)

Abstract | The Solution | An Example | Bugs/Errata


Abstract

Sometimes CSS-only solutions are because developers hate javascript. I can understand that. But sometimes it's because there is a separation from the content, the scripting and the layout. As an example, I have a project that uses CSS to create different themes. That means that if I want to use one div to popup another div I have to do it via CSS. Creating a hovering popup is easy with :hover, but creating a click popup is a different story.

I couldn't use the many lovely :target solutions, because they require that the popup has a unique 'id', and again, I can't change the content/HTML.

Simply put, I have multiple divs that contain other divs, and I want to be able to click on the first div to bring up it's inner div, and it needs to be done only in CSS, without adding javascript or changing the basic structure:

<div class="outer">
	Click here for more info
	<div class="inner">
		More info!
	</div>
</div>

The Solution

We can use :active as a selector for when an object is clicked, and then use that to change the inner div's visibility. This is only while the div is clicked, so we add visibility to the inner div when we hover over it, so it ends up keeping itself alive.

As extra credit, we want to be able to click on the inner div to make it go away. Unfortunately we can't use :active to just change the visibility because as soon as it disappears then it reappears because it's also controlled by the :active of the outer div (at least that's what seems to happen on Chrome on Ubuntu).

So instead we hide it with a different tactic, by setting the width/height to 0. This only works if we aren't then clicking on the outer div below, which is generally functional if the popup is big enough.

On some browsers you can see the info shrink away into the zero sized div, and unfortunately some will catch the mouse click on it and re-raise the div. We fix this by changing the position as well.

An Example

Here's the code (outer/parent div is clsas 'clickToShowInfo' and inner div is class 'info'):
	/* Outer div - needs to be relative so we can use absolute positioning */
	.clickToShowInfo {
		position: relative;
	}
	/* When clicking outer div, make inner div visible */
	.clickToShowInfo:active .info { display: block; }
	/* And hold by staying visible on hover */
	.info:hover {
		display: block;
	}
	/* General settings for popup */
	.info {
		position: absolute;
		top: -5;
		display: none;
		z-index: 100;
		background-color: white;
		box-shadow: 5px 5px 2px #aaa;
		border: 1px solid grey;
		padding: 8px;
		width: 200px;
		height: 200px;
	}
	/* If we want clicking on the popup to close, use this */
	.info:active {
		display: none;	/* Doesn't work because DCEvent is :active as well */
		height: 0px;
		width: 0px;
		left: -1000px;
		top: -1000px;
	}
Here's the example in action (with the ability to click on the popup to make it disappear):

Click here to show info
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit.

Bugs/Errata

This only works if your popup is popping over the parent div.

Currently if you click to close the info div but you are clicking on a portion that contains the parent div, then that is re-activated and the info div is displayed again. It would be great if we could temporarily remove the rule that causes the display in the first place, something like:

 .info:active .clickToShowInfo:active .info {  }
But that doesn't seem to quite work.


Back to Solutions.

DaveSource.com - Dave's geek site GetDave.com - all the current Dave Pointers. MarginalHacks - I have an elegant script for that, but it's too small to fit in the margin.