CSS 为什么 <li>(具有相对位置)内的 <ul>(具有绝对位置)不能自动调整大小?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4691317/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why can't an <ul> (with absolute position) inside a <li> (with relative position) auto size?
提问by Luca Reghellin
EDIT: see also my own answer below (2016)
编辑:另见下面我自己的答案(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 styled:
然后样式:
/* 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've got the main menu that shows up horizontal. I also want the submenu to show horizontal. But for some reason, the ul box do not resize to reach the total li tags width, so it remains vertical. The parent ul do not suffer of this problem. I could make it work by simply adding a proper width to the child ul, but this is not the way I wanna use.
好的。所以,我得到了水平显示的主菜单。我还希望子菜单显示水平。但出于某种原因,ul 框不会调整大小以达到 li 标签的总宽度,因此它保持垂直。父 ul 不会遇到这个问题。我可以通过简单地为子 ul 添加适当的宽度来使其工作,但这不是我想要使用的方式。
Any idea?
任何的想法?
采纳答案by Luca Reghellin
There's one stupid thing: on the submenus, you can force the sumbenus to the inner items width by simply forcing whitespace: no-wrap on the inner items. It works despite any technique or layout you are using -- main LI items with display: inline-block, or modern flex layouts // and for the subs, regular display none/block or modern css3 fx solutions-- it doesn't matter. A raw example can be just this, in this case using flexbox and fadein/out fx for subs (but could be anything more simple no-flexbox or older, it really doesn't matter):
有一件愚蠢的事情:在子菜单上,您可以通过简单地强制使用 whitespace: no-wrap on the internal items 来将 sumbenus 强制设置为内部项的宽度。无论您使用任何技术或布局,它都可以工作——带显示的主要 LI 项目:内联块,或现代 flex 布局 // 对于 subs,常规显示无/块或现代 css3 fx 解决方案——没关系. 一个原始示例可能就是这样,在这种情况下,使用 flexbox 和淡入/淡出 fx 为 subs(但可以是更简单的 no-flexbox 或更旧的东西,这真的无关紧要):
.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
}
回答by yunzen
It's important to have the :hover
twice if you use position absolute; 1st on the li
, that triggers the display: block
, then on the ul
that is shown on trigger.
And then keep positioning and styling separate: I styled the a
and not the li
:hover
如果您使用绝对位置,那么两次很重要;第 1 次li
触发display: block
,然后ul
触发显示的 。
然后保持定位和样式分开:我设计了a
而不是li
See here: http://jsfiddle.net/HerrSerker/T8x2r/2/
见这里: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/
应与工作float:left
也
http://jsfiddle.net/T8x2r/3/
回答by kapa
Elements with position: absolute
take up the size of their children.
元素与position: absolute
占用其子项的大小。
You can either set width: 100%;
on the ul, or set left: 0; right: 0;
which will also stretch it to the right size.
您可以width: 100%;
在 ul 上设置left: 0; right: 0;
,也可以设置它也会将其拉伸到正确的大小。
Also you might want to set list-style:none;
on the nested ULs as well as top one.
此外,您可能希望设置list-style:none;
嵌套的 UL 以及顶部的 UL。
回答by victoroux
To the person who suggested you use ids and classes, it is not necessary except for perhaps the very first ul being id'ed as "menu". I say this because what you're looking for is very rigid and structured.
对于建议您使用 id 和类的人来说,除了第一个 ul 可能被标识为“菜单”之外,没有必要。我这样说是因为你正在寻找的是非常僵化和结构化的。
This is what I understand you're trying to accomplish: Get a horizontal main menu that shows another horizontal sub-menu underneath when hovering over the main menu "links"
这就是我理解您要完成的任务:获取一个水平主菜单,当将鼠标悬停在主菜单“链接”上时,该菜单在下方显示另一个水平子菜单
As shown here:
如图所示:
----------------------------------------------------------------------
Menu-Item 1 | Menu Item 2 (hovered over) | Menu Item 3
----------------------------------------------------------------------
| Sub Menu 1 | Sub Menu 2 | Sub Menu 3
-------------------------------------------------------
Now I'm no one to tell you how to design your menus. But as you can see right now, I'm not sure even how it should work. Should the second menu be left-aligned to the left most point of the main menu item it's hovered over? Or Should the second menu be left-aligned to the whole menu, all the way to the left?
现在我不会告诉你如何设计你的菜单。但是正如您现在所看到的,我什至不确定它应该如何工作。第二个菜单应该左对齐到它悬停在主菜单项上的最左边点吗?或者第二个菜单是否应该与整个菜单左对齐,一直向左?
If it's the first, the last menu item will have too small a space to have links under (one or two max) and if it's the second version, then people will get frustrated that they keep "losing" the sub-menu when trying to access the links all the way to the left when hovering over the last menu item (in our example: Menu Item 3). Trust me, most users are not that adept with the mouse and trust me, the first version would just look bad.
如果是第一个,最后一个菜单项的空间太小,无法在下面放置链接(最多一个或两个),如果是第二个版本,那么人们会感到沮丧,因为他们在尝试时总是“丢失”子菜单将鼠标悬停在最后一个菜单项(在我们的示例中:菜单项 3)上时,可以访问一直到左侧的链接。相信我,大多数用户都不太擅长使用鼠标,相信我,第一个版本会看起来很糟糕。
Thus people use vertical sub-menus when the main menu is horizontal, but again, I'm not going to question your motives. I'm gonna try to answer your question in the best way I can which will end up being the second way, set up 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 set-up to have it go this way. The way your code is currently written, it'll end up like the first example 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 accomplish this goal you will have to get rid of the relative positioning of your li. Another idea if you MUST for some reason have it set to relative is to set each li of your main menu to a different z-index and to set them left margin/padding as well as right margin/padding as to "fit" your entire menu. I find this to be a "hack" and would rather omit the relative positioning of your li.
因此,要实现此目标,您必须摆脱 li 的相对定位。如果出于某种原因必须将其设置为相对的另一个想法是将主菜单的每个 li 设置为不同的 z-index 并将它们设置为左边距/填充以及右边距/填充以“适合”整个菜单。我发现这是一个“黑客”,宁愿省略你的 li 的相对定位。
The absolute ul nested underneath your relative object (whatever it be, in this case it is the menu
嵌套在相对对象下面的绝对 ul(不管它是什么,在这种情况下它是菜单
If you must keep the main menu positioned relative, you will have to individually set the left position of each nested ul manually. And for all but the first one this will be a negative number and will not be an exact science as all browsers do not display the same font (and thus will cause slight changes in the width of the menu items, to counter this you'll need to use images for perfect width across all browsers of all ages). But this distracts from the beauty of CSS which is using few lines to design multiple elements.
It would be much easier to remove the "relative" positioning off the main menu li (#main-menu > ul > li) and to add some bottom padding to it, else you'll never be able to hover over the sub-menu, it'll just disappear each time. If I had to guess at what you're doing and I was coding the CSS/HTML I would do 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've tested this on my own browser and it seems to work like you want it to. By now you should know two other ways to accomplish this, but with varying results and more work than this version.
如果必须保持主菜单相对定位,则必须手动单独设置每个嵌套 ul 的左侧位置。对于除第一个之外的所有内容,这将是一个负数,并且不会是一门精确的科学,因为所有浏览器都不会显示相同的字体(因此会导致菜单项的宽度略有变化,为了解决这个问题,您将需要在所有年龄段的所有浏览器中使用完美宽度的图像)。但这分散了 CSS 使用几行代码来设计多个元素的美感。
从主菜单 li (#main-menu > ul > li) 中删除“相对”定位并为其添加一些底部填充会容易得多,否则您将永远无法将鼠标悬停在子菜单上,它每次都会消失。如果我不得不猜测你在做什么并且我正在编写 CSS/HTML,我会这样做:
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}
我已经在我自己的浏览器上测试过它,它似乎像你想要的那样工作。到现在为止,您应该知道另外两种实现此目的的方法,但与此版本相比,结果各不相同,并且需要做更多的工作。
回答by Alexey Ivanov
Well, if you are sure that items always will be in one line, you can move "position: relative;" to parent ul, and remove "left: 0;" from second ul, it will do what you want, but if there will be to many items in the end of the line, they will be cropped.
好吧,如果您确定项目总是在一行中,您可以移动“位置:相对;” 到父 ul,并删除“left: 0;” 从第二个 ul 开始,它会做你想做的,但如果行尾有很多项目,它们将被裁剪。
Example: http://jsfiddle.net/ed9Wx/
回答by Charming Prince
Since you stated this in your code
#main-menu > ul > li:hover ul {
display:inline-block; }
it'd be best you make the display: block; margin: auto;
that way it could go full width of the li tag
既然你在你的代码中说明了这一点,那么你
#main-menu > ul > li:hover ul {
display:inline-block; }
最好这样做display: block; margin: auto;
,它可以达到 li 标签的全宽
#main-menu > ul > li:hover ul {
display:block; }
#main-menu > ul > li ul li{
float:left;
margin: auto;
list-style:none;}
This should do the trick.
这应该可以解决问题。