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="clickToShowInfo">
Click here for more info
<div class="info">
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 class '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 { visibility: visible; }
/* And hold by staying visible on hover */
.info:hover {
visibility: visible;
}
/* General settings for popup */
.info {
position: absolute;
top: -5;
visibility: hidden;
z-index: 100;
background-color: white;
box-shadow: 5px 5px 2px #aaa;
border: 1px solid grey;
padding: 8px;
width: 220px;
height: 200px;
}
/* If we want clicking on the popup to close, use this */
.info:active {
visibility: hidden; /* 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.
And what's particularly lovely is that you don't need unique names
to create multiple popups. Here's another example:
Another example
This is the same html code, with different content. Just
another example of:
<div class="clickToShowInfo">
Another Example
<div class="info">
This is the same html code
....
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.
It also doesn't seem to work on Safari. I would love a fix or reason.
Back to Solutions.