334

I would like to show a div when someone hovers over an <a> element, but I would like to do this in CSS and not JavaScript. Do you know how this can be achieved?

peak
  • 72,551
  • 14
  • 101
  • 128
tetris
  • 3,954
  • 5
  • 25
  • 39
  • 1
    the div would have to be inside the a tag.. – amosrivera Mar 06 '11 at 10:53
  • please see http://stackoverflow.com/questions/3847568/css-pseudoclasshover-not-working when you find that this technique seems 'broken' – d-_-b Sep 09 '12 at 03:49
  • 2
    remember that :hover will not work the same way on touch-screens, and in these days it should used with caution (e.g. avoid using to display additional navigation elements) – Paweł Bulwan Jul 30 '13 at 13:38
  • @Pawel Bulwan I combined the ":hover" with "+" CSS selector suggestions from here with a :target suggestion for showing content on click (from https://stackoverflow.com/questions/18849520/css-show-hide-content-with-anchor-name) into a solution that should work with both mouse and touch - https://zoomicon.wordpress.com/2017/11/25/howto-show-block-on-anchor-hover-and-click-to-keep-open-with-css/ – George Birbilis Nov 24 '17 at 22:13
  • following up on my last comment, also see some useful variations at a comment reply I did on that blog post: https://zoomicon.wordpress.com/2017/11/25/howto-show-block-on-anchor-hover-and-click-to-keep-open-with-css/#comment-17356 – George Birbilis Jan 29 '20 at 17:40

14 Answers14

564

You can do something like this:

div {
    display: none;
}
    
a:hover + div {
    display: block;
}
<a>Hover over me!</a>
<div>Stuff shown on hover</div>

This uses the adjacent sibling selector, and is the basis of the suckerfish dropdown menu.

HTML5 allows anchor elements to wrap almost anything, so in that case the div element can be made a child of the anchor. Otherwise the principle is the same - use the :hover pseudo-class to change the display property of another element.

nathanjosiah
  • 4,253
  • 4
  • 33
  • 46
Yi Jiang
  • 46,385
  • 16
  • 133
  • 131
  • 14
    nice solution, even if you put div:hover {display: block;} then div will not hided when you hover div itself.. – Alper Nov 14 '11 at 18:35
  • 26
    This will make every `
    ` on the page `display:none` and when the mouse hovers over "Hover over me!" it will make every `
    – Nate Jun 06 '12 at 22:59
  • 12
    add div:hover { display:block; } to keep it out while their mouse is over it – monkeyhouse May 28 '13 at 01:27
  • It might be prudent to use visibility instead of display. As I recall, it's more efficient because display redraws the div every time. Although it probably doesn't matter for one div, if you have to do many, it might be better to make them invisible instead. – Prinsig Dec 18 '14 at 23:01
  • @Yi Jiang - how did you added this code to the answer? – Zameer Ansari Apr 27 '15 at 17:20
  • how to do when a div is not a child or next div. – Aabid Jun 10 '15 at 12:10
  • @Prinsig : Actually `visibility` seems to behave quite poorly in some cases. In particular, if you have several divs with hidden content, and this content contains images, when you hover one div then another the newly displayed div may appear quicker than the images of the previous div would disappear, while other solutions like `display` or `opacity` switch almost instantaneously (tested on several browsers). – Skippy le Grand Gourou Aug 08 '15 at 14:01
  • @Prinsig : Also, use cases are different : `visibility: hidden` will keep blank room for the hidden content (like `opacity: 0`), while `display: none` will remove it from the flow. – Skippy le Grand Gourou Aug 08 '15 at 14:04
  • thanks, combined this solution with :target for activating it with clicks on the anchor too (for touch-only clients), see https://jsfiddle.net/birbilis/23nt74se/ - also used @user1778606's comment from above to keep the item open when mouse hovers over it (having left the anchor above it - useful to select and copy content from the item) – George Birbilis Nov 24 '17 at 22:16
  • btw, one can opt to use "inline-block" too instead of "block" if they prefer its behavior (in newer browsers though - https://www.w3schools.com/css/css_inline-block.asp) – George Birbilis Nov 24 '17 at 22:22
  • I ended up using yet another variation of the jsfiddle I commented about above with simpler syntax, where the anchor and help text is placed inside a parent div that has text for the item the help is about and that div is marked with class “question”. See https://jsfiddle.net/birbilis/s3kaknt9/ – George Birbilis Nov 30 '17 at 20:57
  • ...since the parent question (using it at Trafilm Gallery Metadata forms at http://gallery.trafilm.net/metadata, the anchors are those special icons after a question's greyish comment) DIVs already had an ID, this variation had the benefit that I didn't need to add an ID to the anchor, just an href, plus when clicked it scrolls to the parent item (the question) instead of to the help item that is at the bottom of it which would put the question text out of the view when the help link is clicked, if the question is far enough down the page for it to scroll when targetted by the openhelp anchor. – George Birbilis Nov 30 '17 at 20:59
  • Works Great as expected. Thank you. – invinciblemuffi Oct 28 '20 at 03:56
272

.showme {
  display: none;
}

.showhim:hover .showme {
  display: block;
}
<div class="showhim">HOVER ME
  <div class="showme">hai</div>
</div>

jsfiddle

Since this answer is popular I think a small explanation is needed. Using this method when you hover on the internal element, it wont disappear. Because the .showme is inside .showhim it will not disappear when you move your mouse between the two lines of text (or whatever it is).

These are example of quirqs you need to take care of when implementing such behavior.

It all depends what you need this for. This method is better for a menu style scenario, while Yi Jiang's is better for tooltips.

Nick Parsons
  • 31,322
  • 6
  • 25
  • 44
n00b
  • 5,114
  • 1
  • 25
  • 45
  • You can't have block element inside inline element, unless you are using HTML 5. – methyl Mar 06 '11 at 11:00
  • 3
    HTML5 its not a standard yet, so Yi Jiang's method is better. – methyl Mar 06 '11 at 11:05
  • 5
    i know its better, thats why i upvoted it :) i gave a working example, presenting a concept (css selectors more specifically), dont see why downvote it ^^ – n00b Mar 06 '11 at 11:07
  • This might be better to use ``s, but I think this is a better example than Yi Jiang's. – Nate Jun 06 '12 at 23:02
40

I found using opacity is better, it allows you to add css3 transitions to make a nice finished hover effect. The transitions will just be dropped by older IE browsers, so it degrades gracefully to.

#stuff {
    opacity: 0.0;
    -webkit-transition: all 500ms ease-in-out;
    -moz-transition: all 500ms ease-in-out;
    -ms-transition: all 500ms ease-in-out;
    -o-transition: all 500ms ease-in-out;
    transition: all 500ms ease-in-out;
}
#hover {
    width:80px;
    height:20px;
    background-color:green;
    margin-bottom:15px;
}
#hover:hover + #stuff {
    opacity: 1.0;
}
<div id="hover">Hover</div>
<div id="stuff">stuff</div>
nathanjosiah
  • 4,253
  • 4
  • 33
  • 46
Timothy
  • 1,008
  • 1
  • 14
  • 28
  • 6
    This is great, I used this for a much larger div. I wanted the "stuff" div to remain visible if I moved my cursor from the "hover" div to the "stuff" div so I changed the last style element from `#hover:hover + #stuff {` to `#hover:hover + #stuff, #stuff:hover {`. Then the "stuff" div remains visible when you move over that div! – NotJay Oct 07 '15 at 16:03
29

I'm by know means an expert, but I'm incredibly proud of myself for having worked something out about this code. If you do:

div {
    display: none;
}

a:hover > div {
    display: block;
} 

(Note the '>') You can contain the whole thing in an a tag, then, as long as your trigger (which can be in it's own div, or straight up in the a tag, or anything you want) is physically touching the revealed div, you can move your mouse from one to the other.

Maybe this isn't useful for a great deal, but I had to set my revealed div to overflow: auto, so sometimes it had scroll bars, which couldn't be used as soon as you move away from the div.

In fact, after finally working out how to make the revealed div, (although it is now a child of the trigger, not a sibling), sit behind the trigger, in terms of z-index, (with a little help from this page: How to get a parent element to appear above child) you don't even have to roll over the revealed div to scroll it, just stay hovering over the trigger and use your wheel, or whatever.

My revealed div covers most of the page, so this technique makes it a lot more permanent, rather than the screen flashing from one state to another with every move of the mouse. It's really intuitive actually, hence why I'm really quite proud of myself.

The only downside is that you can't put links within the whole thing, but you can use the whole thing as one big link.

Community
  • 1
  • 1
Edd Tillen
  • 345
  • 3
  • 2
20

This answer doesn't require that you know the what type of display (inline, etc.) the hideable element is supposed to be when being shown:

.hoverable:not(:hover) + .show-on-hover {
    display: none;
}
<a class="hoverable">Hover over me!</a>
<div class="show-on-hover">I'm a block element.</div>

<hr />

<a class="hoverable">Hover over me also!</a>
<span class="show-on-hover">I'm an inline element.</span>

This uses the adjacent sibling selector and the not selector.

nascosto
  • 371
  • 2
  • 10
14

I would like to offer this general purpose template solution that expands on the correct solution provided by Yi Jiang's.

The additional benefits include:

  • support for hovering over any element type, or multiple elements;
  • the popup can be any element type or set of elements, including objects;
  • self-documenting code;
  • ensures the pop-up appears over the other elements;
  • a sound basis to follow if you are generating html code from a database.

In the html you place the following structure:

<div class="information_popup_container">
<div class="information">
<!-- The thing or things you want to hover over go here such as images, tables, 
     paragraphs, objects other divisions etc. --> 
</div>
<div class="popup_information">
<!-- The thing or things you want to popup go here such as images, tables, 
     paragraphs, objects other divisions etc. --> 
</div>
</div>

In the css you place the following structure:

div.information_popup_container {
position: absolute;
width:0px;
height:0px;
/* Position Information */
/* Appearance Information */
}
div.information_popup_container > div.information {
/* Position Information */
/* Appearance Information */
}
div.information_popup_container > div.popup_information {
position: fixed;
visibility: hidden;
/* Position Information */
/* Appearance Information */
}
div.information_popup_container > div.information:hover + div.popup_information {
visibility: visible;
z-index: 200;
}

A few points to note are:

  1. Because the position of the div.popup is set to fixed (would also work with absolute) the content is not inside the normal flow of the document which allows the visible attribute to work well.
  2. z-index is set to ensure that the div.popup appears above the other page elements.
  3. The information_popup_container is set to a small size and thus cannot be hovered over.
  4. This code only supports hovering over the div.information element. To support hovering over both the div.information and div.popup then see Hover Over The Popup below.
  5. It has been tested and works as expected in Opera 12.16 Internet Explorer 10.0.9200, Firefox 18.0 and Google Chrome 28.0.15.

Hover Over The Popup

As additional information. When the popup contains information that you might want to cut and paste or contains an object that you might want to interact with then first replace:

div.information_popup_container > div.information:hover + div.popup_information {
visibility: visible;
z-index: 200;
}

with

div.information_popup_container > div.information:hover + div.popup_information 
,div.information_popup_container > div.popup_information:hover {
visibility: visible;
z-index: 200;
}

And second, adjust the position of div.popup so that there is an overlap with div.information. A few pixels is sufficient to ensure that the div.popup is can receive the hover when moving the cusor off div.information.

This does not work as expected with Internet Explorer 10.0.9200 and does work as expected with Opera 12.16, Firefox 18.0 and Google Chrome 28.0.15.

See fiddle http://jsfiddle.net/F68Le/ for a complete example with a popup multilevel menu.

rbell01824
  • 179
  • 4
  • 10
Tai Paul
  • 779
  • 8
  • 19
7

The + allow 'select' only first not nested element , the > select nested elements only - the better is to use ~ which allow to select arbitrary element which is child of parent hovered element. Using opacity/width and transition you can provide smooth appear

div { transition: all 1s }
.ccc, .ggg { opacity: 0; color: red}
.ccc { height: 0 }

.aaa:hover ~ .bbb .ccc { opacity: 1; height: 34px }
.aaa:hover ~ .eee .fff .ggg { opacity: 1 }
<div class="aaa">Hover me... to see<br><br> </div>

<div class='bbb'>BBBBB
  <div class='ccc'>CCCCC
    <div class='ddd'>DDDDD</div>
  </div>
</div>

<div class='eee'>EEEEE
  <div class='fff'>FFFFF
    <div class='ggg'>GGGGG</div>
    <div class='hhh'>HHHHH</div>
  </div>
</div>
Kamil Kiełczewski
  • 53,729
  • 20
  • 259
  • 241
4

please test this code

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>

<style type="text/css"> 
div
{
display:none;
color:black
width:100px;
height:100px;
background:white;
animation:myfirst 9s;
-moz-animation:myfirst 9s; /* Firefox */
-webkit-animation:myfirst 5s; /* Safari and Chrome */  

}

@keyframes myfirst
{
0%   {background:blue;}
25%  {background:yellow;}
50%  {background:blue;}
100% {background:green;}
}

 @-moz-keyframes myfirst /* Firefox */
{
0%   {background:white;}
50%  {background:blue;}
100% {background:green;}
}

@-webkit-keyframes myfirst /* Safari and Chrome */
{
  0%   {background:red;}
  25%  {background:yellow;}
  50%  {background:blue;}
  100% {background:green;}
}

a:hover + div{
display:inline;
} 
</style>
</head>
<body>
<a href="#">Hover over me!</a>
<div>the color is changing now</div>
<div></div>
</body>
</html>
Mehdi Raash
  • 6,893
  • 1
  • 26
  • 40
2

For me, if I want to interact with the hidden div without seeing it disappear each time I leave the triggering element (a in that case) I must add:

div:hover {
    display: block;
}
Leo the lion
  • 3,213
  • 2
  • 19
  • 39
hachpai
  • 186
  • 12
0

Based on the main answer, this is an example, useful to display an information tooltip when clicking on a ? near a link:

document.onclick = function() { document.getElementById("tooltip").style.display = 'none'; };

document.getElementById("tooltip").onclick = function(e) { e.stopPropagation(); }

document.getElementById("help").onclick = function(e) { document.getElementById("tooltip").style.display = 'block';
e.stopPropagation(); };
#help { opacity: 0; margin-left: 0.1em; padding: 0.4em; }
    
a:hover + #help, #help:hover { opacity: 0.5; cursor: pointer; }

#tooltip { border: 1px solid black; display: none; padding: 0.75em; width: 50%; text-align: center; font-family: sans-serif; font-size:0.8em; }
<a href="">Delete all obsolete informations</a><span id="help">?</span>
<div id="tooltip">All data older than 2 weeks will be deleted.</div>
Basj
  • 29,668
  • 65
  • 241
  • 451
0

HTML

<div>
    <h4>Show content</h4>
</div>
<div>
  <p>Hello World</p>
</div>

CSS

 div+div {
    display: none;
 }

 div:hover +div {
   display: block;
 }

CodePen :hover on div show text in another div

Kondal
  • 2,384
  • 4
  • 21
  • 39
0

Though already an well answered question, I just took the opportunity to post my answer here. Just view this page in W3Schools and you will have a detail answer

https://www.w3schools.com/css/css_combinators.asp

Saikat Dey
  • 187
  • 1
  • 2
  • 12
-1

From my testing using this CSS:

.expandable{
display: none;
}
.expand:hover+.expandable{
display:inline !important;
}
.expandable:hover{
display:inline !important;
}

And this HTML:

<div class="expand">expand</div>
<div class="expand">expand</div>
<div class="expandable">expandable</div>

, it resulted that it does expand using the second , but does not expand using the first one. So if there is a div between the hover target and the hidden div, then it will not work.

Dumitru Daniel
  • 399
  • 3
  • 13
-1

Don't forget. if you are trying to hover around an image, you have to put it around a container. css:

.brand:hover + .brand-sales {
    display: block;
}

.brand-sales {
    display: none;
}

If you hover on this:

<span className="brand">
   <img src="https://murmure.me/wp-content/uploads/2017/10/nike-square-1900x1900.jpg" 
     alt"some image class="product-card-place-logo"/>
</span>

This will show:

<div class="product-card-sales-container brand-sales">
    <div class="product-card-">Message from the business goes here. They can talk alot or not</div>
</div>
Lesly Revenge
  • 706
  • 8
  • 14