Visibility upon hover

I’m attempting to make elements appear when I hover on an anchor. Nothing I try works. Below is a simple example of a failure. (The example uses an h1 for simplicity, though I would like to do the same with an img. A side issue: I’ve been managing anchor colors for ages, and that’s not working in this case either. I don’t know why.)

<!DOCTYPE html>
<html>

<head>
<style>
a.jones:hover {color:#ff0000;}
a.brown:hover {color:#00ff00;}
h1.hiddenj {visibility:hidden;}
h1.hiddenj:hover a.jones {visibility:visible;}
h1.hiddenb {visibility:hidden;}
h1.hiddenb:hover a.brown {visibility:visible;}
</style>
</head>

<body>
<h1>Smith: I am seen</h1>
<h1 class=“hiddenj”>Jones: I want to be seen.</h1>
<h1 class=“hiddenb”>Brown: I want to be seen.</h1>
<p>Make Jones <a class=“jones” href=“#”>appear</a>.</p>
<p>Make Brown <a class=“brown” href=“#”>appear</a>.</p>
</body>
</html>

Where am I going wrong?

It looks like this could be easily solved with a good application of CSS, so I’ve moved this thread to the CSS forum.

It could also be done using JavaScript, but type of solution is less likely to be as flexible as CSS.

Firstly, you can’t really hover over something that’s hidden.

Secondly, a rule like this—

h1.hiddenj:hover a.jones {visibility:visible;}

—assumes that .jones is a descendant of .hiddenj (that is, nested inside it, rather than following it in the HTML). To keep that kind of structure, you’d need JS to do something like this.

Thank you, Ralph, for the hint that got me off the wrong track. I am a 60-year-old editor with design responsibilities, but hardly a designer. I am intrigued by HTML/CSS to the point that I prefer to code it directly. I want to understand it better. At this point my understanding of parent/descendant is vague but improving. But I digress. After your nudge, I tried an entirely different approach, and got what I was after:

<!DOCTYPE html>
<html>
<head>
<style>
a.re:hover {color:#cc0000;}
a.br:hover {color:#661111;}
li {list-style:none; float:left; padding-left:0}
ul {margin-top:4em;}
ul.david {
left: -9999em;
position: absolute;
list-style: none;
}
li.jim:hover ul {
left: 0.35em; top: -4.5em;
}

</style>
</head>

<body>
<ul>
<li class=“jim”>Where is <a href=“#” class=“re”>Red</a>?
<ul class=“david”><li><h1>Red: Here I am.</h1></li></ul></li>

<li class=“jim”> Where is <a href=“#” class=“br”>Brown</a>?
<ul class=“david”><li><h1>Brown: Here I am.</h1></li></ul>
</li>
</ul>

</body>
</html>

Visibility is dispensed with, and this builds on an example of how a drop-down menu can be created in pure HTML/CSS. My hope is that I can now do with an “img” what this example does with “h1.” But oh dear! Long ago, I laid out newspaper pages on paper grids, so I naturally took to using tables as a layout technique. I am a reformed table abuser. . . . But now will I be accused of abusing lists? . . . All the best, and thanks again for your post.

Hi,

If you are just showing an image then there’s no need for the full dropdopwn nested list approach and you could do it more simply like this:


<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<style>
.imgshow {
	position:relative;
	margin:0 0 1em;
	padding:160px 0 0;
}
.imgshow a img {
	left:-999em;
	position:absolute;
	top:0;
}
.imgshow a:hover img {left:0}
</style>
</head>

<body>
<p class="imgshow"><a href="#">Show image 1 <img src="http://placehold.it/150x150" alt="placeholder"></a> or <a href="#">Show image 2 <img src="http://placehold.it/350x150"  alt="placeholder"></a></p>
</body>
</html>

Of course it depends on what happens next and if there is more to this than just displaying an image:)

Thank you, Paul. I’m looking at your concise code with interest–it is a major step toward what I want to do. But so far, I haven’t been able to translate it to the page I’m working on. Though I have built entire corporate sites (including a current one, which I coded in HTLM/CSS sans text editor), there are layers I haven’t mastered. One is building selectors beyond simple ones. For example, I don’t understand what is wrong with the selectors in the snippet from my May 27 post. Also, I’m not sure I understand the meaning of “relative” as in “position:relative;”. I’m working with Castro and Hyslop, HTML5 and CSS3 (7th) and http://www.w3schools.com/ but it’s slow going.

Perhaps if you can give us an idea of what you’re ultimately wanting to achieve, we can help you to get there.

Ralph mentioned a couple of problems with the code but if we take this rule for example:


h1.hiddenj:hover a.jones {visibility:visible;}

For the above snippet to work a.jones would need to be a descendant of the h1. Remember the rightmost selector is the one that gets targeted so you are saying that when the h1 is hovered reveal the element called a.jones. This would require html that looks like this:


<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<style>
h1 a {visibility:hidden}
h1.hiddenj:hover a.jones {visibility:visible}
</style>
</head>

<body>
<h1 class="hiddenj">Reveal <a class="jones" href="#">Jones</a></h1>
</body>
</html>

(which is much like the example I gave you previously)

It seems to me that you were trying to hover an element (like a.jones) and then affect an element higher up the DOM (your H1). (BTW there should really only be one h1 per page in most cases as there is only one main heading to a page).

CSS does not work upwards and can only work on descendent elements or following adjacent or following sibling elements. You can never affect the parent by hovering the child or anything further down the tree.

For your code to work it would have needed to be like this:


<!DOCTYPE html>
<html>

<head>
<style>
.jones:hover span {color:#ff0000;}
.brown:hover span {color:#00ff00;}
h1.hiddenj {display:none}
h1.hiddenb {display:none}
.jones:hover ~ .hiddenj{display:block}
.brown:hover ~ .hiddenb{display:block}


</style>
</head>

<body>
<h1>Smith: I am seen</h1>
<p class="jones">Make Jones <span>appear</span>.</p>
<p class="brown">Make Brown <span>appear</span>.</p>
<h1 class="hiddenj">Jones: I want to be seen.</h1>
<h1 class="hiddenb">Brown: I want to be seen.</h1>
</body>
</html>


The trigger comes first and then you could affect elements later in the structure. Of course this means that the element appears below the trigger so if you wanted it above (visually) you would need to absolutely position it into place which would mean that for in-flow elements it would be a problem as you can’t account for a variable height with absolute positioning (but in the case of a fixed height image as in my example it would be ok)

Also, I’m not sure I understand the meaning of “relative” as in “position:relative;”

When you use position:relative (without co-ordinates) its purpose its to act as a positioning context for any absolutely placed children. Without position:relative on an ancestor of an absolute element the absolute element is placed in relation to the viewport and not the element it sits in. Adding position:relative to an element means that any absolute children will base their co-ordinates on the position of this parent. If the parent was a centred element then the absolute elements co-ordinates start for the top left of this element and not the viewport.

When you use co-ordinates on a position:relative element then that element is moved in relation to itself. If you say left:10px then the element is moved by 10px from where it would have been in the flow of the document. However the element is only moved visually and the element always occupies its original space in the flow of the document although it may appear to be somewhere else. The space is always preserved as though the element had never moved. This means that the element may now overlap other elements because as far as they are concerned the element is still in its original position.