CSS:将绝对定位的div置于父级div上方

3

我想要将一个DIV绝对定位在顶部(top: 0)。在这张图中,黄色的div (#menu) 就是我们需要处理的。

以下是我的HTML代码:

<html>
    <head>
        <link rel="stylesheet" type="text/css" href="style.css">
    </head>
    <body>
        <div id="container_head">
            &nbsp;
        </div>
        <div id="container_body">
            <div id="main">
                <div id="menu">
                    &nbsp;
                </div>
                <div id="content">
                    &nbsp;
                </div>
            </div>
            <div class="clear"></div>
        </div>
        <div id="container_foot">
            &nbsp;
        </div>
    </body>
</html>

以及CSS:

#container_head {
    width: 100%;
    background-color: #00F;
    z-index: 10;
}
#container_body {
    width: 100%;
}
#container_foot {
    width: 100%;
    background-color: #F00;
}
#main {
    width: 960px;
    margin: 0 auto;
    position: relative;
}
#menu {
    background-color: rgba(255,255,0,0.5);
    width: 170px;
    padding: 10px;
    float: left;
    position: absolute;
    top: 0;
    z-index: 100;
}
#content {
    background-color: #0F0  ;
    width: 750px;
    padding: 10px;
    float: right;
}
.clear {clear: both;}

然而,黄色的div不会出现在y位置0。 这里是代码片段更新 谢谢回答。我仍然处于困惑中。对于每个用户来说,#container_head 的高度都不一样。它是一个响应式幻灯片。此外,我需要#menu位于与#main相同形状的区域的左侧,因此它可以插入到#content旁边。

2
你可以将#main的position属性设置为relative。 - webkit
你能否安全地假设你不能修改HTML,只能修改CSS? - Jon Surrell
1
这个线程太疯狂了。而且,初始代码很差:1)块设置为100%的宽度,2)z-index设置在非定位元素上,3)使用标记清除浮动,4)命名约定很奇怪(为什么不使用标题标签或将div称为#header),5)HTML结构很糟糕。关于后者,如果#menu的位置受到#container_header的影响,则应该将其放在其中。这是一个好方法:#main相对定位。为什么?它内部唯一的绝对块是#menu,它需要与#container_header或body相关联。大拇指向下! - DRD
@DRD 我同意。看起来OP尝试了许多不同的方法,但在它们无效时并没有将它们删除。我很想看到这段代码在http://codereview.stackexchange.com/上,那里我们可以询问原始意图并尝试重新开始。对于这个问题,我觉得做一个大规模的代码重写对OP没有帮助(虽然有些答案已经这样做了),所以我只是使用他的fiddle并进行了最小化的更改。至少我删除了一个导致问题的css行,并尝试使其在container_head更改边距时正常工作。 - Guy Schalnat
10个回答

7

#menu#main内部。并且#mainposition: relative;,意味着它已经"定位"了。绝对定位的元素是相对于最近的定位父级进行定位的。因此,#menu上的top: 0;是相对于#main顶部的零点,而不是文档的顶部。

您可以通过以下几种方式解决此问题:

  1. #menu移出#main
  2. 不要将#main定位为相对位置(这会影响#main内部任何绝对定位的元素,因此请小心)
  3. #container_head一个固定高度,然后将#menu的顶部设置为例如-30px
  4. #menu设置为position: fixed;(这将使其相对于视口而不是文档定位,因此它将不再随文档滚动。这可能是需要的,也可能不是。此外,在兼容模式下,IE 6或IE 7无法使用position: fixed。)

非常感谢 @gwcoffey。我已经在我的问题底部添加了一个更新。 - user3698285

1
我拿了你的小提琴并做了两个修改。首先,我将#menu放在#container_head内部,其次,我从#menu css中删除了top: 0;。请查看http://jsfiddle.net/J9E47/
<body>

    <div id="container_head">
        <div id="menu">
                &nbsp;
            </div>
        &nbsp;
    </div>
    <div id="container_body">
        <div id="main">

            <div id="content">
                &nbsp;
            </div>
        </div>
        <div class="clear"></div>
    </div>
    <div id="container_foot">
        &nbsp;
    </div>
</body>

并且

#container_head {
width: 100%;
background-color: #00F;
z-index: 10;
}
#container_body {
width: 100%;
}
#container_foot {
width: 100%;
background-color: #F00;
}
#main {
width: 960px;
margin: 0 auto;
position: relative;
}
#menu {
background-color: rgba(255,255,0,0.5);
width: 170px;
padding: 10px;
float: left;
position: absolute;
z-index: 100;
}
#content {
background-color: #0F0  ;
width: 750px;
padding: 10px;
float: right;
}
.clear {clear: both;}

1
在阅读完这个帖子、您的评论和更新的问题之后,似乎您不想改变标记和布局。考虑到这一点,让我们只修复样式以适应您现有的标记。
在继续之前,请查看此演示:
演示:http://jsfiddle.net/abhitalks/2fYGj/6/ 我们需要理解一些问题并逐一解决它们。
(1.) 您在容器上使用百分比宽度,在子元素上使用像素宽度。在您的问题中,您指出容器特别是标题需要响应。我建议对整个布局使用相同的单位,即为所有布局组件使用百分比宽度。
(2.) 您已经对某些元素应用了填充和边距,如果您没有正确的box-sizing模型,则会导致宽度问题。
让我们解决这两个问题:
我们向您的CSS添加了最小重置。
* {
    margin: 0; padding: 0; box-sizing: border-box;
}

我们现在将百分比宽度应用于所有元素:
#main {
    width: 100%;
    ...
}
#menu {
    width: 10%; /* within 100% of parent i.e. main */
    ...
}
#content {
    width: 70%; /* within 100% of parent i.e. main */
    ...
}

现在让我们看看其他问题:

(3.) 你在 container_headcontainer_bodycontainer_foot 上使用了百分比宽度。100% 宽度是相对于什么而言?它是相对于父元素的宽度。因此,为了保险起见,我们还需要将宽度应用于 html,body

我们可以通过在 CSS 中添加以下内容来解决这个问题:

html, body {
    width: 100%;
}

(4.) 你将你的#menu绝对定位了。现在,绝对定位意味着将元素从流中取出并使其相对于最近的相对定位父元素定位。如果没有这样的父级,则它将相对于body定位。在你的情况下,它的直接父级即#main是相对定位的,因此菜单试图相对于#main定位。但是,这不是你想要的。你希望它相对于#container_head定位。但是#container_head不在其父级层次结构中。(而且你不想更改你的标记),否则添加一个包装器就可以解决这个问题。
因此,我们通过去掉#main上的position:relative来解决这个问题:
#main {
    ...
    /* position: relative;  <-- Remove positioning from main */
}

这将强制#menu相对于页面定位。这会引入另一个问题,即如果#container_head应用了margin-top,则菜单将向上拉。为了缓解这个问题,您需要在#menu上应用一个等于#container_headmargin-toptop。(可以通过此演示最好地理解:http://jsfiddle.net/abhitalks/LbRKb/(5.)您需要使#menu#content对齐。而#menu是绝对定位的。绝对定位意味着它不在流中,因此您现在在菜单和内容上的float就毫无意义了。
我们通过为菜单和内容分配百分比边距来解决它:
#menu {
    width: 10%; 
    top: 0; left: 10%; /* whatever indent you want from left */
    /* float: left <-- not required now */
    ...
}
#content {
    width: 70%;
    margin-right: 10% /* right margin equal to left pos of menu */
    margin-left: 20%; /* left margin equal to left pos of menu + menu width */
    /* float: right <-- not required now */
    ...
}

因为您的菜单现在是绝对定位的,如果#content中没有或很少内容,则其高度可能超过#main。在这种情况下,它将重叠到页脚中甚至超出页面。

我们通过为#menu#main分配最小高度,并确保main的高度大于menu的高度来解决此问题:

#main {
    min-height: 200px; /* must be more than that of menu */
    ...
}
#menu {
    min-height: 100px;
    ...
}

.

好的,现在您拥有一个与您发布的图示完全相似的布局。

更新(根据 Op 的评论):

为了使用 max-width 来约束菜单和内容大小,上述方法将会打破 Op 在下面评论中提到的菜单和内容之间的间隙。

修复这个问题很容易。诀窍是在 #menu 上使用 right 而不是 left

演示 3: http://jsfiddle.net/abhitalks/2fYGj/17/ 演示 3(全屏):http://jsfiddle.net/abhitalks/2fYGj/17/embedded/result/

希望对您有所帮助。

.


厉害了,abhitalks。你做得太棒了! - user3698285
我想将所有内容保持在最大宽度以下。因此,我给了#menu {max-width: 229px;}#content {max-width: 850px;}。你可能会想象这破坏了大屏幕上的布局。请参见此处。我如何使布局更紧凑? - user3698285
是的。这个设计不是响应式的,因为你必须根据菜单的宽度和位置计算内容的左边距。唯一的解决办法就是不强制最大宽度。 - Abhitalks
有没有其他方法可以构建布局,但确保有最大宽度? - user3698285
1
@SR7:再想一想,我试了一下。诀窍是在#menu上使用right而不是left(请参见此Fiddle),以及(查看全屏)。已添加到答案中。 - Abhitalks

0

在我的示例中,我将所有的ID更改为类,因为通常情况下覆盖类比覆盖ID要容易得多。不过,除了我添加的包装器之外,您的结构是相同的。请参见我的Pen:http://codepen.io/mofeenster/pen/jLJhw

只需简单地更改您使用相对定位的位置即可。要使用绝对定位使菜单到达顶部,您需要使用我添加的包装div。您可以通过哪些div是相对和绝对来操纵元素移动到任何位置。

这方面的另一个示例是我为类似目的创建的另一个笔记,请在此处查看:http://codepen.io/mofeenster/pen/nErks

我认为这回答了您提出的所有问题。


0
针对元素#main,移除position:relative;

0
这是一个非常快的小工具 [http://jsfiddle.net/tL55Y/][1]。你需要重新调整你的结构,看看这是否能帮到你。谢谢。

非常感谢你,Vaibhav。我已经在我的问题底部添加了一个更新。 - user3698285

0
如gwcoffey所解释的那样,绝对定位的元素是根据其直接父元素定位的。您无法通过当前的结构获得您要查找的行为。
以下是替代结构的示例:

演示

让我解释一下更改:
  1. 添加一个容器,覆盖你的三个部分 container_head、container_body 和 container_foot。确保这个容器得到 position: relative;

    <div class="container"></div>
    

    注意,你不需要在它们周围建立一个容器,但如果你没有建立一个容器,你需要做一些非常小的更改来考虑默认的 body 边距。你仍然需要以下点的结构,只是没有外部的 div

  2. 使你的菜单位于相对定位元素的下一级,并且与 #container_head 处于同一级别,通过简化你的 #container_body 为只有 #menu#content

    <div class="container">
      <div id="container_head"></div>
      <div id="menu"></div>
      <div id="content"></div>
      <div id="container_foot"></div>
    </div>
    
现在,有了这个结构,您可以更加灵活地编写简单的标记。由于定位将使菜单脱离页面流程,因此您需要通过应用至少菜单左右边距+左右填充+宽度的边距来偏移内容的位置。

0
首先,当你将元素的定位设置为绝对定位时,它不会被视为一般布局的一部分,并且在定位其他 div 时将被忽略。因此,如果你想要对 #content 和 #menu 进行对齐,你需要手动设置一个与 #menu 的宽度和内边距相等的 margin 在 #content 中:
#content {
    background-color: #0F0  ;
    width: 750px;
    padding: 10px;
    margin-left: 190px; /* Allow space for #menu considering its padding */
    /* Floating is not necessary for this. */
}

第二点,position: absolute会将div相对于最近的带有position: relative属性的父元素进行定位。因此,在您的情况下,#menu将相对于#main进行定位。您需要做的是从#main中删除position: relative,以便#menu相对于其下一个最近的父元素body进行定位。

#main {
    width: 960px;
    margin: 0 auto;
}

最后,当使用绝对定位时,浮动没有意义,因此您可以从#menu中删除它。
#menu {
    background-color: rgba(255,255,0,0.5);
    width: 170px;
    padding: 10px;
    position: absolute;
    top: 0;
    z-index: 100;
}

以下是完整的 CSS:

#container_head {
    width: 100%;
    background-color: #00F;
    z-index: 10;
}
#container_body {
    width: 100%;
}
#container_foot {
    width: 100%;
    background-color: #F00;
}
#main {
    width: 960px;
    margin: 0 auto;
}
#menu {
    background-color: rgba(255,255,0,0.5);
    width: 170px;
    padding: 10px;
    position: absolute;
    top: 0;
    z-index: 100;
}
#content {
    background-color: #0F0;
    width: 730px;
    padding: 10px;
    margin-left: 190px;
}
.clear {clear: both;}

这里是 JsFiddle


“position: relative” 是 CSS 中最令人困惑的属性。你的问题主要与它的正确使用有关。 - Can Bayburt

0

我已经更新了你的代码,这可能是你问题的答案:

http://jsfiddle.net/2fYGj/7/

我已经将 div.container_headdiv.container_body 包裹在另一个 div 中:

<body>
<div>
  <div id="container_head"><!-- Contents --></div>
  <div id="container_body"><!-- Contents --></div>
</div>

<div id="container_foot">
</div>
</body>

对于 CSS 部分,我已经移除(注释掉)了 #main 的位置:

#main {
  width: 960px;
  margin: 0 auto;
  /*position: relative;*/
}

还有一些新添加的div的样式:

body > div {
    position: relative;
}

0

position: absolute的元素总是相对于最近的具有position: absoluteposition: relative设置的包含元素定位。这就是为什么你的#menu div固定在你的#main div顶部的原因,正如许多之前的帖子建议的那样,简单地#main中删除position: relative可以让#menu脱离顶部。此外,要将其固定在#container_head的顶部,请添加

body {
  position: relative;
}

这不会影响宽度计算,因此您的菜单位于内容左侧。


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