CSS fixed menu on the right side. Using hover to open submenus

Hi,

I have my nav fixed on the right side. I have used html tables for that. In the code I have set the hover on the first anchor, therefore the submenu appears (as expected). Because of the way I coded the stylesheet, as I hover on the opened yellow menu below, this menu disappears. But I don’t want that the menu disappears. I need an help to resolve this problem. Can you help me? Thanks a lot! :slight_smile:

Fiddle:
jsfiddle.net/framj00/zkL00Ldr/

My code:

<!DOCTYPE html>
<html lang='it'>
  <head>
    <title></title>
    <meta charset='utf-8'>
    <meta name='description' content=''>
    <meta name='keywords' content=''>
    <meta name='author' content=''>
    <meta name='robots' content='all'>
    <link href='/favicon.png' rel='shortcut icon' type='image/png'>
  <style>
  html, body {
     height: 100%;
     padding: 0;
     margin: 0;
  }

  #nav {
     position: absolute;
     display: fixed;
     top: 50%;
     right: 0;
     width: 60px;
  }

  ul {
     padding:0;
     margin: 0;
     list-style: none;
     width: 600px;
     background: grey;
     table-layout: fixed;
     position: absolute;
     right: 0;
  }

  #nav > li > ul {
     margin-right: 60px;
  }

  li {
     display: table;
     height: 60px;
     background: yellow;
     width: 100%;
  }

  a {
     display: table-row;
     display: none;
     width: 100%;
     height: 60px;
     line-height: 60px;
     top: 50%;
     text-align: right;
  }

  li ul {
     display: none;
  }

  li:hover a {
     display: table-row;
  }

  li a:hover + ul {
     display: block !important;
  }

  #button-one {
     display: block;
     width: 60px;
     height: 60px;
     background: tomato;
  }

  #nav > li > a {
     text-indent: -9999em;
  }

  </style>
  </head>
  <body>
     <ul id='nav'>
        <li id='button-one'><a>Sub menu title</a>
           <ul>
              <li>
                 <a>Link</a>
              </li>
              <li><a>Submenu</a>
                 <ul>
                    <li><a href=''>Link 1</a></li>
                    <li><a href=''>Link 2</a></li>
                    <li><a href=''>Link 3</a></li>
                    <li><a href=''>Link 4</a></li>
                  </ul>
              </li>
           </ul>
        </li>
     </ul>
  </body>
</html>

thanks!

Hi,

You have some big logic errors in that code that need addressing,

First of all this rule:

  li a:hover + ul {
     display: block !important;
  }

That says that while you hover an anchor then show the ul next to it. As soon as you stop hovering the anchor then the ul will disappear. This means you can’t use it as a technique for opening and navigating a submenu.

What you need to do is hover on the parent list item as this contains the nested ul and will allow the ul to show and remain hovered while you navigate it because you are still hovering the parent list.

li:hover > ul {
     display: block;
  }

That also means that the nested ul should not be placed anywhere where it does not remain in contact with the parent list. Hover menus must always have an edge touching the trigger point or you won;t be able to keep them open before you get to them.

I’m not sure why you are using display:table rules but then again the display isn’t really showing me anything that I can latch on to. Note there is no such thing as display:fixed and I think you meant position:fixed.

Take care with global rules because you don’t want to apply these to all elements throughout your site.

e.g.

  li:hover a {
     display: table-row;
  }

It is very unlikely that you want that to apply to all elements throughout your site so don’t forget to use the class

Here is a working menu but of course I have no idea how you wanted it to look but you can modify it as you wish but maintain the key concepts I mentioned above to keep it working.

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<style>
html, body {
	height: 100%;
	padding: 0;
	margin: 0;
}
ul {
	padding:0;
	margin: 0;
	list-style: none;
}
#nav {
	position:fixed;
	top: 50%;
	right: 0;
	width: 120px;
}
#nav ul {
	width: 200px;
	background: grey;
	position:absolute;
	left:-9999em;
}
#nav a {
	display:block;
	padding:5px 10px;
}
#nav ul li {
	position:relative;
}
#nav li:hover > ul {
	left:-200px;
	top:0;
}
#nav li:hover > a {
	background:yellow;
	cursor:pointer
}
#button-one a {
	display: block;
	padding:5px 10px;
	background: tomato;
}
</style>
</head>

<body>
<ul id='nav'>
  <li id='button-one'><a>Sub menu title</a>
    <ul>
      <li><a>Link</a></li>
      <li><a>Submenu</a>
        <ul>
          <li><a href=''>Link 1</a></li>
          <li><a href=''>Link 2</a></li>
          <li><a href=''>Link 3</a></li>
          <li><a href=''>Link 4</a></li>
        </ul>
      </li>
    </ul>
  </li>
</ul>
</body>
</html>
1 Like

Yes, many thanks! It’s very clear!

Now I wonder, If i want to load this content on a smartphone, Do I have to code also a function to handle the click event using jQuery? What do you think? (I know that jQuery is out of topic, but this question seems to be important now!)

It starts to get complicated when you want to handle hover effects for touch devices which is why I generally avoid hover dropdowns and go with a click version for all.

You can actually make a menu work for mobile without hover as long as you structure it correctly and use anchors (with href) for the triggers because mobile generally treats first touch as a hover and will often show the hover effect. The downside is that most times this will leave the menu open on the screen until you click another link elsewhere in the page to remove the focus from the link.

Here is a css method that slides out a close menu so that mobile users can click and close the menu. There is a 5 second delay on it appearing so hover users mostly won’t see it. There may be an issue in older android/webkit not supporting hover in combination with adjacent selector but that is a bug.

Anyway here is how it looks:

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Untitled Document</title>
<style>
html, body {
	height: 100%;
	padding: 0;
	margin: 0;
}
ul {
	padding:0;
	margin: 0;
	list-style: none;
}
#navwrap {
	position:fixed;
	top: 0;
	bottom:0;
	right: 0;
	width: 120px;
	height:28px;
	margin:auto;
}
#nav ul {
	width: 100px;
	background: grey;
	position:absolute;
	left:-9999em;
}
#nav a {
	display:block;
	padding:5px 10px;
}
#nav ul li {
	position:relative;
}
#nav li:hover > ul {
	left:-100px;
	top:0;
}
#nav li:hover > a {
	background:yellow;
	cursor:pointer
}
#button-one a {
	display: block;
	padding:5px 10px;
	background: tomato;
}
.close {
	z-index:-1;
	opacity:0;
	transition:all .5s ease 5s;
	position:absolute;
	left:0;
	top:0;
}
#nav:hover + .close {
	top:-100%;
	opacity:1;
	display: block;
	padding:5px 10px;
	background: tomato;
}
</style>
</head>

<body>
<div id="navwrap">
  <ul id='nav'>
    <li id='button-one'><a href="#">Sub menu here.</a>
      <ul>
        <li><a href="#">Link</a></li>
        <li><a href="#">Submenu</a>
          <ul>
            <li><a href='http://www.google.com'>Google</a></li>
            <li><a href='#'>Link 2</a></li>
            <li><a href='#'>Link 3</a></li>
            <li><a href='#'>Link 4</a></li>
          </ul>
        </li>
      </ul>
    </li>
  </ul>
  <a class="close" href="#">Close</a> </div>
</body>
</html>

You will of course need media queries depending on your content to align better at smaller screen widths.

1 Like

Yes! Excellent!

In my first code I have thought the anchor with the button without href, because I was trying to handle click and hover, and I don’t want to load any page. Once you click (or hover) on that button, you can see the list of hrefs and load what you want.

I was thinking also about this:
When I have that button (the first button tagged Sub Menu here) with anchor but without href, once I hover on it, (useful if there is only one child link) the href of the child link appears also on that empty anchor!

Look at this site, scroll down a little bit and look at the right fixed menu. You can see that, (if you use an inspector) only when you hover on the image of the menu, that image become clickable with the same anchor with href of his child link. (It has been used something as, ::before and content, things that I have never used before!)

That menu is controlled purely by javascript and adds a class to the menu (probably) on mouseover/touchstart and removes it on mouseout/touchend. It does not use css hover as such although it could mostly be duplicated in css with a different structure but you would still need to address the touch issue.

The menu on that page uses js to add a class so that the menu can slide out as required. It has a different structure to your nested list approach because it relies on javascript and not nested uls.

Indeed if you disable javascript on that site you get no site at all as all you get is the spinning loading gif on a blank page.

Also note that on small screen the menu is moved to the top and inside a button to activate it.

1 Like

Hi Paul,

In both of your nav, there is some bug, if you add more than one “Sub menu title”, the nested menu open always on the left of the first “Sub menu title”:

fiddle:
jsfiddle.net/framj00/ykn2dyf0/

code:

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<style>
html, body {
	height: 100%;
	padding: 0;
	margin: 0;
}
ul {
	padding:0;
	margin: 0;
	list-style: none;
}
#nav {
	position:fixed;
	top: 50%;
	right: 0;
	width: 120px;
}
#nav ul {
	width: 200px;
	background: grey;
	position:absolute;
	left:-9999em;
}
#nav a {
	display:block;
	padding:5px 10px;
}
#nav ul li {
	position:relative;
}
#nav li:hover > ul {
	left:-200px;
	top:0;
}
#nav li:hover > a {
	background:yellow;
	cursor:pointer
}
.button a {
	display: block;
	padding:5px 10px;
	background: tomato;
}
</style>
</head>

<body>
<ul id='nav'>
  <li class='button'><a>Sub menu title 1</a>
    <ul>
      <li><a>Link</a></li>
      <li><a>Submenu</a>
        <ul>
          <li><a href=''>Link 1</a></li>
          <li><a href=''>Link 2</a></li>
          <li><a href=''>Link 3</a></li>
          <li><a href=''>Link 4</a></li>
        </ul>
      </li>
    </ul>
  </li>
  <li class='button'><a>Sub menu title 2</a>
    <ul>
      <li><a>Link</a></li>
      <li><a>Submenu</a>
        <ul>
          <li><a href=''>Link 1</a></li>
          <li><a href=''>Link 2</a></li>
          <li><a href=''>Link 3</a></li>
          <li><a href=''>Link 4</a></li>
        </ul>
      </li>
    </ul>
  </li>
  <li class='button'><a>Sub menu title 3</a>
    <ul>
      <li><a>Link</a></li>
      <li><a>Submenu</a>
        <ul>
          <li><a href=''>Link 1</a></li>
          <li><a href=''>Link 2</a></li>
          <li><a href=''>Link 3</a></li>
          <li><a href=''>Link 4</a></li>
        </ul>
      </li>
    </ul>
  </li>
</ul>
</body>
</html>

It should be this if you have more than one item.

#navwrap ul li {
	position:relative;
}

e.g.

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Untitled Document</title>
<style>
html, body {
	height: 100%;
	padding: 0;
	margin: 0;
}
ul {
	padding:0;
	margin: 0;
	list-style: none;
}
#navwrap {
	position:fixed;
	top: 0;
	bottom:0;
	right: 0;
	width: 120px;
	height:28px;
	margin:auto;
}
#nav ul {
	width: 100px;
	background: grey;
	position:absolute;
	left:-9999em;
}
#nav a {
	display:block;
	padding:5px 10px;
}
#navwrap ul li {
	position:relative;
}
#nav li:hover > ul {
	left:-100px;
	top:0;
}
#nav li:hover > a {
	background:yellow;
	cursor:pointer
}
.button a {
	display: block;
	padding:5px 10px;
	background: tomato;
}
.close {
	z-index:-1;
	opacity:0;
	transition:all .5s ease 5s;
	position:absolute;
	left:0;
	top:0;
}
#nav:hover + .close {
	top:-100%;
	opacity:1;
	display: block;
	padding:5px 10px;
	background: tomato;
}
</style>
</head>

<body>
<div id="navwrap">
  <ul id='nav'>
    <li class="button"><a href="#">Sub menu here.</a>
      <ul>
        <li><a href="#">Link</a></li>
        <li><a href="#">Submenu</a>
          <ul>
            <li><a href='http://www.google.com'>Google</a></li>
            <li><a href='#'>Link 2</a></li>
            <li><a href='#'>Link 3</a></li>
            <li><a href='#'>Link 4</a></li>
          </ul>
        </li>
      </ul>
    </li>
    <li class="button" ><a href="#">Sub menu 2.</a>
      <ul>
        <li><a href="#">Link 2</a></li>
        <li><a href="#">Submenu 2</a>
          <ul>
            <li><a href='http://www.google.com'>Google</a></li>
            <li><a href='#'>Link 2</a></li>
            <li><a href='#'>Link 3</a></li>
            <li><a href='#'>Link 4</a></li>
          </ul>
        </li>
      </ul>
    </li>
    
    
  </ul>
  <a class="close" href="#">Close</a> </div>
</body>
</html>

Another observation. When menu is tall, there is no way to scroll down the page!

That was your design not mine.:slight_smile:

You placed the nav at 50% using position:fixed and fixed positioned elements cannot be accessed if they go outside the viewport. Your original demo only had a couple of items so likely would not have been an issue. If you are going to have loads of items then you will need to re-think the usefulness of having the menu fixed half way down the screen.

The example you linked to was a single line menu of 5 items only all of fixed height which is fine and easy to control and doesn’t extend out of the viewport. If you want a fixed side menu then you should follow that sort of design and keep it minimal.

If you want a full drop down then you should have it in the flow at the top of the page like normal navigation or if it must be fixed positioned then move it to nearer the top of the page so that there’s a good chance it won’t go out of the viewport.

In the end its up to you to decide what is the best design for the content you have in mind. We started with a couple of items but if you are expanding to many items then a different approach is needed. Web design is all about what comes next and building the demo with full example content so that the right approach is taken from the start. :slight_smile:

This is about as many items as you should be thinking of at that position.

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Untitled Document</title>
<style>
html, body {
	height: 100%;
	padding: 0;
	margin: 0;
}
ul {
	padding:0;
	margin: 0;
	list-style: none;
}
#navwrap {
	position:fixed;
	top: 0;
	bottom:0;
	right: 0;
	width: 120px;
	height:120px;
	margin:auto;
}
#nav ul {
	width: 100px;
	background: grey;
	position:absolute;
	left:-9999em;
}
#nav a {
	display:block;
	padding:5px;
	border:1px solid #000;
	margin:0 0 -1px;
}
#navwrap ul li {
	position:relative;
}
#nav li:hover > ul {
	left:-100px;
	top:0;
}
#nav li:hover > a {
	background:yellow;
	cursor:pointer
}
.button a {
	display: block;
	padding:5px 10px;
	background: tomato;
}
.close {
	z-index:-1;
	opacity:0;
	transition:all .5s ease .5s;
	position:absolute;
	left:0;
	top:0;
}
#nav:hover + .close {
	top:-30px;
	opacity:1;
	display: block;
	padding:5px 10px;
	background: tomato;
	transition:all .5s ease 5s;
}
</style>
</head>

<body>
<div id="navwrap">
  <ul id='nav'>
    <li class="button"><a href="#">Sub menu here.</a>
      <ul>
        <li><a href="#">Link</a></li>
        <li><a href="#">Submenu</a>
          <ul>
            <li><a href='http://www.google.com'>Google</a></li>
            <li><a href='#'>Link 2</a></li>
            <li><a href='#'>Link 3</a></li>
            <li><a href='#'>Link 4</a></li>
          </ul>
        </li>
      </ul>
    </li>
    <li class="button" ><a href="#">Sub menu 2</a>
      <ul>
        <li><a href="#">Link 2</a></li>
        <li><a href="#">Submenu 2</a>
          <ul>
            <li><a href='http://www.google.com'>Google</a></li>
            <li><a href='#'>Link 2</a></li>
            <li><a href='#'>Link 3</a></li>
            <li><a href='#'>Link 4</a></li>
          </ul>
        </li>
      </ul>
    </li>
    <li class="button" ><a href="#">Sub menu 3</a>
      <ul>
        <li><a href="#">Link 3</a></li>
        <li><a href="#">Submenu 3</a>
          <ul>
            <li><a href='http://www.google.com'>Google</a></li>
            <li><a href='#'>Link 2</a></li>
            <li><a href='#'>Link 3</a></li>
            <li><a href='#'>Link 4</a></li>
          </ul>
        </li>
      </ul>
    </li>
    <li class="button" ><a href="#">Sub menu 4</a>
      <ul>
        <li><a href="#">Link 4</a></li>
        <li><a href="#">Submenu 4</a>
          <ul>
            <li><a href='http://www.google.com'>Google</a></li>
            <li><a href='#'>Link 2</a></li>
            <li><a href='#'>Link 3</a></li>
            <li><a href='#'>Link 4</a></li>
          </ul>
        </li>
      </ul>
    </li>
  </ul>
  <a class="close" href="#">Close</a> </div>
</body>
</html>

Sorry, so many questions. I am curious and sometimes I am unable to code properly!

So there isn’t any solution with fixed position! :frowning:

Web design is like cookies. One cookie led to another cookie and… etc… :slight_smile:
I see a completed demo at a particular step, and another idea springs out, and I would to go to the next step!

Does another solution could be imagine body as table, and main as table-row having two cells, respectively the content on left and nav on the right? Do you think it could be ok?

No worries. That’s how you learn and then you begin to understand what is possible and what is feasible.

It all depends of the data you want to display. If you can supply the data you need to display then it can be worked out from there where best it will fit and if things are possible.

If you look at the Alfa romeo site you linked to then they only have 7 fixed width items to cater for and only slide out one level to the left. The last item has the three social network icons in a row so you could do something similar with three links in a row on each item but you could not then have more submenus as with your example.

Usually those fixed side menus are just showing a few main navigation links and not meant to be a full navigation system.

The best way to find out is to keep experimenting as you are doing and to see what works and what doesn’t :slight_smile:

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.