绝对定位及其父元素

8
我一直听说当你使用绝对定位时,你想要作为其父元素的元素需要具有relativeposition
我试图构建一个CSS下拉菜单,但当我将其父元素设置为relative时,我很难让下拉菜单项超出主菜单项的宽度; 下拉菜单项中的文本会自动换行。
所以我查看了其他示例菜单,看看它们是如何做到的,我发现其中一个甚至没有使用任何带有relative position的父元素,尽管它们像我一样使用了绝对定位。
这个例子在这里:http://purecssmenu.com/ 所以我尝试删除我的relative定位,问题就解决了。然而,现在我正在使用绝对定位,而没有使用relative定位的任何父元素,它们都设置为static
所以我想知道这是否合理-没有relative的父元素,它不会回退到浏览器窗口吗?
如果需要,这是我的HTML:
    <div class="navWrapper">
        <div class="left"></div>
        <div class="nav">
            <ul>
                <li class="home"><a href="/">Home</a></li>
                <li class="spacer"></li>
                <li class="about"><a href="about_us/">About Us</a></li>
                <li class="spacer"></li>
                <li class="trademark"><a href="freetrademarksearch/">Free Trademark Search</a></li>
                <li class="spacer"></li>
                <li class="services">
                    <a href="services/">Services</a>
                    <ul class="sub">
                        <li><a href="">Trademark Search</a></li>
                        <li><a href="">Prepare &amp; File Trademark</a></li>
                        <li><a href="">Trademark Infringement</a></li>
                    </ul>
                </li>
                <li class="spacer"></li>
                <li class="testimonials"><a href="testimonials/">Testimonials</a></li>
                <li class="spacer"></li>
                <li class="more"><a href="javascript:void(0);">More Information</a></li>
                <li class="spacer"></li>
                <li class="contact"><a href="contact-us/">Contact Us</a></li>                 
            </ul>
            <div class="contentClear"></div>
        </div>
        <!-- Nav Ends -->
        <div class="right"></div>
    </div>
    <!-- Nav Wrapper Ends -->

CSS:

#header .navWrapper {
    width: 1004px;
}

#header .navWrapper .left {
    float: left;
    width: 4px;
    min-width: 4px;
    height: 47px;
    min-height: 47px;
    background: url('../images/nav-left-bg.png') left top no-repeat;
}

#header .navWrapper .nav {
    float: left;
    width: 994px;
    border-top: 1px solid #e0d0b4;
    border-left: 1px solid #e0d0b4;
    border-right: 1px solid #e0d0b4;
    border-bottom: 1px solid #e8dcc8;
    background: url('../images/nav-button-bg.png') left top repeat-x;
}

#header .navWrapper .nav ul {
    margin: 0 1px;
    display: block;
}

#header .navWrapper .nav li {
    float: left;
    display: block;
    height: 45px;
    font-family: OpenSansBold, Arial;
    font-size: 16px;
    line-height: 2.9;
    text-align: center;
    color: #646464;
}

#header .navWrapper .nav li.spacer {
    width: 2px;
    min-width: 2px;
    height: 45px;
    min-height: 45px;
    background: url('../images/nav-button-spacer-bg.png') left top no-repeat;
}

#header .navWrapper .nav li a,
#header .navWrapper .nav li a:visited
{
    display: block;
    height: 45px;
    padding: 0 20px;
    color: #646464;
    text-decoration: none;
}

#header .navWrapper .nav li a:hover,
#header .navWrapper .nav li a:active,
#header .navWrapper .nav li a:focus
{
    color: #fff;
    background: url('../images/nav-button-bg.png') left bottom repeat-x;
}

#header .navWrapper .nav li.home {
    max-width: 86px;
    text-indent: -1px;
}

#header .navWrapper .nav li ul.sub {
    position: absolute;
}

#header .navWrapper .nav li ul.sub li {
    float: none;
    display: block;
    font-family: OpenSansSemibold, Arial;
    font-size: 14px;
    line-height: 2.3;
    height: auto;
    text-align: center;
    background-color: #f4771d;
    color: #fff;
}

#header .navWrapper .nav li ul.sub li a,
#header .navWrapper .nav li ul.sub li a
{
    color: #fff;
    height: auto;
}

#header .navWrapper .nav li ul.sub li a:hover,
#header .navWrapper .nav li ul.sub li a:focus,
#header .navWrapper .nav li ul.sub li a:active
{
    background: #d66627;
}

#header .navWrapper .right {
    float: right;
    width: 4px;
    min-width: 4px;
    height: 47px;
    min-height: 47px;    
    background: url('../images/nav-right-bg.png') left top no-repeat;
}

请查看我的最新更新,其中展示了您如何查看http://purecssmenu.com/在`:hover`时将`position:relative`应用于父级`<ul>`的情况。 - Faust
好的,我明白了,但我认为你是指父级<li>,而不是<ul>。 :) - Brett
1
我知道了。这能正常工作是因为虽然你在列表上设置了 position:absolute,但你没有定义任何 topleftbottomright 属性。这些属性 不会 默认为 0。当未指定 topbottom 时,元素的垂直位置与其在流中仍然存在时的位置相同。leftright 也是如此,水平定位也是如此。尝试将其中任何一个属性设置为 0px,你就会明白我的意思。 - Faust
在您的情况下,设置 position:absolute 是必要的,因为它将子菜单从流中移除,使得容器 li 可以保持由菜单顶部的文本计算出的宽度,而该容器 li 没有指定宽度。而如果您在子列表上使用了 position:relative,则其宽度会强制包含 li 扩大,导致 "联系我们" 项目跳到下一行。 - Faust
2个回答

19

如果一个元素的定位通过 relativeabsolutefixed(不一定是 relative,而是除默认值 static 以外的任何值)定义,则它会回退到最近的具有定位属性的祖先元素。

一般来说,您希望根据父元素建立的网格将项目绝对定位。然而,有时将其定位到上层元素建立的网格是合理的。

例如:

HTML

<body>
    <div id="div1">
        <div id="div2-A">[some content]</div>
        <div id="div2-B">
            <div id="div3">[more content]</div>
        </div>
    </div>
</div>

CSS

#div1{
    width:1024px;margin:auto;
    position:relative
}
#div3{
    position:absolute;
    bottom:0px; left:0px;
}
在这种情况下,div3会定位到其祖先元素div1的最左下角,因为它的直接父元素(div2)具有默认的position:static,因此不会为其子元素建立绝对定位上下文/网格。但是div3不一定会到达视口或页面正文的最左边,因为更高层次的元素div1的位置被定义为relative。
更新: 在您提供的示例中(http://purecssmenu.com/),position:relative声明被应用于:hover伪类,因此您在Google开发者工具或Firebug中列出的样式中不会立即看到它。
您可以在Google开发者工具中检查父元素,然后在“样式”面板的右侧单击“切换元素状态”按钮(看起来像一个带有虚线边框和箭头指向其中的框),然后选中“:hover”旁边的框。我相信Firebug也有类似的功能。
您将看到将此声明添加到列表中:
ul.cssMenu li:hover { position: relative; }
这个能够起作用是因为当你不悬停在父级<li>上时,子菜单<ul>会被隐藏(使用display:none),所以它的位置无关紧要。

2
你忘记在其父元素的悬停状态下声明 ul.cssMenu li:hover { position: relative; } - Faust
@Niklas:实际上,没有理由这样做(或者可能只是为了让我们困惑!)。我只是报告http://purecssmenu.com/的人是如何做到的。 - Faust
@Faust 哈哈,那他们在我身上成功了;-) - Niklas Wulff
我在我的CSS中没有relative设置,正如你上面所看到的,但是我的菜单显示得很好。如果我像那个网站一样在父级<li>上添加relative,它会包裹文本,如果我只在hover时添加它,则会在悬停时包裹文本。这很奇怪。我猜我必须上传它让你看看。 - Brett
еҘҪзҡ„пјҢFWIWжҲ‘йҖҡиҝҮдҪҝз”Ёwhite-space: nowrapи§ЈеҶідәҶжҚўиЎҢй—®йўҳпјӣ然иҖҢпјҢжҲ‘д»Қ然дёҚйңҖиҰҒдҪҝз”ЁrelativeпјҢдҪ еҸҜд»ҘеңЁиҝҷйҮҢзңӢеҲ°пјҡhttp://www.condorstudios.com/stuff/temp/ - Brett
显示剩余3条评论

2

关于元素定位时最近祖先的另一个注意事项。

在 OP 三年后,CSS3 属性如 transform 被更广泛地使用,它隐式地创建了一个新的包含块,强制使元素具有 position: relative/absolute;

因此,为了确保中间父元素不影响子元素的定位,您需要检查它是否具有 position: static 和没有设置任何transforms

示例

    <div id="one">
      <div id="two">
        <div id="three"></div>
      </div>
    </div>

    #one {
      position: relative;
    }
    #two {
      position: static;
      transform: none;
    }
    #three {
      position:absolute;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接