CSS overflow-x: visible; y overflow-y: oculto; causando problemas con la barra de desplazamiento

455

Supongamos que tiene algo de estilo y el marcado:

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>

Cuando ves esto. El <ul>tiene una barra de desplazamiento en la parte inferior, aunque he especificado los valores visibles y ocultas para el desbordamiento x / y.

(observado en Chrome 11 y opera (?))

Supongo que debe haber alguna especificación de w3c o algo que indique que esto suceda, pero por mi vida no puedo entender por qué.

JSFiddle

ACTUALIZACIÓN: - Encontré una manera de lograr el mismo resultado agregando otro elemento envuelto alrededor del ul. Echale un vistazo.

James Khoury
fuente
¿Cuál es tu resultado deseado? jsfiddle.net/Kyle_Sevenoaks/3xv6A/2
Kyle
@kyle debería parecerse un poco más a: jsfiddle.net/3xv6A/5 Desafortunadamente, si lo configuro overflow-x hidden;, elimina el desplazamiento, pero como necesito los elementos li para ocultar el borde en la parte inferior, da el efecto discontinuo deseado. No entiendo por qué overflow-x: visiblecrea una barra de desplazamiento. No debería afaik.
James Khoury
@JamesKhoury, ¿puedes elaborar un poco en tu solución? Realmente no puedo hacer que funcione
George Katsanos
1
@GeorgeKatsanos La solución alternativa: jsfiddle.net/3xv6A/9 se basa en el ser padre overflow: hidden;y el niño insertado alrededor del <ul>ser overflow: visible.
James Khoury
@JamesKhoury ¿Crees que puede funcionar para embed.plnkr.co/2rbaISwvzuKhyPEFpBKD
George Katsanos

Respuestas:

681

Después de algunas búsquedas serias, parece que encontré la respuesta a mi pregunta:

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

En Gecko, Safari, Opera, 'visible' se convierte en 'auto' también cuando se combina con 'oculto' (en otras palabras: 'visible' se convierte en 'auto' cuando se combina con cualquier otra cosa diferente de 'visible'). Gecko 1.8, Safari 3, Opera 9.5 son bastante consistentes entre ellos.

También la especificación W3C dice:

Los valores calculados de 'overflow-x' y 'overflow-y' son los mismos que sus valores especificados, excepto que algunas combinaciones con 'visible' no son posibles: si una se especifica como 'visible' y la otra es 'scroll' o 'auto', entonces 'visible' se establece en 'auto'. El valor calculado de 'overflow' es igual al valor calculado de 'overflow-x' si 'overflow-y' es el mismo; de lo contrario, es el par de valores calculados de 'overflow-x' y 'overflow-y'.

Version corta:

Si está utilizando visibleuno overflow-xu otro overflow-yy algo distinto visibleal otro, el visiblevalor se interpreta como auto.

James Khoury
fuente
264
Entiendo que el W3C lo especifica de esta manera, pero ¿cuál es la motivación detrás de esto? Me parece un comportamiento bastante extraño e inconsistente, lo que resulta en soluciones desordenadas que requieren agregar elementos HTML triviales.
Erwin
21
@Erwin Estoy de acuerdo, espero que alguien decida actualizar la especificación.
James Khoury el
125
Tienes razón pero no tiene sentido. La razón más común por la que incluso querrías x e y es para que puedas hacer que uno esté oculto y el otro sea visible.
Rescate creativo
9191
Esto es paralizante. Por qué no podemos permitir que overflow-x:visibledurante overflow-y:hiddensin un corte del padre / hijo? Bastante litera, en mi opinión.
Slink
34
Esto es totalmente paralizante. Estaba tratando de hacer un montón de enlaces desplegables en una barra de navegación Bootstrap horizontalmente, pero eso rompe los menús desplegables, que dependen overflow-y: visible. Boo CSS!
Andy
131

otro truco barato, que parece hacer el truco:

style="padding-bottom: 250px; margin-bottom: -250px;"en el elemento donde el desbordamiento vertical se está cortando, con la 250representación de tantos píxeles como sea necesario para su menú desplegable, etc.

Justin Krause
fuente
66
Muchas gracias, aunque esto se siente raro, pero parece ser la mejor manera de resolver el problema. Los desbordamientos son terribles en css :(
Serge Eremeev
11
Esto hace que la barra de desplazamiento horizontal aparezca tan abajo
nafg
2
Esto también bloquea los eventos de puntero para 250 px debajo del elemento. Pero encontré una forma de evitar eso, y esta solución es lo que estoy usando.
Chris Chudzicki
2
2 años después y esta parece ser la mejor respuesta a este problema ... Esperemos que con otro navegador (Microsoft Edge) salte al proyecto de código abierto Chromium, veremos un desarrollo más rápido de las características del navegador que importan, así como un mejor navegador compatibilidad.
Spencer O'Reilly
En mi escenario particular, donde position: relativeno era posible quitar o usar envoltorios, esta era la única solución que funcionaba, aunque también requería agregar muchos márgenes feos a los elementos secundarios dentro del elemento que quería configurar overflow-x: hiddenpara compensar el hacky relleno. Sin embargo, esto me salvó, ¡así que gracias!
Philip Stratford
81

Originalmente encontré una forma de CSS para evitar esto cuando uso el complemento Cycle jQuery. Cycle usa JavaScript para configurar mi diapositiva overflow: hidden, por lo que cuando configuro mis imágenes para que width: 100%las imágenes se vean cortadas verticalmente, las obligué a que sean visibles !importanty eviten mostrar la animación de diapositivas fuera de la caja que configuré overflow: hiddenen el contenedor div del diapositiva. Espero que funcione para ti.

ACTUALIZACIÓN - Nueva solución:

Problema original -> http://jsfiddle.net/xMddf/1/ (Incluso si lo uso overflow-y: visiblese convierte en "auto" y en realidad "scroll").

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

La nueva solución -> http://jsfiddle.net/xMddf/2/ (Encontré una solución usando un contenedor wrap para aplicar overflow-xy overflow-ypara diferentes elementos DOM como James Khoury aconsejó sobre el problema de combinar visibley hiddenpara un solo elemento DOM).

#wrapper {
    height: 100px;
    overflow-y: visible;
}
#content {
    width: 200px;
    overflow-x: hidden;
}
Macumbaomuerte
fuente
12
¿Cómo se aplica esto? No parece funcionar en overflow-x o overflow-y.
James Khoury
1
@Macumbaomuetre Eso está más claro, gracias +1. Es similar a la "actualización" que agregué. Originalmente no pude alterar el div de envoltura y mi solución terminó similar a: jsfiddle.net/3xv6A/338
James Khoury
99
Esta solución no aplica. La pregunta es overflow-x:visible;y overflow-y:hidden. No de la otra manera.
Jakobovski
1
@TomasJansson @Edward Se hace el trabajo, sólo hay que permuta donde se aplica la overflow-xe -y: violín actualizada .
Solo un estudiante
1
esto falla tan pronto como el contenedor gana un ancho por alguna razón - jsfiddle.net/ad1941k9/16
David Meister
10

Me he encontrado con este problema al intentar crear una barra lateral de posición fija con contenido desplazable verticalmente y elementos secundarios anidados en posición absoluta que se mostrarán fuera de los límites de la barra lateral .

Mi enfoque consistía en aplicar por separado:

  • una overflow: visiblepropiedad para el elemento de la barra lateral
  • una overflow-y: autopropiedad del envoltorio interno de la barra lateral

Por favor, consulte el ejemplo a continuación o un código en línea .

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
fuente
2
Estoy bastante seguro de que esta es la misma solución que otros han presentado, excepto con en autolugar de hidden.
James Khoury
@JamesKhoury Pero este es el único que puedo comprender porque señala el uso deposition
Guichi
7

Utilicé el content+wrapperenfoque ... pero hice algo diferente a lo mencionado hasta ahora: me aseguré de que los límites de mi envoltorio NO se alinearan con los límites del contenido en la dirección en la que quería ser visible .

Nota importante: Fue bastante fácil de conseguir el content+wrapper, same-boundsenfoque de trabajo en un navegador u otro dependiendo de varias combinaciones de CSS position, overflow-*etc ... pero nunca podría utilizar este enfoque para conseguir que todo correcto (Edge, Chrome, Safari. ..).

Pero cuando tuve algo como:

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

... todos los navegadores estaban contentos.

dsdsdsdsd
fuente
6

Ahora hay una nueva forma de abordar este problema : si elimina la posición: relativa del contenedor que necesita tener el desbordamiento-y visible, puede tener desbordamiento-y visible y desbordamiento-x oculto, y viceversa (tener desbordamiento- x visible y overflow-y oculto, solo asegúrese de que el contenedor con la propiedad visible no esté relativamente posicionado).

Vea esta publicación de CSS Tricks para más detalles: funcionó para mí: https://css-tricks.com/popping-hidden-overflow/

Alexandra
fuente
2
pero eso requeriría algo de javascript para colocar el elemento correctamente si es absoluto
gaurav5430