Why can't <ul> (with absolute position) inside the automatic size <li> (with relative position)?

EDIT: see also my own answer below (2016)


For example:

<ul> <li class="first"><a href="#" title="">Home</a></li> <li><a href="#" title="">Chi siamo</a> <ul><li><a href="#" title="">item1</a></li><li><a href="#" title="">item2</a></li></ul> </li> <li><a href="#" title="">Novità</a></li> <li><a href="#" title="">Promozioni</a></li> </ul> 

Then in the style of:

 /* level 1 Main menu ----------------------------------------- */ #main-menu > ul{ list-style:none; } #main-menu > ul > li{ float:left; display:block; position:relative; margin-left:1em; } #main-menu > ul > li.first{ margin-left:0; } /* sub Main menu ----------------------------------------- */ #main-menu > ul > li ul { position: absolute; z-index:1000; display:none; left:0; top:28px; } #main-menu > ul > li:hover ul { display:inline-block; } #main-menu > ul > li ul li{ float:left; display:block; list-style:none; } 

OK. So, I have a main menu that displays horizontally. I also want the submenu displayed horizontally. But for some reason, the ul box doesn't resize to achieve the total width of the li tags, so it stays vertical. The ul parent does not suffer from this problem. I could make it work by simply adding the correct width to the child ul, but that is not the way I want to use.

Any idea?

+8
css html-lists
source share
6 answers

There's one stupid thing: in the submenu, you can force sumbenus to use the internal width of the elements by simply forcing spaces: no-wrap on the internal elements . It works, despite any technique or layout that you use - the main LI elements with a display: built-in block or modern flexible layouts // and for subnets, a normal none / block display or modern css3 fx solutions - it doesn’t matter, Raw An example can be just this, in this case using flexbox and fadein / out fx for subs (but maybe something simpler no-flexbox or older, it really doesn't matter):

 .main-menu{ // ul display: flex; flex-wrap: nowrap; > li{ display: inline-block; flex: 1; position: relative; &:hover{ .sub-menu{ visibility: visible; opacity: 1; transition: opacity 200ms linear; } } .sub-menu{ display: inline-block; position: absolute; top: 50px; left:0; visibility: hidden; opacity: 0; transition: visibility 0s 200ms, opacity 200ms linear; li{ a{ white-space: nowrap; // <<< THIS IS THE KEY! } } } // sub-menu } // > li } 
0
source share

It is important that :hover twice if you use the absolute position; 1 on li , which runs display: block , and then on ul , which is displayed on the trigger.
Then save the positioning and style: I created a , not li

See here: http://jsfiddle.net/HerrSerker/T8x2r/2/

 #main-menu > ul > li > ul:hover, #main-menu > ul > li:hover > ul { display: block; } 

Should work with float:left also http://jsfiddle.net/T8x2r/3/

+5
source share

Elements with position: absolute occupy the size of their children.

You can either set width: 100%; on ul, or set left: 0; right: 0; left: 0; right: 0; which will also stretch it to the desired size.

You can also set list-style:none; on nested UL, as well as on the top.

+3
source share

For a person who suggested that you use identifiers and classes, this is not necessary, except that perhaps the very first ul was id'ed as a “menu”. I say this because what you are looking for is very rigid and structured.

This is what I understand you are trying to accomplish: get a horizontal main menu that displays another horizontal submenu at the bottom when it hangs over the main menu “links”

As below:

 ---------------------------------------------------------------------- Menu-Item 1 | Menu Item 2 (hovered over) | Menu Item 3 ---------------------------------------------------------------------- | Sub Menu 1 | Sub Menu 2 | Sub Menu 3 ------------------------------------------------------- 

Now I won’t tell anyone how to create my own menus. But, as you can see right now, I'm not sure how it should work. If the second menu is left-aligned on the left side of the main menu item, which one does it hang? Or, if the second menu is left-aligned to the entire menu, is everything to the left?

If this is the first, the last menu item will contain too little space for links (one or two max), and if this is the second version, then people will be disappointed that they continue to “play” the submenu when they try to access the links all the way to the left when hovering cursor to the last menu item (in our example: menu item 3). Believe me, most users are not so good at mouse and trust me, the first version will look just bad.

Thus, people use vertical submenus when the main menu is horizontal, but then again, I will not question your motives. I am going to try to answer your question in the best way, which may be the second way configured as such:

 ---------------------------------------------------------------------- Menu-Item 1 | Menu Item 2 (hovered over) | Menu Item 3 ---------------------------------------------------------------------- Sub Menu 1 | Sub Menu 2 | Sub Menu 3 | (blank) ---------------------------------------------------------------------- 

Firstly, your code is not even configured to go this way. The way your code is currently written will be the same as in the first example that I showed you (which, as I explained, will have very little horizontal space for the last menu item to show things if your menu takes up the width of your page of course)

So, to achieve this, you have to get rid of your relative positioning. Another idea, if you SHOULD relate it to a relative for some reason, is to set each li of your main menu to a different z-index and set their left margin / pad as well as the right margin / pad to "put "your entire menu. I believe that this is a “hack” and rather omit the relative positioning of your whether.

The absolute ul nested below your relative object (whatever it may be, in this case the menu

), may take up as much space as you indicated. In this case, 100% will only be whether the size in it is nested. You can set it to something greater than 100%, for example 500 pixels, but this can cause a problem for two reasons: 1) you cannot set all the submenus to the absolute menu on the left, as you probably want, because the absolute left part of the nested element will it be only the left left side in it. and 2) This is not good, because the correct majority of the subtypes of the menu will be shifted to the right of the general menu.

If you must leave the main menu positional relative to, you will have to individually set the left position of each nested ul manually. And for all but the first, this will be a negative number and will not be an exact science, since all browsers will not display the same font (and, thus, it will lead to small changes in the width of the menu items to counter this, you you will need to use images for perfect width in all browsers of all ages). But this distracts from the beauty of CSS, which uses multiple lines to create multiple elements.

It would be much easier to remove the "relative" positioning from the li main menu (# main-menu> ul> li) and add some bottom addition to it, otherwise you can never hover over a submenu, it will simply disappear every time. If I had to guess what you were doing and I encoded CSS / HTML, I would have done it as such:

HTML:

  <li>A <ul> <li>A1<li> <li>A2<li> <li>A3<li> </ul> </li> <li>B <ul> <li>B1<li> <li>B2<li> <li>B3<li> </ul> </li> <li>C <ul> <li>C1<li> <li>C2<li> <li>C3<li> </ul> </li> </ul> 

CSS

 ul#main-menu{ list-style:none;} ul#main-menu > li { float: left; margin-left: 1em; padding-bottom: 3em; /*make this the line-height space underneat the main menu, plus the heigh of the secondary menu, plus the extra space you wanna give the user to not lose focus on the second menu*/ } ul#main-menu > li:first-child {margin-left: 0;} ul#main-menu > li > ul { display: none; } ul#main-menu > li:hover > ul { position: absolute; display: block; left: 0; list-style: none; } ul#main-menu > li:hover > ul > li, ul#main-menu > li > ul:hover > li { position: relative; float: left; margin-left: 1em; } ul#main-menu > li:hover > ul > li:first-child, ul#main-menu > li > ul:hover > li:first-child {margin-left: 0px} 

I tested this in my browser and it seems to work the way you want it. By now, you should know two other ways to achieve this, but with different results and more work than this version.

+3
source share

Well, if you are sure that the elements will always be on the same line, you can move "position: relative"; to the parent ul, and delete "left: 0;" from the second ul, it will do what you want, but if there are many elements at the end of the line, they will be trimmed.

Example: http://jsfiddle.net/ed9Wx/

0
source share

Since you indicated this in your code #main-menu > ul > li:hover ul { display:inline-block; } #main-menu > ul > li:hover ul { display:inline-block; } it would be best to do display: block; margin: auto; display: block; margin: auto; so it could go the full width of the li tag

 #main-menu > ul > li:hover ul { display:block; } #main-menu > ul > li ul li{ float:left; margin: auto; list-style:none;} 

That should do the trick.

0
source share

Source: https://habr.com/ru/post/651061/


All Articles