绝对定位的元素会发生折叠。

5

我有一些绝对定位的元素:

span {
  display: block;
}

span.sub {
  color: blue;
  position: absolute;
}
<div>
  <span>Coffee</span>
  <span class="sub">Tea</span>
  <span class="sub">Milk</span>
  <span class="sub">Water</span>
</div>

我该如何防止它们塌陷? 我想让它们自由地流动到 div 下的元素上,就像下拉式导航菜单一样。能否在不将定位元素嵌套在额外容器内的情况下实现?


绝对定位的元素不会影响其周围的任何内容,因此为它们指定尺寸不会改变其他任何东西。不将它们定位为相对位置的原因是什么? - A Haworth
@AHaworth: “不将它们定位为相对位置的原因是什么?” 我希望它们可以自由地在div下面的元素上流动,就像导航下拉菜单一样。 - user4351667
3
把它们都放入一个绝对定位的 div 中会是答案吗? - A Haworth
当然,但我想知道是否可以在不添加额外元素的情况下实现相同的效果。 - user4351667
如果您想让它们一个接一个地排列,为什么要使用绝对定位?您甚至可以通过display属性来实现这一点。 - Diwyansh
显示剩余2条评论
3个回答

6

一种方法是在父级div上使用white-space: pre;

    span {
      display: block;
    }

    span.sub {
      color: blue;
      position: absolute;
    }


    /* --------------------- */

    :root {
      /* 1em is default font size */
      --menu-bar-height: 1.3em;
    }

    body div {
      
      width: 200px;
      background-color: rgb(122, 213, 243);

      height: var(--menu-bar-height);
      white-space: pre;
    }

    span:first-child {
      margin-top: -2em;
      width: fit-content;
      background-color: rgb(48, 171, 212);
    }

    span.sub {
      margin-top: -2.4em;
    }


    /* cosmetic changes */
    .sub:hover {
      border: 2px dotted blue;
      transform: translateX(10px);
    }

    .sub:nth-child(even) {
      background-color: lawngreen;
    }

    .sub:nth-child(odd) {
      background-color: tomato;
    }

    #second {
      width: 200px;
      height: 200px;
      background-color: wheat;
      text-align: center;
      z-index: -1;
    }
<div>
  <span>Coffee</span>
  <span class="sub">Tea</span>
  <span class="sub">Milk</span>
  <span class="sub">Water</span>
  <span class="sub">Chocolate</span>
</div>
<div id="second">Div 2</div>

以下是另一种方法。在伪元素 span:before 上使用 white-space: pre; 属性,并使用计数器添加更多行。

span {
      display: block;
    }

    span.sub {
      color: blue;
      position: absolute;
    }


    /* --------------------- */

    @counter-style nuLine {
      system: symbolic;
      symbols: "\a";
    }

    body div:first-child {
      width: 200px;
      counter-reset: lines;
      background-color: lightblue;
      flex-direction: column-reverse;
    }

    span.sub {
      height: 0px;
      margin-top: -1em;
      background-color: transparent;
      mix-blend-mode: multiply;
    }

    span.sub::before {
      counter-increment: lines;
      content: counter(lines, nuLine) counter(lines) ". ";
      white-space: pre;
    }

    span.sub::after {
      content: "\00a0";
      width: 100%;
      position: absolute;
      left: 0px;
      opacity: .5;
    }


    /* cosmetic changes */
    span:first-child {
      width: 200px;
    }

    .sub:hover {
      transform: translateX(10px);
    }

    .sub:hover::after {
      border: 2px dotted blue;
    }

    .sub:nth-child(even)::after {
      background-color: lawngreen;
    }

    .sub:nth-child(odd)::after {
      background-color: tomato;
    }

    #second {
      width: 200px;
      height: 200px;
      background-color: wheat;
      text-align: center;
      padding: 0px;
      margin: 0px;
    }
<div>
  <span>Coffee</span>
  <span class="sub">Tea</span>
  <span class="sub">Milk</span>
  <span class="sub">Water</span>
  <span class="sub">Chocolate</span>
</div>

<div id="second">Div 2</div>


你的第一种方法看起来很有趣,但是如果你在页面上添加其他元素,比如另一个 div,它就不能很好地工作了。 - user4351667
添加 height 解决了这个问题。运行更新后的第一种方法代码。我希望这是您想要的行为。 - the Hutt
第二种方法已经修复了。输出看起来几乎与第一种方法相同。 - the Hutt

1
你也可以这样做。在父级 div 上应用绝对定位。这将使整个父元素绝对定位于任何其他内容之上,例如你提到的一个下拉菜单,而子元素 span 将在该元素内正常流动。

div {
  position:absolute;
}

span {
  display: block;
}

span.sub {
  color: blue;
}
<div>
  <span>Coffee</span>
  <span class="sub">Tea</span>
  <span class="sub">Milk</span>
  <span class="sub">Water</span>
</div>


那有什么意义呢?他只需从span.sub中删除绝对位置,就可以得到相同的“外观”。 - HiLuLiT
没有额外的DOM内容,你无法真正区分它们的区别,但是OP要求将列表项悬停在内容上方,就像下拉菜单一样,因此我提供了更好的解决方案。实际上已经删除了跨度的绝对定位。 - scooterlord

0
首先我们需要理解一些东西。
当我们使用position时,通常需要将父元素设置为position:relative,将子元素设置为position:absolute。
如果我们在没有在父级中使用position:relative的情况下给子元素position:absolute,则子元素将以窗口作为参考来定位,因此它们将定位在窗口的左上角,从而导致崩溃。
其次,在使用position:absolute时,我们还需要告诉子元素要在哪里使用top, bottom, left, right这些属性来确定位置。
如果不使用它们,它们将被定位在同一位置,导致崩溃。
因此,一旦解释清楚了,这是我的解决方案,我认为这不是做下拉菜单的最佳方式。
<div>
    <span>Coffee</span>
    <span class="sub">Tea</span>
    <span class="sub">Milk</span>
    <span class="sub">Water</span>
</div>

我的HTML与你想要的一样。

    div{
        position: relative;
    }
    span {
        display: block;
    }
    span.sub {
        color: blue;
        position: absolute;
    }
    span.sub:nth-child(2){            
        left: 0;
        top: 20px;
        display: none;
    }
    span.sub:nth-child(3){
        left: 0;
        top: 40px;
        display: none;
    }
    span.sub:nth-child(4){
        left: 0;
        top: 60px;
        display: none;
    }

    span:first-child:hover ~ span{
        display: block;
    }

请注意,我像之前说的那样使用了left和top

首先,我们需要父元素,也就是这个div,设置为position: relative,因为这是我们的参考点。

包含“Coffee”单词的span已经被正确定位。

然后很简单,我们需要针对每个进行定位,因为它们需要不同的位置值以避免折叠,我使用了伪类来针对它们,您也可以使用另一个类。

要在悬停时制作下拉菜单,我使用了这一行代码:span:first-child:hover ~ span{display: block;}当悬停在咖啡上时,所有的显示将更改为块以便能够看到它们。


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