Как предотвратить абсолютно позиционированный элемент, чтобы повлиять на полосу прокрутки?

рассмотрим вход автозаполнения, сидящий в контейнере с некоторым содержимым и вертикальной полосой прокрутки:

enter image description here

когда отображаются предложения автозаполнения, они должны отображаться поверх содержимого не затрагивая полосу прокрутки контейнера.

Я ожидаю получить:

enter image description here

обратите внимание, что полоса прокрутки точно такая же, как и выше.

но, я получаю следующий:

enter image description here

обратите внимание, что полоса прокрутки затронута, и предложения вырезаются.

Почему абсолютно позиционированные предложения влияют на полосу прокрутки контейнера?

как бы вы это исправить?

9 ответов


это кажется немного странным подходом и имеет небольшое предостережение, но это чистый CSS/ без изменений структуры HTML.

по сути, я делаю .container основной родитель вместо того, чтобы пытаться работать с более низкого уровня (.autosuggest). Шаг за шагом:

  • движение position: relative до .container
  • сделать .autosuggest позиционируется абсолютно (верхнее / левое значение по умолчанию 0px).
    • дать ему более высокий Z-индекс, чтобы всегда топ!--29-->
  • сделать .content позиционируется абсолютно все четыре стороны 0px, так что это тот же размер, что и .container
  • переместите полосу прокрутки переполнения в .content div
  • (вот предостережение) установите верхнюю прокладку .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;
    }
<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>

I также добавлен показ / скрытие для окна автозаполнения, потому что он выглядит красиво.

.autosuggest .input:focus ~ .suggestions{
  display: block;
}
.suggestions {
  display: none;
}

рабочая jsFiddle.

протестировано FF 43, Chrome 47


при прокрутке контейнера входные данные и предложения должны перемещаться вместе.

для этого, скорее всего, потребуется JavaScript. По определению, установка предложений в абсолютное положение удаляет их из остальной части потока контента. Ты мог бы ... установите высоту на .suggestions div и прокрутите его отдельно, но эта прокрутка не может (насколько мне известно) быть привязана к .content прокрутите, если он расположен абсолютно (опять же, используя только CSS).

что-то типа:

$('.content').on('scroll', function () {
  $('.autosuggest .suggestions').scrollTop($(this).scrollTop());
});

почему абсолютно позиционированные предложения влияют на полосу прокрутки контейнера?

Технически говоря, абсолютно позиционированные элементы не влияют на высоту родителя. Тем не менее, они по-прежнему рассматриваются как содержимое элемента-содержимое, которое переполняется (по крайней мере, в этом случае).

свойство overflow указывает, следует ли обрезать содержимое, отображать полосы прокрутки или просто отображать содержимое при переполнении контейнера уровня блока. (из MDN)

С .container и переливом набор для прокрутки, он показывает полосу прокрутки, потому что один из детей выходит за рамку. Если вы измените overflow на hidden, он скроет все расширяющееся содержимое и установите для visible вы увидите .autosuggest расширить за .container, но и .content (поскольку это также контент, который расширяет ограничивающую рамку).

вы видите полосу прокрутки, потому что .suggest содержание визуально выходит за рамки .container блок, хотя он расположен абсолютно.


  • когда отображаются предложения автозаполнения, они должны отображаться поверх содержимого, не влияя на полосу прокрутки контейнера.
  • при прокрутке контейнера входные данные и предложения должны перемещаться вместе.

это не может быть сделано только с CSS.

иметь suggestions появляются поверх containerсодержание, не обрезается, он должен иметь position: absolute и ни один из его родителей (autosuggest и container) может быть position: relative.

программа suggestions не будет двигаться по спирали.

на suggestions для перемещения со свитком, один из его родителей (autosuggest или container) должен быть position: relative.

нижняя сторона с тем, что есть, и как container - это не overflow: visible, то он будет обрезан


как уже предлагалось, так и предполагалось input должно быть в пределах autosuggest элемент, изменяющий position: relative на autosuggest to position: absolute, так что input остается с suggestions на прокрутке, вероятно, будет лучшим, хотя настройка z-index в каждом container будет необходимо, чтобы избежать нечетного перекрытия.

но если поставщик компонент третьей стороны,... :) ..., можно было бы поговорить в версию, где input может быть размещен за пределами autosuggest элемент, можно получить больше контроля, используя только CSS, как suggestions и content и их макеты, основанные на 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;
}
<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>

все, что вам нужно сделать, это добавить свойства z-индекса.автозавершение и .предложения Вот пример кода из 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;
}

обновление:

Я считаю, что это то, что вы ищете

http://jsbin.com/fegibaboyo/1/edit?html, css, выход

Примечание: наведите курсор на вход с предложения.

обновление 2:

http://jsbin.com/mojopuboku/edit?html, css, выход

вот новый ответ.

я протестировал этот ответ в большинстве браузеров(Firefox, Chrome, Opera), и все они выполняют одни и те же результаты.(Я не уверен в Safari, потому что я не могу установить Safari на моем Windows XP)


.autosuggest {
  position: fixed; /* add position:fixed */
}

.suggestions {
 /* remove position:absolute */
}

Почему бы просто не вытащить элементы ul и li из контейнера div, а затем переместить предложения вверх, установив отрицательное верхнее положение?

http://jsbin.com/ficalu/edit?html, css, выход

обновление: Изменение.autosuggest в позицию: абсолютный

http://jsbin.com/gezimi/edit?html, css, вывод


легко, удалить

position: relative

из класса .автозаполнение и добавление в класс .контейнер


добавьте это в свой CSS:

.input:focus + .suggestions {
  position: fixed;
  display: block;
}

и добавить display: none; to .suggestions в вашем CSS.

Скрипка здесь.


Как насчет этого:

  • перемещение автозаполнения вне контейнера
  • дайте содержимому тот же запас, что и высота ввода (если вы используете меньше/SASS, вы должны быть в состоянии вычислить это)
  • падение autosuggest вниз, чтобы занять место на полях

мои изменения в CSS имеют комментарий рядом с ними. Обратите внимание, что это был протестирован только в Chrome. Вы также можете немного оптимизировать HTML, например, удалить контейнер в Примере, но у вас, вероятно, есть несколько элементов.

HTML:

  <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="container">
    <div class="content">
      content content content content content content content content content content
    </div>
  </div>

CSS-код:

.container {
  height: 100px;
  width: 300px;
  overflow-y: auto;
  border: 1px solid black;
}
.autosuggest {
  position: relative;
  top:29px; /* height of input */
  left:1px; /* width of container border */
  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;
  margin-top: 29px; /* height of input */
  padding: 5px 10px;
}

вы можете сделать это в стиле "только css", только если предложение 1,2,3 элементов не будет дочерним элементом элемента" input".

например:

<input>
 content
 content
</input>

suggestion1
suggestion2
suggestion3

или в качестве рабочего примера Thar предложить htmlnoob url в некотором верхнем беспорядке

другое исправление, может работать только в старых браузерах, таких как ie5.