定位:绝对定位和父元素的高度?

158

我有一些容器,它们的子元素只使用了绝对/相对定位。如何设置容器的高度才能让它们的子元素都在容器内?

以下是代码:

HTML

<section id="foo">
    <header>Foo</header>
    <article>
        <div class="one"></div>
        <div class="two"></div>
    </article>
</section>    

<div style="clear:both">Clear won't do.</div>
<!-- I want to have a gap between sections here -->

<section id="bar">
    <header>bar</header>
    <article>
        <div class="one"></div><div></div>
        <div class="two"></div>
    </article>
</section>  

CSS

article {
    position: relative;
}

.one {
    position: absolute;
    top: 10px;
    left: 10px;
    background: red;
    width: 30px;
    height: 30px;
}

.two {
    position: absolute;
    top: 10px;
    right: 10px;
    background: blue;
    width: 30px;
    height: 30px;
}

这里有一个jsfiddle代码。我希望"bar"文本出现在4个正方形之间,而不是在它们后面。

http://jsfiddle.net/Ht9Qy/

有什么简单的解决方法吗?

请注意,我不知道这些子元素的高度,并且无法为容器设置 height: xxx。


1
可能是使绝对定位的div扩展父div高度的重复问题。 - Syed
8个回答

109

2022更新。本回答已经有近10年的历史了,在编写此回答时,我们没有可用的Flex或Grid等布局技术(它们是黑暗而有趣的时代)。

值得庆幸的是,现在情况已经大大改善。Jöcker的答案展示了如何使用Grid实现此布局。如果你可以接受不支持旧浏览器的情况,那么就用Grid吧!


原始回答

如果我正确理解你的意图,那么在保持子元素绝对定位的同时,使用CSS无法实现此效果。

绝对定位的元素完全脱离文档流,因此它们的尺寸不能改变其父元素的尺寸。

如果你确实必须在使子元素为position:absolute的同时实现此效果,那么可以通过JavaScript找到渲染后的绝对定位子元素的高度,并使用该高度设置父元素的高度。

或者,只需使用float:left/float:right和margin即可获得相同的定位效果,同时使子元素保持在文档流中,然后您可以在父元素上使用overflow:hidden(或任何其他清除浮动的技术)来导致其高度扩展到其子元素的高度。

article {
    position: relative;
    overflow: hidden;
}

.one {
    position: relative;
    float: left;
    margin-top: 10px;
    margin-left: 10px;
    background: red;
    width: 30px;
    height: 30px;
}

.two {
    position: relative;
    float: right;
    margin-top: 10px;
    margin-right: 10px;
    background: blue;
    width: 30px;
    height: 30px;
}

对于那些碰巧跌入这里的人,试图弄清为什么您的margin-left: -16px和overflow: hidden技巧不起作用。我没有考虑到我也有右边填充,所以我需要margin-right: -16px。此外,我使用了容器的width: 100vw,不知道是否需要。 - TeemuK

41

这是我的解决方法,
在你的例子中,你可以添加第三个元素,其中包含与.one和.two元素相同的"相同样式",但没有绝对定位,并且具有隐藏的可见性:

HTML

<article>
   <div class="one"></div>
   <div class="two"></div>
   <div class="three"></div>
</article>

CSS

.three{
    height: 30px;
    z-index: -1;
    visibility: hidden;
    width:0!important; /* if you got unnecessary horizontal scroll*/
}

简而言之,需要一个内容的克隆体,使其产生相同的高度。 - Kalnode

33

你可以使用网格来实现:

article {
    display: grid;
}

.one {
    grid-area: 1 / 1 / 2 / 2;
}

.two {
    grid-area: 1 / 1 / 2 / 2;
}

3
你真是个天才!谢谢!这似乎是在不设置固定值的情况下保持绝对定位元素高度的唯一方法。太妙了。 - Kashkashio
这是否也允许文章的父元素保持高度?我在尝试将其传递给DOM树上的2个父级时遇到了问题,以保持大小。即使是文章上面的1个父级似乎也很困难。在我的情况下,除了文章外没有其他额外的元素。 - SimbaClaws
1
我的用例稍有不同:我需要一个重叠效果,所以对于任何遇到问题的类似用例的人来说,这个CSS可以替代定位...请在此处查看更新的示例:https://jsfiddle.net/6xv4c1sa/ - undefined
在这种情况下,如果你喜欢简短的符号表示法,我认为你可以使用grid-area: 1 / -1; - undefined

4
这是一个晚回答,但通过查看源代码,我注意到当视频为全屏时,“mejs-container”元素会增加“mejs-container-fullscreen”类。因此,可以基于这个类更改样式。
.mejs-container.mejs-container-fullscreen {
    // This rule applies only to the container when in fullscreen
    padding-top: 57%;
}

此外,如果你想使用CSS让你的MediaElement视频更加流畅,以下是由Chris Coyier提供的一个很棒的技巧:http://css-tricks.com/rundown-of-handling-flexible-media/。只需将以下内容添加到你的CSS中即可:
.mejs-container {
    width: 100% !important;
    height: auto !important;
    padding-top: 57%;
}
.mejs-overlay, .mejs-poster {
    width: 100% !important;
    height: 100% !important;
}
.mejs-mediaelement video {
    position: absolute;
    top: 0; left: 0; right: 0; bottom: 0;
    width: 100% !important;
    height: 100% !important;
}

我希望这有所帮助。

1

article {
    position: relative;
   
}

//clear the float

article::after{
  content: '';
  clear: both;
  
}

.one {
    position: relative;
    float:left
    margin-top: 10px;
    margin-left: 10px;
    background: red;
    width: 30px;
    height: 30px;
}

.two {
    position: relative;
    float: right;
    margin-top: 10px;
    margin-right: 10px;
    background: blue;
    width: 30px;
    height: 30px;
}


1
现在可以使用flexbox解决这种布局问题,避免了需要知道高度或使用绝对定位或浮动来控制布局的需求。OP的主要问题是如何让父元素包含未知高度的子元素,并希望在特定布局内完成。将父容器的高度设置为“fit-content”可以实现此目的;使用“display:flex”和“justify-content:space-between”可以产生我认为OP试图创建的部分/列布局。
<section id="foo">
    <header>Foo</header>
    <article>
        <div class="main one"></div>
        <div class="main two"></div>
    </article>
</section>    

<div style="clear:both">Clear won't do.</div>

<section id="bar">
    <header>bar</header>
    <article>
        <div class="main one"></div><div></div>
        <div class="main two"></div>
    </article>
</section> 

* { text-align: center; }
article {
    height: fit-content ;
    display: flex;
    justify-content: space-between;
    background: whitesmoke;
}
article div { 
    background: yellow;     
    margin:20px;
    width: 30px;
    height: 30px;
    }

.one {
    background: red;
}

.two {
    background: blue;
}

我修改了原作者的代码: http://jsfiddle.net/taL4s9fj/

关于flexbox的css技巧: https://css-tricks.com/snippets/css/a-guide-to-flexbox/


“fit-content” 是解决这个问题的方法! - SwankyLegg
嗯,实际上OP是在使用position:absolute时寻求解决方案,这也是我们许多人所关注的。 - Kalnode

-1

使用样式 position:absolute 设置元素的位置,top: 0, bottom: 0


欢迎来到SO!请先看看其他人已经给出的答案。你的方法已经被提到了。为了保持网站清晰,方便找到答案,我们尽量避免重复回答。 - ahuemmer

-20
这是另一个晚回答,但我找到了一个相当简单的方法将“bar”文本放置在四个正方形之间。这里是我所做的更改; 在bar部分,我使用center和div标签包装了“bar”文本。
<header><center><div class="bar">bar</div></center></header>

在CSS部分,我创建了一个名为“bar”的类,该类用于上面的div标记。添加后,条形文本位于四个彩色块之间的中心位置。
.bar{
    position: relative;
}

25
请不要使用<center>标签!该标签已被弃用。 - Ian Devlin
25
自HTML4(公元1997年)以来。 - frzsombor

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