如何防止绝对定位的元素影响滚动条?

Mis*_*hko 31 html css css-position overflow

考虑一个坐在容器中的autosuggest输入,其中包含一些内容和一个垂直滚动条:

在此输入图像描述

显示自动提示建议时,它们应显示在内容的顶部,而不会影响容器的滚动条.

我希望得到:

在此输入图像描述

请注意,滚动条与上面完全相同.

但是,我得到以下内容:

在此输入图像描述

请注意,滚动条会受到影响,建议会被删除.

为什么绝对定位的建议会影响容器的滚动条?

你会如何解决这个问题?

这里的游乐场

笔记:

  • 滚动容器时,输入和建议应一起移动.
  • 您可以修改HTML,但输入和建议列表应保留在内部.autosuggest(考虑.autosuggest作为第三方组件,其HTML无法更改,但您可以更改其CSS).
  • 如果有帮助,您可以使用flexbox.
  • 我正在寻找CSS唯一的解决方案.请不要Javascript.

.container {
  height: 100px;
  width: 300px;
  margin-top: 50px;
  overflow-y: auto;
  border: 1px solid black;
}
.autosuggest {
  position: relative;
  width: 250px;
}
.input {
  font-size: 16px;
  width: 230px;
  padding: 5px 10px;
  border: 0;
  background-color: #FFEBBF;
}
.suggestions {
  list-style-type: none;
  margin: 0;
  padding: 5px 10px;
  width: 230px;
  background-color: #85DDFF;
  position: absolute;
}
.content {
  width: 120px;
  padding: 5px 10px;
}
Run Code Online (Sandbox Code Playgroud)
<div class="container">
  <div class="autosuggest">
    <input class="input" type="text" value="input">
  </div>
  <div class="content">
    content content content content content content content content content content
  </div>
</div>

<div class="container">
  <div class="autosuggest">
    <input class="input" type="text" value="input">
    <ul class="suggestions">
      <li>suggestion 1</li>
      <li>suggestion 2</li>
      <li>suggestion 3</li>
      <li>suggestion 4</li>
      <li>suggestion 5</li>
      <li>suggestion 6</li>
      <li>suggestion 7</li>
      <li>suggestion 8</li>
      <li>suggestion 9</li>
    </ul>
  </div>
  <div class="content">
    content content content content content content content content content content
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

LGS*_*Son 10

  • 显示自动提示建议时,它们应显示在内容的顶部,而不会影响容器的滚动条.
  • 滚动容器时,输入和建议应一起移动.

仅使用CSS无法完成此操作.

suggestions显示在内容的顶部container,非剪辑,它必须有,position: absolute而且它的父母(autosuggestcontainer)都不能position: relative.

不利的一面是suggestions不会在滚动上移动.

suggestions使用滚动移动,其父项(autosuggestcontainer)之一需要position: relative.

与之相反的是,并且由于它container不是overflow: visible,它将被剪裁


前面已经提出,并且假设input必须是内autosuggest元素,改变了position: relativeautosuggestposition: absolute,所以input用撑suggestions上滚动,将可能是最好的,但设置z-index在每个container将需要避免重叠奇.

但是,如果的供应商的第三方组件,... :) ......,可以说成,其中一个版本,input可以放在外面autosuggest元素,我们可以得到一些更多的控制,仅使用两个CSS,suggestionscontent和他们的布局,基于if是否input有焦点,...

...这个样本可能是一个好的开始(点击input显示suggestions).

.container {
  background-color: white;
  width: 300px;
  min-height: 100px;
  margin-top: 50px;
  border: 1px solid black;
  overflow: auto;
  position: relative;
}
.autosuggest {
  position: relative;
  width: 250px;
  z-index: 1;
}
.input {
  font-size: 16px;
  width: 245px;
  padding: 5px 10px;
  border: 0;
  background-color: #FFEBBF;
  position: relative;
  z-index: 1;
}
.suggestions {
  list-style-type: none;
  margin: 0;
  padding: 5px 10px;
  width: 245px;
  background-color: #85DDFF;
  display: none;
}
.content {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  padding: 35px 10px 5px 10px;
  overflow: auto;
  z-index: 0;
}
input:focus ~ .autosuggest .suggestions {
  display: block;
}
Run Code Online (Sandbox Code Playgroud)
<div class="container">
  <input class="input" type="text" value="input">
  <div class="autosuggest">
    <ul class="suggestions">
      <li>suggestion 1</li>
      <li>suggestion 2</li>
      <li>suggestion 3</li>
      <li>suggestion 4</li>
      <li>suggestion 5</li>
      <li>suggestion 6</li>
      <li>suggestion 7</li>
      <li>suggestion 8</li>
      <li>suggestion 9</li>
    </ul>
  </div>
  <div class="content">
    content content content content content content content content content content
    content content content content content content content content content content
    content content content content content content content content content content
    content content content content content content content content content content
    content content content content content content content content content content
    content content content content content content content content content content
  </div>
</div>

<div class="container">
  <input class="input" type="text" value="input">
  <div class="autosuggest">
    <ul class="suggestions">
      <li>suggestion 1</li>
      <li>suggestion 2</li>
      <li>suggestion 3</li>
      <li>suggestion 4</li>
      <li>suggestion 5</li>
    </ul>
  </div>
  <div class="content">
    content content content content content content content content content content
    content content content content content content content content content content
    content content content content content content content content content content
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)


DAC*_*sby 7

这看起来有点像一个笨拙的方法,并有一个小警告,但它是纯CSS /没有HTML结构修改.

从本质上讲,我.container是主要的父级,而不是尝试从较低级别(.autosuggest)工作.一步步:

  • 移动position: relative.container
  • 使.autosuggest定位绝对(上/左默认为0像素).
    • 给它一个更高的z指数,所以它总是在顶部
  • 使.content绝对定位的四面0像素所以它的大小相同.container
  • 将溢出滚动条移动到.contentdiv
  • (这里是警告)将顶部填充设置.content.input+实际所需填充的高度.否则,.content它位于输入元素的后面.

你最终得到了这个:

    .container {
      height: 100px;
      width: 300px;
      margin-top: 50px;
      border: 1px solid black;
      position: relative;
    }
    .autosuggest {
      width: 250px;
      position: absolute;
      z-index: 50;
    }
    .input {
      font-size: 16px;
      width: 230px;
      padding: 5px 10px;
      border: 0;
      background-color: #FFEBBF;
    }
    .autosuggest .input:focus ~ .suggestions{
      display: block;
    }
    .suggestions {
      display: none;
      list-style-type: none;
      margin: 0;
      padding: 5px 10px;
      width: 230px;
      background-color: #85DDFF;
    }
    .content {
      overflow-y: auto;
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      padding: 28px 10px 5px;
    }
Run Code Online (Sandbox Code Playgroud)
<div class="container">
  <div class="autosuggest">
    <input class="input" type="text" value="input">
    <ul class="suggestions">
      <li>suggestion 1</li>
      <li>suggestion 2</li>
      <li>suggestion 3</li>
      <li>suggestion 4</li>
      <li>suggestion 5</li>
      <li>suggestion 6</li>
      <li>suggestion 7</li>
      <li>suggestion 8</li>
      <li>suggestion 9</li>
    </ul>
  </div>
  <div class="content">
    content content<br >content content content content content<br ><br ><br ><br ><br ><br >content content content
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

我还为autosuggest框添加了一些显示/隐藏,因为它看起来不错.

.autosuggest .input:focus ~ .suggestions{
  display: block;
}
.suggestions {
  display: none;
}
Run Code Online (Sandbox Code Playgroud)

工作jsFiddle.

经过测试的FF 43,Chrome 47


滚动容器时,输入和建议应一起移动.

这很可能需要JavaScript.根据定义,将建议设置为绝对位置会将其从内容流的其余部分中删除.您可以在.suggestionsdiv 上设置一个高度并单独滚动它,但如果滚动.content绝对定位(再次,仅使用CSS),则滚动不能(据我所知)与滚动相关联.

就像是:

$('.content').on('scroll', function () {
  $('.autosuggest .suggestions').scrollTop($(this).scrollTop());
});
Run Code Online (Sandbox Code Playgroud)

为什么绝对定位的建议会影响容器的滚动条?

从技术上讲,绝对定位的元素不会影响父母的身高.但是,它们仍然被视为元素的内容 - 溢出的内容(至少在这种情况下).

overflow属性指定是否剪切内容,渲染滚动条或仅在溢出其块级容器时显示内容.(来自MDN)

由于.container溢出设置为滚动,它显示滚动条,因为其中一个子项溢出边界框.如果你将溢出更改为隐藏它将隐藏所有扩展内容并设置为可见,你会看到.autosuggest延伸超过.container,但也是如此.content(因为它也是扩展边界框的内容).

您会看到一个滚动条,因为.suggest内容在视觉上延伸到.container块之外,即使它位于绝对位置.


HTM*_*oob 5

您所要做的就是将 z-index 属性添加到 .autosuggest 和 .suggestions 这里是来自 codepen 的代码示例

http://codepen.io/HTMLNoob/pen/EPEXKN

.autosuggest {
  z-index: -10;
  width: 250px;
}
.suggestions {
  list-style-type: none;
  margin: 0;
  padding: 5px 10px;
  width: 230px;
  background-color: #85DDFF;
  position: absolute;
  z-index: 10;
}
Run Code Online (Sandbox Code Playgroud)

更新:

我相信这就是您正在寻找的

http://jsbin.com/fegibaboyo/1/edit?html,css,输出

注意:将鼠标悬停在带有建议的输入上。

更新2:

http://jsbin.com/mojopuboku/edit?html,css,输出

这是新的答案。

我已经在大多数浏览器(Firefox、Chrome、Opera)中测试了这个答案,所有浏览器都执行相同的结果。(我不确定 Safari,因为我无法在 Windows XP 上安装 Safari)

  • @HTMLNoob你错过了问题中的注释:_输入**和**建议应该一起移动。_ (2认同)