CSS overflow-x: visible; et overflow-y: caché; provoquant un problème de barre de défilement

455

Supposons que vous ayez un certain style et le balisage:

ul
{
  white-space: nowrap;
  overflow-x: visible;
  overflow-y: hidden;
/* added width so it would work in the snippet */
  width: 100px; 
}
li
{
  display: inline-block;
}
<div>
  <ul>
    <li>1</li> <li>2</li> <li>3</li>
    <li>4</li> <li>5</li> <li>6</li>
    <li>7</li> <li>8</li> <li>9</li>
    <li>1</li> <li>2</li> <li>3</li>
    <li>4</li> <li>5</li> <li>6</li>
    <li>7</li> <li>8</li> <li>9</li>
    <li>1</li> <li>2</li> <li>3</li>
    <li>4</li> <li>5</li> <li>6</li>
    <li>7</li> <li>8</li> <li>9</li>
  </ul>
</div>

Lorsque vous affichez cela. Le <ul>a une barre de défilement en bas même si j'ai spécifié des valeurs visibles et cachées pour le débordement x / y.

(observé sur Chrome 11 et opéra (?))

Je suppose qu'il doit y avoir des spécifications W3C ou quelque chose qui disent que cela doit arriver, mais pour la vie de moi, je ne peux pas comprendre pourquoi.

JSFiddle

MISE À JOUR: - J'ai trouvé un moyen d'obtenir le même résultat en ajoutant un autre élément enroulé autour du ul. Vérifiez-le.

James Khoury
la source
Quel est votre résultat souhaité? jsfiddle.net/Kyle_Sevenoaks/3xv6A/2
Kyle
@kyle, cela devrait ressembler un peu plus à: jsfiddle.net/3xv6A/5 Malheureusement, si je le configure, overflow-x hidden;il supprime le défilement, mais comme j'ai besoin des éléments li pour masquer la bordure en bas, il donne donc l'effet pointillé souhaité. Je ne comprends pas pourquoi overflow-x: visiblecrée une barre de défilement. Cela ne devrait pas afaik.
James Khoury
@JamesKhoury pouvez-vous élaborer un peu dans votre solution? Je ne peux pas vraiment le faire fonctionner
George Katsanos
1
@GeorgeKatsanos La solution de contournement: jsfiddle.net/3xv6A/9 repose sur l'être parent overflow: hidden;et un enfant inséré autour de l' <ul>être overflow: visible.
James Khoury
@JamesKhoury Pensez-vous que cela peut fonctionner pour embed.plnkr.co/2rbaISwvzuKhyPEFpBKD
George Katsanos

Réponses:

681

Après quelques recherches sérieuses, il semble que j'ai trouvé la réponse à ma question:

à partir de: http://www.brunildo.org/test/Overflowxy2.html

Dans Gecko, Safari, Opera, «visible» devient «auto» également lorsqu'il est combiné avec «caché» (en d'autres termes: «visible» devient «auto» lorsqu'il est combiné avec autre chose que «visible»). Gecko 1.8, Safari 3, Opera 9.5 sont assez cohérents entre eux.

aussi la spécification W3C dit:

Les valeurs calculées de 'overflow-x' et 'overflow-y' sont les mêmes que leurs valeurs spécifiées, sauf que certaines combinaisons avec 'visible' ne sont pas possibles: si l'une est spécifiée comme 'visible' et l'autre est 'scroll' ou 'auto', puis 'visible' est réglé sur 'auto'. La valeur calculée de 'overflow' est égale à la valeur calculée de 'overflow-x' si 'overflow-y' est la même; sinon c'est la paire de valeurs calculées de 'overflow-x' et 'overflow-y'.

Version courte:

Si vous utilisez visiblepour ou overflow-xou overflow-yet autre chose que visiblepour l'autre, la visiblevaleur est interprétée comme auto.

James Khoury
la source
264
Je comprends que le W3C le spécifie de cette façon, mais quelle est la motivation derrière cela? Je trouve ce comportement assez étrange et incohérent, ce qui entraîne des solutions de contournement compliquées qui nécessitent l'ajout d'éléments HTML triviaux.
Erwin
21
@Erwin Je suis d'accord, j'espère que quelqu'un décide de mettre à jour la spécification.
James Khoury
125
Vous avez raison mais cela n'a aucun sens. La raison la plus courante pour laquelle vous souhaitez même x et y est pour que vous puissiez en rendre un caché et l'autre visible.
rescuecreative
91
C'est paralysant. Pourquoi ne pouvons - nous permettre au overflow-x:visiblecours overflow-y:hiddensans un hack parent / enfant? Jolie couchette, OMI.
Slink
34
C'est totalement paralysant. J'essayais de créer un tas de liens déroulants dans un défilement de barre de navigation Bootstrap horizontalement, mais cela rompt les menus déroulants, qui comptent overflow-y: visible. Boo CSS!
Andy
131

un autre hack pas cher, qui semble faire l'affaire:

style="padding-bottom: 250px; margin-bottom: -250px;"sur l'élément où le débordement vertical se coupe, avec 250autant de pixels que nécessaire pour votre liste déroulante, etc.

Justin Krause
la source
6
merci beaucoup, même si cela semble hacky, mais semble être le meilleur moyen de résoudre le problème. Les débordements sont terribles en CSS :(
Serge Eremeev
11
Cela fait apparaître la barre de défilement horizontale aussi loin
nafg
2
Cela bloque également les événements de pointeur pour 250 pixels sous l'élément. Mais j'ai trouvé un moyen de contourner cela, et cette solution est ce que j'utilise.
Chris Chudzicki
2
2 ans plus tard et cela semble toujours être la meilleure réponse à ce problème ... Espérons qu'avec un autre navigateur (Microsoft Edge) sautant sur le projet open source Chromium, nous verrons un développement plus rapide des fonctionnalités du navigateur qui comptent ainsi qu'un meilleur navigateur compatibilité.
Spencer O'Reilly
Dans mon scénario particulier, où la suppression position: relativeou l'utilisation de wrappers n'était pas possible, c'était la seule solution qui fonctionnait, même si cela nécessitait également l'ajout de nombreuses marges moches aux éléments enfants à l'intérieur de l'élément que je voulais définir overflow-x: hiddenpour compenser le hacky rembourrage. Cela m'a sauvé, cependant, merci!
Philip Stratford
81

À l'origine, j'ai trouvé un moyen CSS de contourner cela lors de l'utilisation du plugin Cycle jQuery. Cycle utilise JavaScript pour définir ma diapositive.Ainsi overflow: hidden, lors de la définition de mes images, width: 100%les images sembleront coupées verticalement, je les ai donc forcées à être visibles avec !importantet à éviter d'afficher l'animation de la diapositive hors de la boîte que j'ai définie overflow: hiddensur la div du conteneur de la faire glisser. J'espère que ça marche pour toi.

MISE À JOUR - Nouvelle solution:

Problème d'origine -> http://jsfiddle.net/xMddf/1/ (Même si je l'utilise, overflow-y: visibleil devient "auto" et en fait "scroll".)

#content {
    height: 100px;
    width: 200px;
    overflow-x: hidden;
    overflow-y: visible;
}

La nouvelle solution -> http://jsfiddle.net/xMddf/2/ (J'ai trouvé une solution de contournement en utilisant un div wrapper à appliquer overflow-xet overflow-yà différents éléments DOM comme James Khoury l'a conseillé sur le problème de la combinaison visibleet hiddend'un seul élément DOM.)

#wrapper {
    height: 100px;
    overflow-y: visible;
}
#content {
    width: 200px;
    overflow-x: hidden;
}
Macumbaomuerte
la source
12
Comment cela s'applique-t-il? Il ne semble pas fonctionner sur overflow-x ou overflow-y.
James Khoury
1
@Macumbaomuetre C'est plus clair, merci +1. Elle est similaire à la "mise à jour" que j'ai ajoutée. À l'origine, je ne pouvais pas modifier le div enveloppant et ma solution a fini par ressembler à: jsfiddle.net/3xv6A/338
James Khoury
9
Cette solution ne s'applique pas. La question est overflow-x:visible;et overflow-y:hidden. Pas l'inverse.
Jakobovski
1
@TomasJansson @Edward Il fait le travail, il vous suffit de swaps où vous appliquez le overflow-xet -y: violon mis à jour .
Juste un étudiant
1
cela échoue dès que le wrapper gagne en largeur pour une raison quelconque - jsfiddle.net/ad1941k9/16
David Meister
10

J'ai rencontré ce problème en essayant de créer une barre latérale positionnée fixe avec du contenu à défilement vertical et des enfants positionnés absolus imbriqués à afficher en dehors des limites de la barre latérale .

Mon approche consistait à appliquer séparément:

  • une overflow: visiblepropriété à l'élément de la barre latérale
  • une overflow-y: autopropriété au wrapper intérieur de la barre latérale

Veuillez consulter l'exemple ci-dessous ou un codepen en ligne .

html {
  min-height: 100%;
}
body {
  min-height: 100%;
  background: linear-gradient(to bottom, white, DarkGray 80%);
  margin: 0;
  padding: 0;
}

.sidebar {
  position: fixed;
  top: 0;
  right: 0;
  height: 100%;
  width: 200px;
  overflow: visible;  /* Just apply overflow-x */
  background-color: DarkOrange;
}

.sidebarWrapper {
  padding: 10px;
  overflow-y: auto;   /* Just apply overflow-y */
  height: 100%;
  width: 100%;
}

.element {
  position: absolute;
  top: 0;
  right: 100%;
  background-color: CornflowerBlue;
  padding: 10px;
  width: 200px;
}
<p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?</p>
<div class="sidebar">
  <div class="sidebarWrapper">
    <div class="element">
      I'm a sidebar child element but I'm able to horizontally overflow its boundaries.
    </div>
    <p>This is a 200px width container with optional vertical scroll.</p>
    <p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?</p>
  </div>
</div>

Andrea Carraro
la source
2
Je suis presque sûr que c'est la même solution que d'autres ont présenté, sauf avec autoau lieu de hidden.
James Khoury
@JamesKhoury Mais celui-ci est le seul que je peux comprendre car il indique l'utilisation deposition
Guichi
7

J'ai utilisé l' content+wrapperapproche ... mais j'ai fait quelque chose de différent de celui mentionné jusqu'à présent: je me suis assuré que les limites de mon wrapper ne s'alignaient PAS avec les limites du contenu dans la direction que je voulais être visible .

Remarque importante: Il est assez facile d'obtenir l' content+wrapper, same-boundsapproche du travail sur un navigateur ou d'une autre en fonction de diverses combinaisons de css de position, overflow-*, etc ... mais je ne peut utiliser cette approche pour les obtenir tout correct (Edge, Chrome, Safari,. ..).

Mais quand j'avais quelque chose comme:

  <div id="hack_wrapper" // created solely for this purpose
       style="position:absolute; width:100%; height:100%; overflow-x:hidden;">
      <div id="content_wrapper"
           style="position:absolute; width:100%; height:15%; overflow:visible;">         
          ... content with too-much horizontal content ... 
      </div>
  </div>

... tous les navigateurs étaient satisfaits.

dsdsdsdsd
la source
6

Il existe maintenant une nouvelle façon de résoudre ce problème - si vous supprimez la position: relative du conteneur qui doit avoir le débordement-y visible, vous pouvez avoir le débordement-y visible et le débordement-x caché, et vice versa (avoir le débordement- x visible et débordement-y caché, assurez-vous simplement que le conteneur avec la propriété visible n'est pas positionné relativement).

Voir cet article de CSS Tricks pour plus de détails - cela a fonctionné pour moi: https://css-tricks.com/popping-hidden-overflow/

Alexandra
la source
2
mais cela nécessiterait du javascript pour positionner l'élément correctement s'il est absolu
gaurav5430