【问题标题】:absolute in relative: adapt position without size相对中的绝对:适应没有大小的位置
【发布时间】:2018-11-30 04:54:35
【问题描述】:

如果这是一个骗局,那么抱歉,但我没能找到它。

我有一个绝对定位的元素,它的大小当前基于其内容:当前情况下的要求。但是,它也直接设置在其父级的右侧,而它需要在其正下方。 为了将绝对元素设置在其父元素下方,我设置了它的左侧和顶部,并使父元素相对定位。但是,当我这样做时,绝对元素采用其父元素的宽度(非常小)。我真的需要绝对元素根据其(通常是动态的)内容来定义自己的宽度。

有没有一种有效的方法可以将绝对元素设置为刚好在其父元素之下,同时让其打开以根据其内容调整大小?

编辑:

Here's 用于演示问题的 jsfiddle 链接。

这里是html:

<div id='menu'>
    <span class='menuItem'>
        <span class='menuItemTitle'>
            Item 1
        </span>
        <div class='menuItemContent'>
            test1 test1 test1 test1<br/>
            testing testing, one two three<br/>
            Anyone there?
        </div>
    </span>
    <span class='menuItem'>
        <span class='menuItemTitle'>
            Item 2: extra wide
        </span>
        <div class='menuItemContent'>
            test2 test2 test2 test2
        </div>
    </span>
</div>

这是 CSS:

#menu
{
    background-color: blue;
    width: 100%;
}
.menuItem
{
    padding: 0 1em;
    //position: relative;
}
.menuItemTitle
{
    background-color: yellow;
}
.menuItemContent
{
    background-color: green;
    display: none;
    position: absolute;
    z-index: 100;
}
.menuItem:hover .menuItemContent
{
    display: inherit;
}

默认情况下,它显示没有相对父级的绝对元素。这允许元素的内容定义其宽度。 如果您转到“.menuItem”样式并取消注释它的位置,那么绝对元素会被压扁。

【问题讨论】:

    标签: html css position absolute


    【解决方案1】:

    一个绝对定位的元素默认是内容大小的,除非你设置它的两边(例如“left”和“right”),或者明确设置它的宽度。

    因此,如果您的绝对定位元素的大小相对于父元素,则您必须执行上述操作之一。一个很好的测试方法是使用检查器,例如Firefox 或 Chrome,查看计算的 CSS,并查看它是否包含上述内容之一。您还可以通过在元素上设置right: auto;width: auto; 来强制阻止这些情况。

    一个小问题是它仍然会从其父级继承断行规则。为了防止这种情况,只需将其宽度设置为一个非常大的数字,例如 1000000px。这将防止换行,但也会使其中任何相对大小的元素过大。但是,后者不是技术问题:相对大小的元素必须相对于 something 来调整大小,因此您要么将其保留为相对于父对象,要么避免在直接子对象中使用相对大小绝对定位的元素。

    如果您需要内容大小的边框,只需将另一个 div 放在绝对定位的元素中,使其绝对定位或浮动,并给它一个边框。

    如果你想混合大小相对大小的元素和不大小的元素,允许绝对定位的元素相对于父元素调整大小,但同时,包装不应该被包装的单个元素/段落具有极宽的 div。

    如果您希望绝对定位的元素相对于父级的父级调整大小,则根本不要使其绝对定位。相反,使用浮点数,并使其成为父级的直接子级。例如,这是我用来制作内容大小侧边栏的技巧:

    <div id="parent" style="float: left; width: 100%; clear:both"><!-- Float parent -->
        <div id="sidebar" style="float: left">
            Dynamic content
        </div>
        <div id="main_content_position" style="float: left"><!-- Extra div to set the position right of the sidebar -->
            <div id="main_content" style="width: 100%"><!-- Inner div with 100% width forces the position div to grow as large as it can, minus the size of the sidebar -->
                My content
            </div>
        </div>
    </div>
    <div id="clear_after" style="clear:both"></div><!-- Clear after the floating parent. We don't want it to actually float -->
    

    请注意,这种方法远非完美。它需要使用严格模式(&lt;!DOCTYPE html&gt;),如果你使用 RTL,你将需要在 Firefox 上至少多出一个 div,并与overflow:visibleoverflow:hidden 混淆,否则自动换行会被破坏.

    一般来说,让侧边栏具有静态宽度是个好主意,然后使用旧的浮动和边距技巧:

    <div id="parent" style="width: 100%">
        <div id="sidebar" style="float: left; width: 150px">
            Static content
        </div>
        <div id="main_content" style="margin-left: 150px">
            Dynamic content
        </div>
    </div>
    

    更新:它在 JSFiddle 中被“压扁”的原因是因为在这种情况下“内容大小”是基于最大的单词。显然,您想要的是它根本不引入换行符。

    (另外,你在一个不完全有效的范围内放置了一个 div,但我会让它通过)

    一个部分可行的解决方案是增加 div 的宽度并使用内部 div,正如我之前提到的:

    <div class='menuItemContent'>
        <div class='menuItemContentInner'>
            test1 test1 test1 test1<br/>
            testing testing, one two three<br/>
            Anyone there?
        </div>
    </div>
    

    并添加 CSS:

    .menuItemContent
    {
        display: none;
        position: absolute;
        left: 0;
        top: 1em;
        z-index: 100;
        width: 10000px;
    }
    .menuItemContentInner
    {
        background-color: green;
        float: left;
    }
    

    此解决方案的缺陷在于,当您将鼠标悬停在项目上时,它会创建滚动。使用overflow:hidden 并不能解决问题,因为它还会将内容裁剪到菜单的高度。不幸的是,overflow:hidden 不可能只做一个方向。

    然而,在玩弄了提琴手之后,我最终找到了这个解决方案:

    .menuItem
    {
        padding: 0 1em;
        float: left;
    }
    .menuItemContent
    {
        background-color: green;
        display: none;
        position: absolute;
        z-index: 100;
        clear: left;
    }
    

    并在菜单末尾添加&lt;div style="clear:both"&gt;&lt;/div&gt;

    这会导致内容换行并出现在文本下方,而无需显式设置其lefttop,因此不需要在项目上设置position:relative。我已经在 Firefox、Internet Explorer 11 和 Chrome 中对其进行了测试。这实际上是一个更清洁的解决方案。

    【讨论】:

    • 感谢您的快速回复。我尝试了正确的:自动;左:自动;以及宽度:10000px。这些都没有有效地解决问题。我正在使用 jsfiddle 链接编辑我的问题,以更有效地演示该问题。
    • 甜蜜!非常感谢您检查。令人印象深刻的测试完整性。 “clear”属性似乎很有用。这是我的第一篇 stackoverflow 帖子,但我很快就会获得声誉和支持。
    • 亲爱的蛞蝓,你说“一个绝对定位的元素默认是内容大小的,除非你设置它的两边(例如“左”和“右”),或者明确设置它的宽度。”,有文件支持吗?我是 CSS 新手,想了解更多...谢谢!
    • @Eric 规范在这里定义了绝对定位块的大小:w3.org/TR/css-position-3/#abspos-auto-size 在这里:w3.org/TR/css-position-3/#abs-non-replaced-width 但是规范阅读起来可能很复杂,即使在严格模式下,也不能保证全部。在实践中,除了在多个浏览器中进行尝试之外,没有什么真正的替代品。
    【解决方案2】:

    我最近通过网站上的下拉悬停子菜单做到了这一点。我找到的解决方案是将子“绝对”元素的空白设置为“nowrap”。 在我的具体情况下:

    &.menu-item-has-children {
        position: relative;
        .sub-menu {
            position: absolute;
            li a {
                white-space: nowrap;
            }
        }
    }
    

    这允许绝对元素根据其父元素定位,但仍允许其宽度基于其比其父元素更宽的内容。

    【讨论】:

      猜你喜欢
      • 2020-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-05
      • 2014-10-06
      • 1970-01-01
      相关资源
      最近更新 更多