No puedo desplazarme a la parte superior del elemento flexible cuyo contenedor está desbordado

Resuelto jejacks0n asked hace 9 años • 13 respuestas

Al intentar crear un modal útil usando flexbox, encontré lo que parece ser un problema del navegador y me pregunto si existe una solución conocida o alternativa, o ideas sobre cómo resolverlo.

Lo que estoy tratando de resolver tiene dos aspectos. Primero, centrar la ventana modal verticalmente, lo que funciona como se esperaba. La segunda es hacer que la ventana modal se desplace, externamente, de modo que toda la ventana modal se desplace, no el contenido dentro de ella (esto es para que pueda tener menús desplegables y otros elementos de la interfaz de usuario que puedan extenderse fuera de los límites del modal). como un selector de fechas personalizado, etc.)

Sin embargo, al combinar el centrado vertical con barras de desplazamiento, la parte superior del modal puede volverse inaccesible cuando comienza a desbordarse. En el ejemplo anterior, puede cambiar el tamaño para forzar el desbordamiento y, al hacerlo, le permite desplazarse hasta la parte inferior del modal, pero no hasta la parte superior (el primer párrafo está cortado).

.modal-container {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background: rgba(0, 0, 0, 0.5);
  overflow-x: auto;
}
.modal-container .modal-window {
  display: -ms-flexbox;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* Optional support to confirm scroll behavior makes sense in IE10
  //-ms-flex-direction: column;
  //-ms-flex-align: center;
  //-ms-flex-pack: center; */
  height: 100%;
}
.modal-container .modal-window .modal-content {
  border: 1px solid #ccc;
  border-radius: 4px;
  background: #fff;
  width: 100%;
  max-width: 500px;
  padding: 10px
}
<div class="modal-container">
    <div class="modal-window">
        <div class="modal-content">
            <p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
            <p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
            <p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
        </div>
    </div>
</div>
Expandir fragmento

Esto afecta a los (actuales) Firefox, Safari, Chrome y Opera. Curiosamente, se comporta correctamente en IE10 si comenta en el CSS con prefijo del proveedor de IE10. No me molesté en realizar pruebas en IE11 todavía, pero asumo que el comportamiento coincide con el de IE10.

Aquí está el enlace al código de ejemplo (muy simplificado)

https://jsfiddle.net/dh9k18k0/2/

jejacks0n avatar Nov 01 '15 00:11 jejacks0n
Aceptado

El problema

Flexbox hace que centrar sea muy fácil.

Simplemente aplicando align-items: centery justify-content: centeral contenedor flexible, sus artículos flexibles estarán centrados vertical y horizontalmente.

Sin embargo, existe un problema con este método cuando el elemento flexible es más grande que el contenedor flexible.

Como se señaló en la pregunta, cuando el elemento flexible desborda el contenedor, la parte superior se vuelve inaccesible.

Para el desbordamiento horizontal, la sección izquierda se vuelve inaccesible (o sección derecha, en lenguajes RTL).

A continuación se muestra un ejemplo con un contenedor LTR que tiene justify-content: centertres elementos flexibles:

Consulte la parte inferior de esta respuesta para obtener una explicación de este comportamiento.


Solución #1

Para solucionar este problema, utilice los márgenes automáticos de Flexbox , en lugar de justify-content.

Con automárgenes, un elemento flexible desbordado se puede centrar vertical y horizontalmente sin perder el acceso a ninguna parte del mismo.

Entonces, en lugar de este código en el contenedor flexible:

#flex-container {
    align-items: center;
    justify-content: center;
}

Utilice este código en el elemento flexible:

.flex-item {
    margin: auto;
}

Demostración revisada


Solución n.º 2 (aún no implementada en la mayoría de los navegadores)

Agregue el safevalor a su regla de alineación de palabras clave, así:

justify-content: safe center

o

align-self: safe center

De la especificación del módulo de alineación de caja CSS :

4.4. Alineación de desbordamiento: las palabras clave safey unsafey los límites de seguridad de desplazamiento

Cuando el [elemento flexible] es más grande que el [contenedor flexible], se desbordará. Algunos modos de alineación, si se respetan en esta situación, pueden provocar pérdida de datos: por ejemplo, si el contenido de una barra lateral está centrado, cuando se desborda puede enviar parte de sus cuadros más allá del borde inicial de la ventana gráfica, al que no se puede desplazar. .

Para controlar esta situación, se puede especificar explícitamente un modo de alineación de desbordamiento . UnsafeLa alineación respeta el modo de alineación especificado en situaciones de desbordamiento, incluso si causa pérdida de datos, mientras que safela alineación cambia el modo de alineación en situaciones de desbordamiento en un intento de evitar la pérdida de datos.

El comportamiento predeterminado es contener el tema de alineación dentro del área desplazable, aunque en el momento de escribir este artículo esta característica de seguridad aún no está implementada.

safe

Si el tamaño del [elemento flexible] desborda el [contenedor flexible], el [elemento flexible] se alinea como si el modo de alineación fuera [ flex-start].

unsafe

Independientemente de los tamaños relativos de [elemento flexible] y [contenedor flexible], se respeta el valor de alineación dado.

Nota: El módulo de alineación de cajas se utiliza en varios modelos de diseño de cajas, no solo en flex. Entonces, en el extracto de especificaciones anterior, los términos entre paréntesis en realidad dicen "asunto de alineación", "contenedor de alineación" y " start". Utilicé términos específicos de flex para mantener el foco en este problema en particular.


Explicación de la limitación de desplazamiento de MDN:

Consideraciones sobre elementos flexibles

Las propiedades de alineación de Flexbox realizan un centrado "verdadero", a diferencia de otros métodos de centrado en CSS. Esto significa que los elementos flexibles permanecerán centrados, incluso si desbordan el contenedor flexible.

Sin embargo, esto a veces puede ser problemático si se desbordan más allá del borde superior de la página o del borde izquierdo [...], ya que no puede desplazarse a esa área, incluso si hay contenido allí.

En una versión futura, las propiedades de alineación se ampliarán para tener también una opción "segura".

Por ahora, si esto le preocupa, puede utilizar márgenes para lograr el centrado, ya que responderán de forma "segura" y dejarán de centrarse si se desbordan.

En lugar de utilizar las align-propiedades, simplemente coloque automárgenes en los elementos flexibles que desea centrar.

En lugar de las justify-propiedades, coloque márgenes automáticos en los bordes exteriores del primer y último elemento flexible en el contenedor flexible.

Los automárgenes se "flexionarán" y asumirán el espacio sobrante, centrando los elementos flexibles cuando quede espacio sobrante y cambiando a la alineación normal cuando no.

Sin embargo, si está intentando reemplazar justify-contentcon centrado basado en márgenes en una caja flexible de varias líneas, probablemente no tenga suerte, ya que necesita colocar los márgenes en el primer y último elemento flexible de cada línea. A menos que pueda predecir de antemano qué elementos terminarán en qué línea, no podrá utilizar de manera confiable el centrado basado en márgenes en el eje principal para reemplazar la justify-contentpropiedad.

Michael Benjamin avatar Oct 31 '2015 18:10 Michael Benjamin

Logré lograr esto con solo 3 contenedores. El truco consiste en separar el contenedor flexbox del contenedor que controla el desplazamiento. Por último, coloque todo en un recipiente raíz para centrarlo todo. Estos son los estilos esenciales para crear el efecto:

.root {
  display: flex;
  justify-content: center;
  align-items: center;
}

.scroll-container {
  margin: auto;
  max-height: 100%;
  overflow: auto;
}

.flex-container {
  display: flex;
  flex-direction: column;
  justify-content: center;
}
<div class="root">
  <div class="scroll-container">
    <div class="flex-container">
      <p>Lorem ipsum dolor sit amet.</p>
    </div>
  </div>
</div>
Expandir fragmento

Creé una demostración aquí: https://jsfiddle.net/r5jxtgba/14/

varogen avatar Dec 11 '2017 19:12 varogen