为什么<li>(有相对位置)自动尺寸的<ul>(绝对位置)?</li> </ul>

时间:2011-01-14 13:00:37

标签: css html-lists

编辑:另见下面我自己的答案(2016)


例如:

<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>

然后设置样式:

/* 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;
}

确定。所以,我有主菜单,显示水平。我还希望子菜单显示水平。但由于某种原因,ul框不会调整大小以达到总li标签宽度,因此它保持垂直。父亲ul不会遇到这个问题。 我可以通过简单地为孩子ul添加适当的宽度来使其工作,但这不是我想要使用的方式。

有什么想法吗?

6 个答案:

答案 0 :(得分:4)

如果你使用绝对位置,那么让:hover两次是很重要的; li上的第1个触发display: block,然后触发触发器上显示的ul。 然后将定位和样式分开:我设置了a,而不是li

见这里: http://jsfiddle.net/HerrSerker/T8x2r/2/

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

也应该与float:left一起使用 http://jsfiddle.net/T8x2r/3/

答案 1 :(得分:3)

position: absolute元素会占用孩子的大小。

您可以在ul上设置width: 100%;,也可以设置left: 0; right: 0;,这也会将其拉伸到正确的大小。

此外,您可能希望在嵌套的UL和顶级UL上设置list-style:none;

答案 2 :(得分:3)

对于建议您使用ID和类的人,除了可能是第一个ul被称为“菜单”之外,没有必要。我这样说是因为你所寻找的是非常严格和有条理的。

这就是我理解你要完成的事情:当鼠标悬停在主菜单“链接”上时,获取一个水平主菜单,显示下面的另一个水平子菜单

如下所示:

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

现在我没有人告诉你如何设计你的菜单。但正如你现在所看到的,我甚至不确定它应该如何运作。如果第二个菜单左对齐到主菜单项的最左侧点,它是否会悬停在上面?或者第二个菜单是否与整个菜单左对齐,一直到左边?

如果是第一个菜单项,那么最后一个菜单项的空间太小,无法在(最多一个或两个)下面建立链接,如果它是第二个版本,那么人们会因为他们“丢失”子菜单而感到沮丧当鼠标悬停在最后一个菜单项上时(在我们的示例中:菜单项3),当试图一直向左访问链接时。相信我,大多数用户都不熟悉鼠标而且相信我,第一个版本看起来很糟糕。

因此,当主菜单处于水平状态时,人们会使用垂直子菜单,但同样,我不会质疑你的动机。我将尽力以最好的方式回答你的问题,这将最终成为第二种方式,如此设置:

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

首先,您的代码甚至没有设置为让它以这种方式运行。你的代码当前编写的方式,它最终会像我给你看的第一个例子(如我所解释的那样,如果你的菜单占用你页面的宽度,那么最后一个菜单项的水平空间很小当然)

因此,要实现这一目标,您必须摆脱李的相对定位。如果由于某种原因必须将其设置为相对的另一个想法是将主菜单的每个li设置为不同的z-index并将它们设置为左边距/填充以及右边距/填充以“适合”整个菜单。我发现这是一个“黑客”,而宁愿省略你的相对定位。

绝对ul嵌套在你的相对对象下面(无论它是什么,在这种情况下它是菜单

  • )只能占用你指定的空间。在这种情况下,100%将只是它嵌套的li的大小。您可以将其设置为大于100%的值,例如500px,但这会导致问题,原因有两个:1)您将无法将所有子菜单设置为您可能想要的绝对菜单,因为嵌套元素的绝对左边只是它嵌套在li的最左边的点。 2)这不好,因为最右边菜单的子项将偏离整个菜单的右侧。

    如果必须使主菜单保持相对位置,则必须手动单独设置每个嵌套ul的左侧位置。除了第一个之外,这将是一个负数并且不会是一个精确的科学,因为所有浏览器都不显示相同的字体(因此会导致菜单项宽度的轻微变化,以对抗这个你将会需要在所有年龄段的所有浏览器中使用图像以获得完美的宽度。但这会分散CSS的优点,即使用少量线来设计多个元素。

    从主菜单li(#main-menu&gt; ul&gt; 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}
    

    我在自己的浏览器上测试了这个,它看起来像你想要的那样工作。到目前为止,你应该知道另外两种方法来实现这一目标,但结果和工作量都不同于这个版本。

  • 答案 3 :(得分:0)

    好吧,如果您确定项目总是在一行中,您可以移动“position:relative;”到父级ul,并删除“left:0;”从第二个ul开始,它会做你想要的,但如果在行尾有很多项目,它们将被裁剪。

    示例:http://jsfiddle.net/ed9Wx/

    答案 4 :(得分:0)

    因为您在代码中说明了这一点 #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;}
    

    这应该可以解决问题。

    答案 5 :(得分:0)

    有一个愚蠢的事情:在子菜单上,你可以通过简单地强制空格强制将sumbenus强制到内部项目宽度:内部项目的无包裹。尽管您正在使用任何技术或布局,它仍然有效 - 带有显示的主要LI项目:内联块,或现代flex布局//以及潜艇,常规显示无/块或现代css3 fx解决方案 - 没关系。一个原始的例子可以就是这个,在这种情况下使用flexbox和fadein / out 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
    }