Mi posición: el elemento adhesivo no es adhesivo cuando se usa flexbox

107

Estuve atascado en esto por un tiempo y pensé en compartir esto position: sticky+ flexbox gotcha:

Mi div pegajoso funcionaba bien hasta que cambié mi vista a un contenedor de caja flexible, y de repente el div no estaba pegajoso cuando estaba envuelto en un padre flexbox.

.flexbox-wrapper {
  display: flex;
  height: 600px;
}
.regular {
  background-color: blue;
}
.sticky {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  background-color: red;
}
<div class="flexbox-wrapper">
  <div class="regular">
    This is the regular box
  </div>
  <div class="sticky">
    This is the sticky box
  </div>
</div>

JSFiddle mostrando el problema

BHOLT
fuente
¿Este comportamiento persiste en todos los navegadores compatibles position: stickyo solo en uno o algunos?
TylerH
1
@TylerH Creo que son todos los navegadores. Funcionó así tanto en Chrome como en Safari.
BHOLT
Gracias. También puedo confirmar que el problema y la solución se encuentran en Firefox.
TylerH

Respuestas:

205

Dado que los elementos de caja flexible están predeterminados stretch, todos los elementos tienen la misma altura, por lo que no se puede desplazar.

Al agregar align-self: flex-startal elemento adhesivo, establezca la altura en automático, lo que permitió el desplazamiento y lo corrigió.

Actualmente, esto es compatible con todos los navegadores principales, pero Safari todavía tiene un -webkit-prefijo y otros navegadores, excepto Firefox, tienen algunos problemas con las position: stickytablas.

.flexbox-wrapper {
  display: flex;
  overflow: auto;
  height: 200px;          /* Not necessary -- for example only */
}
.regular {
  background-color: blue; /* Not necessary -- for example only */
  height: 600px;          /* Not necessary -- for example only */
}
.sticky {
  position: -webkit-sticky; /* for Safari */
  position: sticky;
  top: 0;
  align-self: flex-start; /* <-- this is the fix */
  background-color: red;  /* Not necessary -- for example only */
}
<div class="flexbox-wrapper">
  <div class="regular">
    This is the regular box
  </div>
  <div class="sticky">
    This is the sticky box
  </div>
</div>

JSFiddle mostrando la solución

BHOLT
fuente
26
esto solo funciona cuando se desplaza dentro del elemento flexible que lo contiene; cuando se desplaza por toda la ventana, NO se pega (al menos en Firefox), por lo que para aquellos que están experimentando un comportamiento contradictorio, es más probable que esté experimentando expectativas contradictorias (como yo fue)
aequalsb
@aequalsb ¿Conoce alguna forma de hacer que se pegue al desplazarse por toda la página?
Douglas Gaskell
@Douglas la pregunta es engañosa porque sugiere que el problema está en flexboxpero el problema tiene más que ver con contener el stickyelemento. mire este violín: jsfiddle.net/9y87zL5c donde la SEGUNDA caja roja funciona como se esperaba pero la PRIMERA caja roja no se pega, así que ... esto no está relacionado con flexbox (por lo tanto, expectativas contradictorias) ... TAMBIÉN ... i agregó un montón de jabberwocky para ver los resultados de una manera más precisa.
aequalsb
28

En mi caso, se le había overflow-x: hidden;aplicado uno de los contenedores principales , lo que interrumpirá la position: stickyfuncionalidad. Deberá eliminar esa regla.

Ningún elemento padre debe tener aplicada la regla CSS anterior. Esta condición se aplica a todos los padres hasta (pero sin incluir) el elemento 'cuerpo'.

TheoPlatica
fuente
Tampoco puede tener overflow-x:hiddenen el elemento html.
Samuel Liew
Muchas gracias. SIEMPRE lucho con la posición pegajosa y no sabía de esta condición hasta que leí su respuesta. :)
Raphael Aleixo
@SamuelLiew, sí, puedes tenerlo overflow-x: hidden;en el elemento HTML.
TheoPlatica
@RaphaelAleixo Me alegro de haber podido ayudar :)
TheoPlatica
Esto es lo que me impedía que un adhesivo funcionara correctamente. ¡Muchas gracias!
MoOx
7

También puede intentar agregar un div hijo al elemento flexible con el contenido dentro y asignarlo position: sticky; top: 0;.

Eso funcionó para mí para un diseño de dos columnas donde el contenido de la primera columna necesitaba ser pegajoso y la segunda columna parecía desplazable.

Simon_Weaver
fuente
Totalmente de acuerdo, esta es la opción más simple y confiable que pude encontrar. De esta forma también podrás controlar cuándo dejar de pegar controlando la altura del recipiente.
Ibrahim ben Salah
0

Hice una mesa flexible improvisada y tuve este problema. Para resolverlo, simplemente coloco la fila del encabezado adhesivo fuera del flexbox, justo antes.

Andrés
fuente
0

Para mi situación, la solución align-self: flex-start(o justify-self: flex-start) no funciona. También necesito mantenerme overflow-x: hidden, ya que algunos contenedores se deslizan horizontalmente.

Mi solución requerida anidado display: flexcon overflow-y: autoconseguir los comportamientos deseados:

  • El encabezado puede ajustar la altura dinámicamente, lo que evita jugar con position: absoluteoposition: fixed
  • el contenido se desplaza verticalmente, restringido horizontalmente al ancho de la vista
  • El elemento adhesivo puede estar en cualquier lugar verticalmente, pegado a la parte inferior del encabezado.
  • otros elementos pueden deslizarse horizontalmente
    • parece que la herramienta de fragmentos SO no se puede representar widthen elementos secundarios para demostrar correctamente la diapositiva horizontal, o tal vez haya alguna otra configuración en mi diseño real que lo haga funcionar ...
    • tenga en cuenta que se requiere un elemento contenedor que no hace nada más para permitir overflow-x: autoque funcione correctamente en elementos bajo un padre conoverflow-x: hidden

body {
  height: 100vh;
  width: 100vw;
  display: flex;
  flex-direction: column;
}

body>header {
  background-color: red;
  color: white;
  padding: 1em;
}

.content {
  overflow-x: hidden;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}

article {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

.horizontal_slide {
  display: flex;
  overflow-x: auto;
  background-color: lightblue;
  padding: .5em;
}

.horizontal_slide>* {
  width: 1000px;
}

.toolbar {
  position: sticky;
  top: 0;
  z-index: 10;
  background-color: lightgray;
  padding: .5em;
  display: flex;
}
<header>Fancy header with height adjusting to variable content</header>
<div class="content">
  <article class="card">
    <h1>One of several cards that flips visibility</h1>
    <div class="overflow_x_wrapper">
      <div class="horizontal_slide">
        <div>Reason why `overflow-x: hidden` on the parent is required
        </div>
        <div>Reason why `overflow-x: hidden` on the parent is required
        </div>
        <div>Reason why `overflow-x: hidden` on the parent is required
        </div>
      </div>
      <div class="toolbar">Sticky toolbar part-way down the content</div>
      <p>Rest of vertically scrollable container with variable number of child containers and other elements</p>
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
        dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
  </article>
  </div>

OXIGEN
fuente