La siguiente es una publicación invitada de Agop Shirinian. Agop se encontró con un escenario interesante en el que necesitaba que un elemento fuera desplazable en una dirección, mientras permitía el desbordamiento en la otra dirección. Uno pensaría que para eso son overflow-x y overflow-y, pero no es tan simple. Dejaré que Agop lo explique.
Por lo tanto, tiene la tarea de crear un menú desplazable con submenús que aparecen cuando se desplaza sobre un elemento del menú principal.
¡Simple!
Cree una lista para el menú, agregue algunas listas anidadas para los submenús, coloque las listas anidadas según los elementos de la lista principal, ¡voilà!
Vea el menú desplazable del lápiz con submenús emergentes (roto) de Agop (@agop) en CodePen.
Espera, eso no está bien. Oh, por supuesto, usamos overflow: auto
– tal vez si usamos overflow-x: visible
, el desbordamiento horizontal de los submenús será visible:
Vea el menú desplazable del lápiz con submenús emergentes (roto # 2) de Agop (@agop) en CodePen.
¿Lo que da? ¿Por qué todavía tenemos barras de desplazamiento?
El problema
Si miramos la especificación W3C, encontramos la siguiente explicación:
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 uno se especifica como ‘visible’ y el otro es ‘scroll’ o ‘auto’, entonces ‘visible’ se establece en ‘auto’.
Básicamente, esto:
overflow-x: visible;
overflow-y: auto;
Se convierte en esto:
overflow-x: auto;
overflow-y: auto;
Por lo tanto, no podemos tener un desbordamiento horizontal visible si el desbordamiento vertical es invisible y viceversa.
Y si no podemos tener un desbordamiento horizontal visible, ¡no podemos tener nuestros submenús emergentes!
La solución
Curiosamente, si omitimos el position: relative
desde los elementos del menú, aparecen los submenús, posicionados en función de su antecesor posicionado más cercano. En este caso, no tienen un antepasado posicionado, por lo que se ubican en relación con <body>
:
Consulte el menú desplegable Pen con submenús emergentes (paso 1) de Agop (@agop) en CodePen.
Básicamente, para que un elemento absolutamente posicionado aparezca fuera de un elemento con overflow: hidden
, su antepasado posicionado más cercano también debe ser un antepasado del elemento con overflow: hidden
.
Sabiendo esto, podemos agregar un envoltorio alrededor de los menús para que actúe como el ancestro posicionado más cercano para cada submenú. Luego, cada vez que el usuario se desplaza sobre un elemento del menú, podemos colocar los envoltorios del submenú usando un poco de JavaScript:
Vea el menú desplegable Pen con submenús emergentes de Agop (@agop) en CodePen.
¡Y eso es! Dado que ni los menús ni los elementos del menú están ubicados, los submenús pueden salir del desbordamiento oculto / desplazable. Ahora podemos tener tantos niveles de submenús anidados como queramos, y no obtendremos ningún recorte no deseado.
Quitar
Desafortunadamente, este método de mostrar elementos que de otro modo estarían ocultos es muy oscuro.
Sería bueno si pudiéramos especificar una profundidad de recorte, que controlaría qué antepasado en la jerarquía sería responsable de recortar un elemento en particular:
./* Fair warning: not real code */
.submenu {
/* only an ancestor 2 levels up can clip this element */
clip-depth: 2;
}
O, mejor aún, quizás podríamos especificar el padre de recorte mediante un selector de CSS:
/* Fair warning: not real code */
.submenu {
/* only an ancestor that matches the .panel selector can clip this element */
clip-parent: .panel;
}