M. Eugen
M. Eugen

Reputation: 27

How to overflow 3 levels deep menu ul > li > ul > li > ul > li

I need to create a menu using a combination of ul > li > ul which scale horizontally. Each ul should have a max-height and to scroll if it overflows. On hover over li, it should open another menu on the right if if has another ul tag inside.

In other words, each subsequent menu should be independent, to have it's own scroll bar if necessary and to show/hide if it has another menu (this part works from js code)

For this example bellow I ignored hover mechanism, but red background should show the flow of displaying next menu levels.

Problem: I can't position 3rd level to be absolute, it wraps under 2nd level. Also, I cant overflow 2nd level so I could have 2 scrolls for level2 and level3. Thanks for any help.

HTML:

ul.l1--menu,
ul.l2--menu,
ul.l3--menu  {
	position: relative;
	display: block;
	padding: 0;
	float: left;
	z-index: 1;
	width: 100px;
  border: 1px solid black;
  height: 100px;
}
.menu {
  position: absolute;
}
li {
	list-style: none;
	display: block;
}
li:hover {
  background: red;
}
ul.l1--menu {
	width: 300px;
	z-index: 1;
}
ul.l2--menu {
	margin : 0;
	left: 100px;
	width: 200px;
	z-index: 2;
	position: absolute;
	top: 0;
    max-height:100px;
    overflow-y: scroll;
    overflow-x: hidden;
}
ul.l3--menu {
	margin : 0;
	left: 100px;
	width: 100px;
	z-index: 3;
	position: absolute;
	top: 0;
}
<div class="menu">
  <ul class=" l1--menu">
    <li>
      <a href="#">1</a>
    </li>
    <li>
      <a href="#">2</a>
      <ul class=" l2--menu">
        <li>
          <a href="#">a</a>
        </li>
        <li>
          <a href="#">b</a>
        </li>
        <li>
          <a href="#">c</a>
        </li>
        <li>
          <a href="#">d</a>
          <ul class=" l3--menu">
            <li>
              <a href="#">sub d</a>
            </li>
          </ul>
        </li>
        <li>
          <a href="#">e</a>
          <ul class=" l3--menu">
            <li>
              <a href="#">sub e</a>
            </li>
          </ul>
        </li>
        <li>
          <a href="#">e</a>
        </li>
        <li>
          <a href="#">f</a>
        </li>
        <li>
          <a href="#">g</a>
        </li>
        <li>
          <a href="#">h</a>
        </li>
       </ul>
     </li>
   </ul>
 </div>

Upvotes: 0

Views: 1970

Answers (2)

vals
vals

Reputation: 64244

Here is a solution using pure CSS.

I changed display none to opacity 0 to get the posibility of fade-in fade-out and also to be more user-frindly with keeping the state when going from parent to child

.menu {
  position: relative;
}

ul {
  width: 200px;
  margin: 0;
  color: black;
  list-style:none;
  padding:0;
  max-height:100px;
  overflow-x: hidden;
  overflow-y: auto;
}

li {
  padding:0.5em;
}
li:hover{
  background-color:blue;
  color:white;
}
li .menu {
  position: absolute;
  z-index: 10;
  background-color:lightgrey;
  opacity: 0;
  transition: opacity 0.5s;
}
li:hover > .menu,
.menu:hover {
  opacity: 1;
}

li.parent {
  cursor: pointer;
}

.level2 {
  top: 0px;
  left: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="menu">
  <ul>
    <li>Link1</li>
    <li class="parent">Link3...
      <div class="menu level2">
        <ul>
          <li class="parent">Link31...
            <div class="menu level2">
              <ul>
                <li>Link 311</li>
                <li>Link 312</li>
                <li>Link 313</li>
                <li>Link 314</li>
              </ul>
            </div>
          </li>
          <li>Link 32</li>
          <li>Link 33</li>
          <li>Link 34</li>
        </ul>
      </div>
    </li>
    <li>Link2</li>
    
    <li>Link1</li>
    <li>Link2</li>
    
  </ul>
</div>

Upvotes: 2

Pawan Kumar
Pawan Kumar

Reputation: 1374

If you wanted to do something similar to this, just try it.

$(function() {
  $('li.parent').on('mouseover', function() {
    var menuItem = $(this);
    var submenuItem = $('.menu', menuItem);
    
    var menuItemPos = menuItem.position();
    
    submenuItem.css({
      top: 0,
      left: menuItemPos.left + Math.round(menuItem.outerWidth())
    });
  });
});
.menu {
  position: relative;
}

ul {
  width: 200px;
  margin: 0;
  color: black;
  list-style:none;
  padding:0;
  max-height:100px;
  overflow-x: hidden;
  overflow-y: auto;
}

li {
  padding:0.5em;
}
li:hover{
  background-color:blue;
  color:white;
}
li .menu {
  position: absolute;
  z-index: 10;
  display: none;
  background-color:lightgrey;
}
li:hover > .menu {
  display: block;
}

li.parent {
  cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="menu">
  <ul>
    <li>Link1</li>
    <li class="parent">Link3...
      <div class="menu">
        <ul>
          <li class="parent">Link31...
            <div class="menu">
              <ul>
                <li>Link 311</li>
                <li>Link 312</li>
                <li>Link 313</li>
                <li>Link 314</li>
              </ul>
            </div>
          </li>
          <li>Link 32</li>
          <li>Link 33</li>
          <li>Link 34</li>
        </ul>
      </div>
    </li>
    <li>Link2</li>
    
    <li>Link1</li>
    <li>Link2</li>
    
  </ul>
</div>

Upvotes: 1

Related Questions