34 votes

Comment empêcher un élément positionné de manière absolue d'affecter la barre de défilement ?

Prenons l'exemple d'une entrée autosuggest située dans un conteneur avec du contenu et une barre de défilement verticale :

enter image description here

Lorsque les suggestions d'autosuggestion sont affichées, elles doivent apparaître en haut du contenu. sans affecter la barre de défilement du conteneur .

Je m'attends à recevoir :

enter image description here

Notez que la barre de défilement est exactement la même que ci-dessus.

Mais, j'obtiens ce qui suit :

enter image description here

Notez que la barre de défilement est affectée, et que les suggestions sont coupées.

Pourquoi les suggestions positionnées affectent-elles absolument la barre de défilement du conteneur ?

Comment réparer cela ?

Terrain de jeu ici

Notes :

  • Lorsque vous faites défiler le conteneur, l'entrée et les suggestions doivent se déplacer ensemble.
  • Vous êtes autorisé à modifier le HTML, mais l'entrée et la liste de suggestions doivent rester à l'intérieur. .autosuggest (considérer .autosuggest comme un composant tiers dont le HTML ne peut être modifié, mais dont vous pouvez modifier le CSS).
  • Vous pouvez utiliser le système Flexbox, si cela peut vous aider.
  • Je cherche une solution uniquement en CSS. Pas de Javascript s'il vous plaît.

.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;
}

<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>

0 votes

Quels sont les résultats attendus ? Le conteneur overflow-y est réglé sur auto et a une hauteur fixe. Les suggestions d'auto ne peuvent pas laisser ce conteneur tel quel. Retirez l'overlow et le scroll disparaît.

0 votes

@charlietfl J'ai mis à jour la question avec le comportement attendu.

0 votes

Pouvez-vous également mettre à jour votre question avec le code ? Les captures d'écran sont bien, mais vous devriez savoir maintenant que vous devez inclure le code dans la question.

12voto

LGSon Points 1306
  • Lorsque les suggestions automatiques sont affichées, elles doivent apparaître au-dessus du contenu sans affecter la barre de défilement du conteneur.
  • Lorsque vous faites défiler le conteneur, l'entrée et les suggestions doivent se déplacer ensemble.

Cela ne peut pas être fait avec CSS seulement.

Pour avoir suggestions apparaissent en haut de l'écran container contenu, non coupé, il doit avoir position: absolute et aucun de ses parents ( autosuggest et container ) peut être position: relative .

L'inconvénient est que suggestions ne bougera pas sur le parchemin.

Pour suggestions pour se déplacer avec le scroll, l'un de ses parents ( autosuggest o container ) doit être position: relative .

Le revers de la médaille est, et comme la container n'est pas overflow: visible il sera coupé


Comme déjà suggéré, et en supposant que le input doit se situer dans la autosuggest en modifiant l'élément position: relative sur le autosuggest à position: absolute donc le input reste avec suggestions sur le parchemin, sera probablement la meilleure, bien que le réglage z-index sur chaque container sera nécessaire pour éviter les chevauchements bizarres.

Mais si le fournisseur de le composant tiers ,... :) ..., on pourrait parler d'une version où le input pourrait être placé à l'extérieur de la autosuggest il est possible d'obtenir un meilleur contrôle, en utilisant uniquement le CSS, à la fois de l'élément suggestions et le content et leurs dispositions, en fonction de si input a le focus ou pas,...

... où cet échantillon pourrait peut-être être un bon début (cliquez sur input pour montrer 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>

8voto

DACrosby Points 3736

Cette approche semble un peu farfelue et comporte une petite mise en garde, mais il s'agit de CSS purs, sans modification de la structure HTML.

Essentiellement, je fais le .container le parent principal au lieu d'essayer de travailler à partir d'un niveau inférieur ( .autosuggest ). Pas à pas :

  • Déplacements position: relative jusqu'à .container
  • Faites le .autosuggest positionné de manière absolue (haut / gauche par défaut à 0px).
    • Donnez-lui un z-index plus élevé pour qu'il soit toujours en haut de l'écran.
  • faire .content positionné de manière absolue sur les quatre côtés à 0px, de sorte qu'il soit de la même taille que .container
  • Déplacez la barre de défilement de débordement vers le .content div
  • (voici la mise en garde) Définir le rembourrage supérieur de .content à la hauteur de .input + le rembourrage réellement souhaité. Sinon, le .content est derrière l'élément d'entrée.

Et vous vous retrouvez avec ça :

    .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>

J'ai également ajouté des fonctions d'affichage et de masquage pour la boîte d'autosuggestion, car cela est agréable à regarder.

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

Travail de jsFiddle.

Testé FF 43, Chrome 47


Lorsque vous faites défiler le conteneur, l'entrée et les suggestions doivent se déplacer ensemble.

Cela nécessitera probablement JavaScript. Par définition, le fait de placer les suggestions en position absolue les éloigne du reste du flux de contenu. Vous pourriez définir une hauteur sur le .suggestions et le faire défiler séparément, mais ce défilement ne peut pas (à ma connaissance) être lié à la balise .content défiler s'il est positionné de manière absolue (là encore, en utilisant uniquement les CSS).

Quelque chose comme :

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

Pourquoi les suggestions positionnées affectent-elles absolument la barre de défilement du conteneur ?

Techniquement parlant, les éléments positionnés de manière absolue n'affectent pas la hauteur du parent. Cependant, ils sont toujours considérés comme le contenu de l'élément - un contenu qui déborde (du moins dans ce cas).

La propriété overflow indique s'il faut couper le contenu, rendre les barres de défilement ou simplement afficher le contenu lorsqu'il dépasse son conteneur de niveau bloc. ( de MDN )

Depuis .container dont le débordement est réglé sur le défilement, il affiche une barre de défilement parce que l'un de ses enfants dépasse la boîte de délimitation. Si vous changez le paramètre overflow en hidden (caché), tout le contenu qui s'étend sera masqué, et si vous le mettez en visible, vous verrez la barre de défilement .autosuggest s'étendent au-delà du .container mais aussi .content (puisqu'il s'agit également d'un contenu qui étend la boîte englobante).

Vous voyez une barre de défilement parce que le .suggest le contenu s'étend visuellement au-delà du .container même s'il est positionné de manière absolue.

5voto

HTMLNoob Points 493

Tout ce que vous avez à faire est d'ajouter des propriétés z-index à .autosuggest et .suggestions ; voici un exemple de code tiré de 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;
}

UPDATE :

Je crois que c'est ce que vous recherchez

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

Note : Passez la souris sur l'entrée avec des suggestions.

UPDATE2 :

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

Voici la nouvelle réponse.

J'ai testé cette réponse dans la plupart des navigateurs (Firefox, Chrome, Opera) et tous donnent les mêmes résultats (je ne suis pas sûr pour Safari, car je ne peux pas installer Safari sur mon Windows XP).

0 votes

La tentative de poster le lien aurait dû entraîner une erreur. Qu'est-ce que cela vous dit ?

0 votes

"Vous devez fournir un code avec tout lien....." Je le fais et il affiche littéralement le code et non le lien.

0 votes

Vous êtes sûr d'avoir inclus le code ? Je ne vois rien d'autre que le lien (dans un bloc de code).

1voto

Tate Thurston Points 327

Pourquoi ne pas simplement retirer les éléments ul et li du conteneur div et déplacer les suggestions vers le haut en définissant une position supérieure négative ?

http://jsbin.com/ficalu/edit?html,css,output

Mise à jour : Changer .autosuggest en position : absolute

http://jsbin.com/gezimi/edit?html,css,output

0 votes

Je devrais probablement être plus précis et dire que .autosuggest est un composant tiers, donc vous ne pouvez pas déplacer .suggestions à l'extérieur de .autosuggest .

0 votes

Je l'ai. Et si on changeait .autosuggest en position : absolute ? jsbin.com/gezimi/edit?html,css,output

0 votes

Veuillez vérifier à nouveau le lien. Je suppose que vous avez collé le mauvais lien, ou mis à jour le Bin après cela. Cela ne semble pas résoudre le problème.

1voto

Jamie Paterson Points 74

Facile, à enlever

position: relative

de la classe .autosuggest et ajouter à la classe .container

0 votes

.container { height : 100px ; width : 300px ; margin-top : 50px ; border : 1px solid black ; position : relative ; } .autosuggest { width : 300px ; overflow-y : scroll ; height : 100px ; } .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 ; }

0 votes

Votre JSbin ne fonctionne pas comme prévu (il n'a pas du tout de barre de défilement, et le contenu semble être en dehors du conteneur).

0 votes

D'après votre question, je pensais que c'était ce que vous vouliez obtenir comme résultat - je ne suis pas sûr de bien comprendre la question alors ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X