【问题标题】:How can I prevent an absolutely positioned element from breaking within CSS columns?如何防止绝对定位的元素在 CSS 列中中断?
【发布时间】:2016-11-22 15:40:12
【问题描述】:

我有一个使用 HTML 和 CSS 的 2 列布局。在这些列中,我有一个选择菜单,当单击这些列表项之一时将显示该菜单。我需要相对于单击的项目定位此选择菜单,并且不影响它周围元素的布局,就像传统的选择选项菜单一样。但是,我不能使用传统的选择,因为这是一个自动提示输入/菜单。因此,我在其相对定位的父项中为菜单容器使用了绝对定位项。

我想要什么:

我的问题是绝对定位的项目正在破坏,就好像它是列的一部分一样。这违背了我对position: absolute 的理解,但它似乎是within spec。更令人沮丧的是,浏览器按我的意愿显示绝对定位的项目(只要我没有在父级上设置position: relative),但我需要在父级上设置position: relative,或者选择菜单(作为绝对定位的项目)不会总是显示与其对应的元素相邻。

我得到了什么:

我也尝试了使用 flexbox 的列式布局,但是这样,项目从左到右显示,当我需要它们按顺序从上到下显示时,就像在传统的列式布局中一样。我可以将 flexbox 与flex-flow: column wrap 一起使用,但这需要我知道/设置容器元素的高度,这是我做不到的。 CSS 列很好地包裹了列表,无需设置高度。

我认为最简单的解决方案是以某种方式伪造绝对定位或让 flexbox 按顺序(从上到下)显示项目,而无需在容器上明确设置高度。这两种我都试过了,都没有令人满意的结果。我愿意使用 JavaScript 解决方案,但我会尽力避免它并仅使用 CSS 解决此问题。

.columns-two {
  column-count: 2;
  column-width: 300px;
  -moz-column-count: 2;
  -moz-column-width: 300px;
}
.parent {
  -webkit-column-break-inside: avoid;
  page-break-inside: avoid;
  break-inside: avoid;
  position: relative;
}
.highlight {
  background-color: #FFF8DC;
}
.absolute-element {
  width: 200px;
  position: absolute;
  background: #ffffff;
  border: 1px solid #cccccc;
  padding: 15px;
  -webkit-column-break-inside: avoid;
  page-break-inside: avoid;
  break-inside: avoid;
}
<ul class="columns-two">
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li class="parent highlight">item that shows selectmenu
    <div class="absolute-element">This is an absolute element. This is an absolute element. This is an absolute element. This is an absolute element. This is an absolute element. This is an absolute element. This is an absolute element. This is an absolute element.This is an absolute
      element. This is an absolute element. This is an absolute element. This is an absolute element.</div>
  </li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
</ul>

Here is a codepen 用一个例子来说明我的问题。从 HTML 中移除父类以查看预期的绝对定位项(注意,这有时会导致定位不正确)。

【问题讨论】:

  • transform: translate3d(0,0,0); 被标记为已接受的答案,但是当我对此进行测试时,它似乎仍然保留了原始布局,但只是隐藏了右侧包裹的多余部分。你找到解决方案了吗?

标签: html css css-position css-multicolumn-layout column-count


【解决方案1】:

我发现在绝对定位的元素上使用transform: translate3d(0,0,0); 可以防止其分列。

【讨论】:

  • 这个技巧只有在绝对定位元素不包含链接的情况下才有效。否则它会失败,因为仍然在(错误的)原始元素位置检测到鼠标!
【解决方案2】:

在子元素上使用backface-visibility: hidden

【讨论】:

  • 我起初对这个答案持怀疑态度,在查看the docs 之后,我更加确定它不会起作用。最终,我还是选择了它,因为我已经用尽了所有其他可能的解决方案,而且 - 你瞧 - 这就像一个魅力!如果我可以问,你是怎么知道这个的??
  • 这在 Chrome 中可以工作,但在 Safari 12.1.2 中不能更正它——即使是-webkit-backface-visibility: hidden。这个答案导致我尝试其他解决问题的方法,但是 - transform: translate3d(0,0,0); 在绝对定位的元素上。
  • @feihcsim - 我是通过反复试验发现的,就像 CSS 中的许多愚蠢的东西一样......
  • 不适用于 MS Edge。在 Firefox 上正常。
【解决方案3】:

只需将position:relative 设置为ul,并根据需要将子菜单放置在属性边距上。

【讨论】:

    【解决方案4】:

    您是否可以将&lt;li&gt; 设置为position: relative;,并且选择菜单绝对位于&lt;li&gt; 内? AFAIK 这是实现这种效果的标准方法。

    然后:

    .selectMenu {
        position: absolute;
        top: /* height of li element */;
        left: 0;
    }
    

    【讨论】:

    • 在codepen示例和我的实际项目中,
    • 是具有相对定位的父元素。如您所见,设置 topleft 值并不能防止绝对定位的元素在列中中断。
  • 啊,抱歉。我想不出一个自然的解决方案,我要么使用一些 javascript 来定义正确的位置,要么放弃 CSS 列。
  • 这可能是我必须做的......或者只是使用 flexbox 并接受从左到右的顺序。但我仍然希望这里可能有人遇到类似问题并可以提供一个聪明的 CSS 解决方案。
  • 这似乎很简单,但这是在考虑 CSS 列之前。希望有人可以提供直接的解决方案。
  • 猜你喜欢
    相关资源
    最近更新 更多
    热门标签