Este capitulo habla sobre:
- Los tipos de posicionamiento de elementos: fixed, relative y absolute
- Construyendo cuadros de diálogo modales y menús desplegables
- Triángulos CSS
- Comprender el z-index y los stacking contexts
- Un nuevo tipo de posicionamiento: sticky
Ahora hemos analizado varias formas de controlar el diseño de la página, desde la visualización de la tabla hasta el flexbox
y los floats. En este capítulo, veremos una técnica importante: la propiedad de position
, que puede usar para crear menús desplegables, cuadros de diálogo modales y otros efectos esenciales para las aplicaciones web modernas.
El posicionamiento puede complicarse. Es un tema en el que muchos desarrolladores solo tienen una comprensión superficial. Sin una comprensión completa del posicionamiento y las ramificaciones involucradas, es fácil meterse en un agujero. Puede encontrarse con los elementos equivocados frente a otros y corregir el problema no siempre es sencillo.
A medida que analizamos los distintos tipos de posicionamiento, me aseguraré de que comprenda con precisión lo que hacen. Luego, aprenderá sobre algo llamado stacking context (contexto de apilamiento), que es una especie de efecto secundario oculto del posicionamiento. Comprender el contexto de apilamiento lo mantendrá fuera de problemas, y si alguna vez se encuentra "en medio de la maleza" con un diseño de página, este conocimiento le brindará las herramientas que necesita para volver a encarrilarse.
El valor inicial de la propiedad position
es static
. Todo lo que hemos hecho en capítulos anteriores es con posicionamiento estático. Cuando cambia este valor por cualquier otro, se dice que el elemento está positioned. Por tanto, un elemento con posicionamiento estático está not positioned.
Los métodos de diseño que hemos cubierto en capítulos anteriores hacen varias cosas para manipular la forma en que se comporta el flujo de documentos. El posicionamiento es diferente: elimina elementos del flujo de documentos por completo. Esto le permite colocar el elemento en otro lugar de la pantalla. Puede colocar elementos uno delante o detrás del otro, superponiéndose así.
7.1. POSICIONAMIENTO FIJO
El posicionamiento fijo, aunque no es tan común como algunos de los otros tipos de posicionamiento, es probablemente el más simple de entender, así que comenzaremos por ahí. Aplicar position: fixed
a un elemento le permite colocar el elemento arbitrariamente dentro de la ventana gráfica. Esto se hace con cuatro propiedades complementarias: top
, right
, bottom
y left
. Los valores que asigna a estas propiedades especifican qué tan lejos debe estar el elemento fijo de cada borde de la ventana del navegador. Por ejemplo, top: 3em
en un elemento fijo significa que su borde superior estará a 3em
de la parte superior de la ventana gráfica.
Al establecer estos cuatro valores, también define implícitamente el ancho y el alto del elemento. Por ejemplo, especificando left: 2em; right: 2em
significa que el borde izquierdo del elemento estará a 2em
del lado izquierdo de la ventana gráfica y el borde derecho estará a 2em
del lado derecho; por lo tanto, el elemento será 4em
menos que el ancho total de la ventana gráfica. Lo mismo ocurre con la parte superior, inferior y la altura de la ventana gráfica.
7.1.1. Creando un diálogo modal con posicionamiento fijo
Usemos estas propiedades para construir el modal dialog box (cuadro de dialogo modal) que se muestra en la figura 7.1. Este cuadro de diálogo aparecerá frente al contenido de la página, ocultándolo de la vista hasta que se cierre el cuadro de diálogo.

Por lo general, usará un cuadro de diálogo modal para solicitar al usuario que lea algo o que ingrese algo antes de continuar. Por ejemplo, este modal (figura 7.1) muestra un formulario donde un usuario puede suscribirse a un boletín. Inicialmente, ocultará el cuadro de diálogo con display: none
, y luego usará un poco de JavaScript para cambiar su valor a block
con el fin de abrir el modal.
Cree una nueva página y agregue la siguiente lista al elemento <body>
. Coloca el contenido dentro de dos elementos que lo contienen y usa una etiqueta <script>
con algo de JavaScript para proporcionar una funcionalidad básica.
<header class="top-banner">
<div class="top-banner-inner">
<p>Find out what's going on at Wombat Coffee each
month. Sign up for our newsletter:
<button id="open">Sign up</button> 1
</p>
</div>
</header>
<div class="modal" id="modal"> 2
<div class="modal-backdrop"></div> 3
<div class="modal-body"> 4
<button class="modal-close" id="close">close</button>
<h2>Wombat Newsletter</h2>
<p>Sign up for our monthly newsletter. No spam.
We promise!</p>
<form>
<p>
<label for="email">Email address:</label>
<input type="text" name="email"/>
</p>
<p><button type="submit">Submit</button></p>
</form>
</div>
</div>
<script type="text/javascript">
var button = document.getElementById('open');
var close = document.getElementById('close');
var modal = document.getElementById('modal');
button.addEventListener('click', function (event) { 5
event.preventDefault(); 5
modal.style.display = 'block'; 5
}); 5
close.addEventListener('click', function (event) { 6
event.preventDefault(); 6
modal.style.display = 'none'; 6
}); 6
</script>
Listado 7.1. Crear un cuadro de diálogo modal
- Botón para activar el modal
- Container para el modal
- Un "telón de fondo" para ocultar el contenido detrás del modal
- Contenidos modales
- Abre el modal cuando el usuario hace clic en el botón Registrarse
- Cierra el modal cuando el usuario hace clic en el botón Cerrar
El primer elemento de esta lista es un banner en la parte superior de la página. Contiene el botón que activa el modal. El segundo elemento es el diálogo modal. Incluye un telón de fondo modal modal-backdrop
vacío, que utilizará para ocultar el resto de la página y atraer la atención del usuario al contenido del cuadro de diálogo. Los contenidos están dentro de un elemento de modal-body
.
El CSS para implementar esto se muestra a continuación. Agréguelo a su hoja de estilo. Incluye un estilo básico para el banner superior, así como los estilos para el modal.
body {
font-family: Helvetica, Arial, sans-serif;
min-height: 200vh; 1
margin: 0;
}
button {
padding: 0.5em 0.7em;
border: 1px solid #8d8d8d;
background-color: white;
font-size: 1em;
}
.top-banner {
padding: 1em 0;
background-color: #ffd698;
}
.top-banner-inner {
width: 80%;
max-width: 1000px;
margin: 0 auto;
}
.modal {
display: none; 2
}
.modal-backdrop { 3
position: fixed; 3
top: 0; 3
right: 0; 3
bottom: 0; 3
left: 0; 3
background-color: rgba(0, 0, 0, 0.5);
}
.modal-body { 4
position: fixed; 4
top: 3em; 4
bottom: 3em; 4
right: 20%; 4
left: 20%; 4
padding: 2em 3em;
background-color: white;
overflow: auto; 5
}
.modal-close {
cursor: pointer;
}
Listado 7.2. Agregar estilos modales
- Fuerza la altura de la página para permitir el desplazamiento (solo para fines de demostración)
- Oculta el modal por defecto; JavaScript establecerá
display: block
cuando abra el modal. - Utiliza un fondo semitransparente para ocultar el resto de la página mientras el modal está abierto
- Posiciona la parte principal del modal
- Permite que el cuerpo modal se desplace, si es necesario
En este CSS, ha utilizado el posicionamiento fijo dos veces. Primero en el modal-backdrop
con cada uno de los cuatro lados establecidos en 0. Esto hace que el telón de fondo llene toda la ventana gráfica. Le has dado un color de fondo de rgba (0, 0, 0, 0.5)
. Esta notación de color especifica valores de rojo, verde y azul de 0, que se evalúan como negro. El cuarto valor es el canal "alfa", que especifica su transparencia: un valor de 0 es completamente transparente y 1 es completamente opaco. El valor 0.5
es semitransparente. Esto sirve para oscurecer todo el contenido de la página detrás del elemento.
El segundo lugar en el que usó el posicionamiento fijo es en modal-body
. Ha colocado cada uno de sus cuatro lados dentro de la ventana gráfica: 3em
desde los bordes superior e inferior y el 20%
desde los lados izquierdo y derecho. También establece un color de fondo blanco. Esto hace que el modal sea un cuadro blanco, centrado en la pantalla. Puede desplazarse por la página como desee, pero el fondo y el cuerpo modal permanecen en su lugar.
Cargue la página y verá un banner amarillo pálido en la parte superior de la pantalla con un botón. Haga clic en el botón para abrir el modal posicionado. Debido al posicionamiento fijo, el modal permanece en su lugar, incluso cuando se desplaza por la página (el gran valor de min-height
en el cuerpo permite el desplazamiento para ilustrar este comportamiento).
Haga clic en el botón cerrar en la parte superior del modal para cerrarlo. Este botón se encuentra ahora en una ubicación extraña, pero regresaremos y lo colocaremos en un momento.
7.1.2. Controlar el tamaño de los elementos posicionados
Al colocar un elemento, no es necesario que especifique valores para los cuatro lados. Puede especificar solo los lados que necesita y luego usar el width
y / o height
para ayudar a determinar su tamaño. También puede permitir que el elemento se dimensione de forma natural. Considere estas declaraciones:
position: fixed;
top: 1em;
right: 1em;
width: 20%
Estos fijarían el elemento 1em
desde los bordes superior y derecho de la ventana gráfica con un ancho del 20%
del ancho de la ventana gráfica. Al omitir las propiedades bottom
y height
, la altura del elemento será determinada naturalmente por su contenido. Esto se puede utilizar para colocar un menú de navegación en la pantalla, por ejemplo. Permanecerá en su lugar incluso cuando el usuario se desplace hacia abajo por el contenido de la página.
Debido a que un elemento fijo se elimina del flujo de documentos, ya no afecta la posición de otros elementos en la página. Seguirán el flujo normal de documentos como si no estuviera allí, lo que significa que a menudo fluirán detrás del elemento fijo, ocultos a la vista. Esto suele estar bien con un diálogo modal porque desea que esté al frente y al centro hasta que el usuario lo descarte.
Con algo persistente, como un menú de navegación lateral, deberá tener cuidado de que no fluya otro contenido detrás de él. Por lo general, esto es más fácil de hacer agregando un margen al contenido. Por ejemplo, coloque todo su contenido en un contenedor con un right-margin: 20%
. Este margen fluirá detrás de su elemento fijo y el contenido no se superpondrá.
7.2. POSICIONAMIENTO ABSOLUTO
El posicionamiento fijo, como acaba de ver, le permite colocar un elemento en relación con la ventana gráfica. A esto se le llama containing block. La declaración left: 2em
, por ejemplo, coloca el borde izquierdo de un elemento posicionado a 2em
del borde izquierdo del bloque contenedor.
El posicionamiento absoluto funciona de la misma manera, excepto que tiene un bloque de contención diferente. En lugar de que su posición se base en la ventana gráfica, su posición se basa en el elemento ancestro posicionado más cercano. Al igual que con un elemento fijo, las propiedades top
, right
, bottom
e left
colocan los bordes del elemento dentro de su bloque contenedor.
7.2.1. Posicionamiento absoluto del botón Cerrar
Para ver cómo funciona, cambiemos la posición del botón Cerrar a la esquina superior derecha de su cuadro de diálogo modal. Después de hacerlo, el modal se verá como la figura 7.2.

Para hacer esto, declarará la posición absoluta para el botón Cerrar. Su elemento padre es modal-body
, que tiene un posicionamiento fijo, por lo que se convierte en el bloque contenedor del botón. Edite los estilos de su botón para que coincidan con la lista 7.3.
.modal-close {
position: absolute;
top: 0.3em;
right: 0.3em;
padding: 0.3em;
cursor: pointer;
}
Listado 7.3. Botón de cierre absolutamente posicionado
Esta lista coloca el botón 0.3em
desde la parte superior y 0.3em
desde la derecha del modal-body
. Normalmente, como en este ejemplo, el bloque contenedor será el padre del elemento. En los casos en los que el elemento principal no está posicionado, el navegador buscará la jerarquía DOM en el abuelo, bisabuelo, etc. hasta que se encuentre un elemento posicionado, que luego se utiliza como bloque contenedor.
Si ninguno de los antepasados del elemento está posicionado, entonces el elemento posicionado absolutamente se colocará en función de algo llamado initial containing block. Esta es un área con dimensiones iguales al tamaño de la ventana gráfica, anclada en la parte superior de la página.
7.2.2. Posicionando un pseudo-elemento
Ha colocado el botón Cerrar donde lo desea, pero es bastante espartano. Para un botón Cerrar como este, los usuarios normalmente esperan ver alguna indicación gráfica como una x como en la figura 7.3.
Su primera tentación puede ser eliminar la palabra cerrar de su marcado y reemplazarla con una x, pero esto introduciría un problema de accesibilidad: los lectores de pantalla de asistencia leen el texto del botón, por lo que debería dar una indicación significativa del propósito del botón. El HTML debe tener sentido por sí solo antes de aplicar CSS.
En su lugar, puede utilizar CSS para ocultar la palabra close y mostrar una x. Lo logrará haciendo dos cosas. Primero, presionará el texto del botón fuera del botón y ocultará el desbordamiento. En segundo lugar, usará la propiedad de content
para agregar la x al pseudoelemento ::after
del botón y al posicionamiento absoluto para centrarlo dentro del botón. Actualice los estilos de sus botones para que coincidan con la lista 7.4.
En lugar de la letra x, recomiendo el carácter Unicode para el signo de multiplicación. Es más simétrico y, por lo general, más agradable estéticamente para este propósito. El carácter HTML (×)
se representará como este carácter, pero en la propiedad de CSS content
, debe utilizar el número Unicode de escape: \00D7
.
.modal-close {
position: absolute;
top: 0.3em;
right: 0.3em;
padding: 0.3em;
cursor: pointer;
font-size: 2em;
height: 1em; 1
width: 1em; 1
text-indent: 10em; 2
overflow: hidden; 2
border: 0;
}
.modal-close::after {
position: absolute;
line-height: 0.5;
top: 0.2em;
left: 0.1em;
text-indent: 0;
content: "\00D7"; 3
}
Listado 7.4. Reemplazo del botón Cerrar con una x
- Hace que el botón sea un pequeño cuadrado
- Obliga al texto a desbordar el elemento y lo oculta
- Agrega el carácter Unicode U + 00D7 (signo de multiplicación)
Esta lista establece explícitamente el tamaño del botón en 1em
cuadrado. La propiedad text-indent
luego empuja el texto hacia la derecha, fuera del elemento. El valor exacto no importa siempre que sea mayor que el ancho del botón. Luego, debido a que text-indent
es una propiedad heredada, la restableces a 0 en la pseudoclase para que la x no tenga sangría.
La pseudoclase ahora está absolutamente posicionada. Se comporta como un elemento hijo del botón, por lo que el botón que se coloca se convierte en el bloque contenedor de su pseudoelemento. La line-height
evita que el pseudoelemento sea demasiado alto, y las propiedades top
y left
lo colocan en el centro del botón. Llegué a los valores exactos aquí a través de un poco de prueba y error; Le animo a experimentar con esos valores en las herramientas de desarrollo de su navegador para ver cómo afectan el posicionamiento.
El posicionamiento absoluto es el peso pesado entre los tipos de posicionamiento. Se utiliza a menudo junto con JavaScript para mostrar menús, información sobre herramientas y cuadros de "información". Lo usaremos para crear un menú desplegable, pero para hacerlo, deberá echar un vistazo a su compañero, el posicionamiento relativo.
7.3. POSICIONAMIENTO RELATIVO
El posicionamiento relativo es probablemente el tipo de posicionamiento menos comprendido. Cuando aplica por primera vez position: relative
a un elemento, normalmente no verá ningún cambio visible en la página. El elemento relativamente posicionado, y todos los elementos de la página que lo rodean, permanecerán exactamente donde estaban (aunque es posible que veas algunos cambios con respecto a qué elementos están frente a cada uno. Llegaremos a eso en un momento).
Las propiedades top
, right
, bottom
e left
, si se aplican, desplazarán el elemento de su posición original, pero no cambiarán la posición de ningún elemento a su alrededor. Consulte la figura 7.4 para ver un ejemplo. Muestra cuatro elementos inline-block. Apliqué tres propiedades adicionales al segundo elemento: position: relative; top; 1em; left: 2em
. Como puede ver, esto ha desplazado el elemento de su posición inicial, pero los otros elementos no se ven afectados. Todavía siguen el flujo de documentos normal alrededor de la posición inicial del elemento desplazado.

Aplicar top: 1em
mueve el elemento hacia abajo 1em
(lejos de su borde superior original). Y a la left: 2em
desplaza el elemento a la derecha 2em
(lejos de su borde izquierdo original). Estos cambios pueden hacer que ese elemento se superponga a elementos debajo o al lado de él. Al posicionar, también se admiten valores negativos, por lo que bottom: -1em
desplazaría el elemento 1em
hacia abajo, tal como lo hace top: 1em
.
A diferencia del posicionamiento fijo y absoluto, no puede utilizar top
, right
, bottom
e left
para cambiar el tamaño de un elemento posicionado relativamente. Esos valores solo cambiarán la posición del elemento hacia arriba o hacia abajo, hacia la izquierda o hacia la derecha. Puede usar top
o bottom
, pero no ambos juntos (se ignorará el bottom
); del mismo modo, puede utilizar left
o right
, pero no ambas (se ignorará la right
).
El uso de estas propiedades para ajustar la posición de un elemento relativo puede ser útil para empujar un elemento en su lugar en ocasiones, pero a decir verdad, esta es la razón por la que rara vez utilizará el posicionamiento relativo. Con mucha más frecuencia, usará position: relative
para establecer el bloque contenedor para un elemento absolutamente posicionado dentro de él.
7.3.1. Crear un menú desplegable
Usemos el posicionamiento relativo y absoluto para crear un menú desplegable. Inicialmente será un rectángulo simple, pero cuando el usuario pasa el mouse sobre él, se abre una lista de enlaces como los que se muestran en la figura 7.5.

El Listado 7.5 muestra el marcado para este menú. Añádalo a su HTML después del cierre </div>
del elemento <div class = "modal">
. Este código incluye un contenedor que usará para centrar el contenido y alinearlo con el contenido del banner. También agregué un <h1>
debajo de la ventana emergente para ilustrar cómo aparece la ventana emergente frente a otro contenido en la página.
<div class="container">
<nav>
<div class="dropdown"> 1
<div class="dropdown-label">Main Menu</div> 2
<div class="dropdown-menu"> 3
<ul class="submenu"> 3
<li><a href="/">Home</a></li> 3
<li><a href="/coffees">Coffees</a></li> 3
<li><a href="/brewers">Brewers</a></li> 3
<li><a href="/specials">Specials</a></li> 3
<li><a href="/about">About us</a></li> 3
</ul> 3
</div> 3
</div>
</nav>
<h1>Wombat Coffee Roasters</h1>
</div>
Listado 7.5. Agregar el HTML del menú desplegable
- Contenedor para el menú desplegable
- Label siempre estará visible.
- Div para mostrar y ocultar a medida que se abre y se cierra el menú
El contenedor desplegable incluye dos elementos secundarios: label, un rectángulo gris que siempre está visible y el menú desplegable que se mostrará y ocultará a medida que se abra y se cierre el menú desplegable. El menú desplegable estará absolutamente posicionado para que no se mueva alrededor del diseño de la página cuando se revele. Esto significa que aparece frente a otro contenido cuando está visible.
A continuación, aplicará la posición relativa al contenedor desplegable. Esto establece el bloque contenedor para el menú absolutamente posicionado. Agregue estos estilos a su hoja de estilo.
.container {
width: 80%;
max-width: 1000px;
margin: 1em auto
}
.dropdown {
display: inline-block;
position: relative; 1
}
.dropdown-label {
padding: .5em 1.5em;
border: 1px solid #ccc;
background-color: #eee;
}
.dropdown-menu {
display: none; 2
position: absolute;
left: 0; 3
top: 2.1em; 3
min-width: 100%;
background-color: #eee;
}
.dropdown:hover .dropdown-menu { 4
display: block; 4
} 4
.submenu {
padding-left: 0;
margin: 0;
list-style-type: none;
border: 1px solid #999;
}
.submenu > li + li {
border-top: 1px solid #999;
}
.submenu > li > a {
display: block;
padding: .5em 1.5em;
background-color: #eee;
color: #369;
text-decoration: none;
}
.submenu > li > a:hover {
background-color: #fff;
}
Listado 7.6. Abrir el menú desplegable al pasar el mouse
- Establece el bloque contenedor
- Oculta el menú inicialmente
- Coloca el menú debajo del menú desplegable
- Revela el menú al pasar el mouse
(hover)
Ahora, cuando mueve el puntero del mouse sobre la etiqueta del Menú principal, el menú desplegable se abre debajo de él. Observe que utilizó el estado :hover
de todo el contenedor para abrir el menú. Esto significa que mientras el cursor permanezca sobre cualquiera de sus contenidos, ya sea el dropdown-label
o el dropdown-menu
, el menú permanece abierto.
En el dropdown-menu
absolutamente posicionado, usó left: 0
para alinear su lado izquierdo con el lado izquierdo del menú desplegable. Luego usó top: 2.1em
para colocar su borde superior debajo de label (con el relleno y el borde, la etiqueta mide aproximadamente 2.1em
de alto). Un min-width
del 100% asegura que será al menos tan ancho como el contenedor desplegable (cuyo ancho está determinado por dropdown-label
). Luego usó la clase submenu
para diseñar el menú dentro del menú desplegable. (Si abre el cuadro de diálogo modal en este punto, es posible que observe que aparece detrás del menú desplegable de una manera extraña. Está bien; abordaremos ese problema pronto).
Para simplificar, el ejemplo del listado 7.6 usa una pseudoclase :hover
para abrir el menú cuando el usuario pasa el cursor del mouse sobre él. Este ejemplo no está completo. Por lo general, un enfoque más sólido sería usar JavaScript para agregar y eliminar una clase que controla si el menú está abierto. Esto le permite agregar un ligero retraso antes de abrir o cerrar el menú para evitar que el usuario lo active involuntariamente cuando pasa el mouse rápidamente.
Además, aunque el ejemplo aquí funciona con un mouse, no funcionará en algunos dispositivos con pantalla táctil (solo ciertos dispositivos con pantalla táctil activan el estado :hover
al tocar). Tampoco aborda los problemas de accesibilidad de un lector de pantalla o de la navegación por teclado. Sería prudente aumentar el menú desplegable para garantizar que los controles de la pantalla táctil funcionen y que el menú permanezca abierto cuando el usuario usa la tecla Tab para navegar por los enlaces del menú.
El JavaScript para hacer esto está más allá del alcance de este libro, pero si es experto en ello, puede abordar estas inquietudes con el código que escriba allí. Alternativamente, puede usar una biblioteca de terceros que proporcione una funcionalidad desplegable para encargarse de esto por usted, luego use CSS para personalizar su apariencia a su gusto.
7.3.2. Creando un triángulo CSS
Agreguemos un toque final a su menú desplegable. Funciona como está, pero es posible que el usuario no vea inmediatamente que hay más contenido que descubrir junto con la etiqueta del Menú principal. Agreguemos una pequeña flecha hacia abajo a la etiqueta para indicar que hay más para explorar.
Puedes usar un pequeño truco con bordes para dibujar un triángulo que sirva como flecha hacia abajo. Usarás el pseudoelemento ::after
de la etiqueta desplegable para dibujar el triángulo, luego usarás el posicionamiento absoluto para colocarlo en el lado derecho de la etiqueta.
La mayoría de las veces, cuando agrega bordes a un elemento, los hace delgados: generalmente 1px
o 2px
es suficiente. Pero observe lo que sucede cuando hace un borde mucho más grueso como se muestra en la figura 7.6. Hice que cada lado del borde tenga un color único para resaltar dónde termina un borde y comienza el siguiente.

Observe lo que sucede en las esquinas donde se unen los bordes de dos bordes: forman un borde diagonal. Ahora observe lo que sucede si encoge el elemento a una altura y un ancho de cero (figura 7.7). Todas las fronteras se unen y se unen en el medio.

El borde de cada lado del elemento forma un triángulo. El borde superior apunta hacia abajo; el borde derecho apunta a la izquierda, y así sucesivamente. Con esto en mente, puede usar un borde para darle el triángulo que necesita y luego establecer el color de los bordes restantes en transparente. Un elemento con bordes transparentes izquierdo y derecho y un borde superior visible se verá como la figura 7.8 un triángulo simple.

Apliquemos estilos al pseudoelemento dropdown-label::after
para hacer un triángulo y colocarlo usando posicionamiento absoluto. Agregue esto a su hoja de estilo.
.dropdown-label {
padding: 0.5em 2em 0.5em 1.5em; 1
border: 1px solid #ccc;
background-color: #eee;
}
.dropdown-label::after {
content: "";
position: absolute; 2
right: 1em; 2
top: 1em; 2
border: 0.3em solid; 3
border-color: black transparent transparent; 3
}
.dropdown:hover .dropdown-label::after {
top: 0.7em;
border-color: transparent transparent black; 4
}
Listado 7.7. Posicionamiento absoluto de un triángulo en la etiqueta desplegable
- Aumenta el relleno derecho para agregar espacio a la flecha
- Coloca el elemento en el lado derecho de la etiqueta.
- Utiliza el borde superior para formar una flecha hacia abajo
- Al pasar el mouse, cambia a una flecha hacia arriba
El pseudo-elemento no tiene contenido, por lo que no tiene alto ni ancho. Luego usó la propiedad abreviada border-color
para establecer el borde superior en negro y los bordes lateral y derecho transparentes, lo que le proporciona la flecha hacia abajo. Un poco de relleno adicional en la dropdown-label
deja espacio a la derecha, donde puede colocar el triángulo. El resultado final se muestra en la figura 7.9.

Cuando abre el menú, la flecha cambia de dirección y apunta hacia arriba para indicar que el menú se puede cerrar. El ligero cambio en el valor superior (de 1em
a 0.7em
) ayuda a que la flecha hacia arriba aparezca ópticamente en el mismo lugar que la flecha hacia abajo.
Alternativamente, puede agregar esta flecha con el uso de una imagen o imagen de fondo, pero unas pocas líneas adicionales de CSS pueden ahorrarle a sus usuarios la solicitud externa a través de la red. El resultado de esto es un pequeño toque final que puede agregar mucho brillo a su aplicación o sitio web.
Puede utilizar esta técnica para construir otras formas complicadas, como trapezoides, hexágonos y estrellas. Para obtener una lista de docenas de formas creadas en CSS, consulte https://css-tricks.com/examples/ShapesOfCSS/.
7.4. STACKING CONTEXT Y Z-INDEX
El posicionamiento es útil, pero es importante conocer las ramificaciones involucradas. Cuando elimina un elemento del flujo de documentos, se convierte en responsable de todas las cosas que el flujo de documentos normalmente hace por usted.
Debe asegurarse de que el elemento no se desborde accidentalmente fuera de la ventana del navegador y, por lo tanto, quede oculto para el usuario. Y debe asegurarse de que no cubra inadvertidamente el contenido importante que necesita ver.
Eventualmente, encontrará problemas con el apilamiento. Cuando coloca varios elementos en la misma página, puede encontrarse con un escenario en el que dos elementos colocados diferentes se superponen. Es posible que de vez en cuando se sorprenda al encontrar el "incorrecto" que aparece delante del otro. De hecho, en este capítulo, he creado intencionalmente un escenario de este tipo para ilustrar esto.
En la página que ha creado, haga clic en el botón Registrarse en el encabezado de la página para abrir el cuadro de diálogo modal. Si colocó el marcado para el menú desplegable después del modal en su HTML, se verá como la figura 7.10. Observe que el menú desplegable que agregó a la página ahora aparece frente al modal.

Puede abordar este problema de varias formas. Antes de llegar a eso, es importante comprender cómo el navegador determina el orden de apilamiento. Para eso, debemos observar más de cerca cómo el navegador representa una página.
7.4.1. Comprender el proceso de renderizado y el orden de apilamiento
A medida que el navegador analiza HTML en el DOM, también crea otra estructura de árbol llamada render tree (árbol de representación). Esto representa la apariencia visual y la posición de cada elemento. También es responsable de determinar el orden en el que el navegador pintará los elementos. Este orden es importante porque los elementos pintados más tarde aparecen frente a los elementos pintados anteriormente, en caso de que se superpongan.
En circunstancias normales (es decir, antes de aplicar el posicionamiento), este orden está determinado por el orden en que aparecen los elementos en el HTML. Considere los tres elementos en este fragmento de marcado:
<div>one</div>
<div>two</div>
6lt;div>three</div>
Su comportamiento de apilamiento se ilustra en la figura 7.11. He utilizado algunos márgenes negativos para obligarlos a superponerse, pero no les he aplicado ninguna posición. Los elementos que aparecen más adelante en el marcado están pintados sobre los anteriores.

Este comportamiento cambia cuando comienzas a colocar elementos. El navegador primero pinta todos los elementos no posicionados, luego pinta los posicionados. De forma predeterminada, cualquier elemento posicionado aparece delante de cualquier elemento no posicionado. En la figura 7.12, agregué position: relative
a los dos primeros elementos. Esto los lleva al frente, cubriendo el tercer elemento posicionado estáticamente, aunque el orden de los elementos en el HTML no cambia.

Observe que entre los elementos posicionados, el segundo elemento sigue apareciendo delante del primero. Los elementos colocados se llevan al frente, pero el apilamiento dependiente de la fuente entre ellos permanece sin cambios.
En su página, esto significa que tanto el menú modal como el desplegable aparecen frente al contenido estático (que desea), pero lo que aparece más adelante en su marcado se muestra frente al otro. Una forma de arreglar su página sería mover <div class = "modal">
y todo su contenido a algún lugar después del menú desplegable.
Normalmente, los modales se agregan al final de la página como el último fragmento de contenido antes de la etiqueta </body>
de cierre. La mayoría de las bibliotecas de JavaScript para crear cuadros de diálogo modales lo harán automáticamente. Debido a que el modal utiliza un posicionamiento fijo, no importa en qué parte del marcado aparezca; siempre estará ubicado en el centro de la pantalla.
Mover el elemento a otro lugar en el marcado tiende a ser inofensivo para el posicionamiento fijo, pero esta no es una solución que normalmente pueda utilizar para el posicionamiento relativo o absoluto. El posicionamiento relativo depende del flujo del documento y el posicionamiento absoluto depende de su elemento antecesor posicionado. Necesitamos una forma de controlar su comportamiento de apilamiento. Esto se hace mediante una propiedad denominada z-index
.
7.4.2. Manipulación del orden de apilamiento con z-index
La propiedad z-index
se puede establecer en cualquier número entero (positivo o negativo). Z se refiere a la dimensión de profundidad en un sistema de coordenadas cartesiano X-Y-Z. Los elementos con un índice Z más alto aparecen delante de los elementos con un índice Z más bajo. Los elementos con un índice Z negativo aparecen detrás de los elementos estáticos.
El uso del z-index
es el segundo enfoque que puede utilizar para solucionar el problema de apilamiento de su página. Este enfoque le da más libertad a la hora de estructurar el HTML. Apliquemos un z-index
de 1 al fondo modal y un z-index
de 2 al modal-body
(esto asegurará que el cuerpo aparezca frente al fondo). Actualice esta parte de su hoja de estilo para que coincida con la siguiente lista.
.modal-backdrop {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1; 1
}
.modal-body {
position: fixed;
top: 3em;
bottom: 3em;
right: 20%;
left: 20%;
padding: 2em 3em;
background-color: white;
overflow: auto;
z-index: 2; 2
}
Listado 7.8. Agregar z-index al cuadro de diálogo modal para llevarlo al frente del menú desplegable
- Trae el telón de fondo frente a elementos sin z-index
- Trae el cuerpo modal frente al telón de fondo
El z-index
parece sencillo, pero su uso presenta dos errores. Primero, el z-index
solo funciona en elementos posicionados. No puede manipular el orden de apilamiento de los elementos estáticos. En segundo lugar, la aplicación de un z-index
a un elemento posicionado establece algo llamado contexto de apilamiento.
7.4.3. Comprender los contextos de apilamiento
Un contexto de apilamiento consta de un elemento o un grupo de elementos que el navegador pinta juntos. Un elemento es la raíz del contexto de apilamiento, por lo que cuando agrega un z-index
a un elemento posicionado, ese elemento se convierte en la raíz de un nuevo contexto de apilamiento. Todos sus elementos descendientes son entonces parte de ese contexto de apilamiento.
Los contextos de apilamiento no deben confundirse con los contextos de formato de bloques (capítulo 4). Los dos son conceptos separados, aunque no necesariamente mutuamente excluyentes. Los contextos de apilamiento se ocupan de qué elementos están delante de otros elementos; Los contextos de formato de bloque se ocupan del flujo de documentos y de si los elementos se superpondrán o no.
El hecho de que todos los elementos del contexto de apilamiento estén pintados juntos tiene una ramificación importante: ningún elemento fuera del contexto de apilamiento puede apilarse entre dos elementos que estén dentro de él. Dicho de otra manera, si un elemento se apila delante de un contexto de apilamiento, ningún elemento dentro de ese contexto de apilamiento puede colocarse delante de él. Del mismo modo, si un elemento de la página se apila detrás del contexto de apilamiento, ningún elemento dentro de ese contexto de apilamiento se puede apilar detrás de ese elemento.
Esto puede ser un poco complicado de entender, así que vamos a armar un escenario para ilustrar esto. En una página HTML nueva, agregue este marcado.
<div class="box one positioned">
one
<div class="absolute">nested</div>
</div>
<div class="box two positioned">two</div>
<div class="box three">three</div>,
Listado 7.9. Ejemplo de apilamiento de contextos
Este marcado consta de tres casillas, dos de las cuales se colocarán y se les dará un z-index
de 1. El elemento absolute
dentro de la primera casilla se colocará y se le dará un z-index
de 100. A pesar de su alto z-index
, todavía aparece detrás del segundo cuadro porque su padre forma un contexto de apilamiento detrás del segundo cuadro (figura 7.13).

Los estilos para este escenario se encuentran en el listado 7.10. Aplica esto a tu página. La mayoría de estos estilos son para dimensionar y colorear para que el orden de apilamiento exacto sea claramente visible. Los márgenes negativos obligan a los elementos a superponerse. Las únicas declaraciones esenciales son position
y el z-index
para los distintos elementos.
body {
margin: 40px;
}
.box {
display: inline-block;
width: 200px;
line-height: 200px;
text-align: center;
border: 2px solid black;
background-color: #ea5;
margin-left: -60px;
vertical-align: top;
}
.one { margin-left: 0; }
.two { margin-top: 30px; }
.three { margin-top: 60px; }
.positioned { 1
position: relative; 1
background-color: #5ae; 1
z-index: 1; 1
} 1
.absolute {
position: absolute;
top: 1em;
right: 1em;
height: 2em;
background-color: #fff;
border: 2px dashed #888;
z-index: 100; 2
line-height: initial;
padding: 1em;
}
Listado 7.10. Creando los contextos de apilamiento
- Cada cuadro colocado establece un contexto de apilamiento con un
z-index
de 1. - Un
z-index
solo controla la posición de apilamiento del elemento dentro de su contexto de apilamiento.
La caja uno, apilada detrás de la caja dos, es la raíz de un contexto de apilamiento. Debido a esto, no se puede hacer que el elemento absolutamente posicionado dentro de él aparezca delante del cuadro dos, incluso con un valor de z-index
alto. Pruebe este ejemplo en las herramientas de desarrollo de su navegador para familiarizarse con las cosas. Manipule el z-index
de cada elemento para ver qué sucede.
Agregar un z-index
a un elemento posicionado es la forma más notable en que se crea un contexto de apilamiento, pero algunas otras propiedades también pueden crear uno. Una opacity
por debajo de 1 crea una, al igual que las propiedades de transform
o filter
. Estos afectan fundamentalmente cómo se representan el elemento y sus elementos secundarios, por lo que todos se pintan juntos. La raíz del documento (<html>)
; también crea un contexto de apilamiento de nivel superior para toda la página.
Todos los elementos dentro de un contexto de apilamiento se apilan en este orden, de atrás hacia adelante:
- El elemento raíz del contexto de apilamiento
- Elementos posicionados con un
z-index
negativo (junto con sus hijos) - Elementos no posicionados
- Elementos posicionados con un
z-index
deauto
(y sus hijos) - Elementos posicionados con un
z-index
positivo (y sus hijos)
Es fácil que una hoja de estilo se convierta en una guerra de z-index
, sin un orden claro en cuanto a la prioridad de varios componentes. Sin una guía clara, los desarrolladores que agregan a la hoja de estilo pueden agregar algo como un modal y, por temor a que aparezca detrás de otra cosa en la página, le darán un z-index
ridículamente alto, como 999999
. Después de que esto suceda algunas veces, nadie puede adivinar cuál debería ser el z-index
para otro componente nuevo.
Si utiliza un preprocesador como LESS o SASS (consulte el apéndice B), o si admite navegadores que admiten propiedades personalizadas (consulte el capítulo 2), utilícelo en su beneficio. Coloque todos sus valores de z-index
en variables, todo en un solo lugar. De esa manera, puede ver de un vistazo lo que se supone que debe aparecer frente a qué:
--z-loading-indicator: 100;
--z-nav-menu: 200;
--z-dropdown-menu: 300;
--z-modal-backdrop: 400;
--z-modal-body: 410;
Utilice incrementos de 10 o 100, de modo que pueda insertar nuevos valores en el medio en caso de que sea necesario.
Si alguna vez encuentra que el z-index
no se comporta como usted esperaría, busque el árbol DOM en los antepasados del elemento hasta que encuentre uno que sea la raíz de un contexto de apilamiento. Luego, use el z-index
para llevar todo el contexto de apilamiento hacia adelante o hacia atrás. Tenga cuidado, ya que puede encontrar varios contextos de apilamiento anidados entre sí.
Cuando la página es complicada, puede ser difícil determinar exactamente qué contexto de apilamiento es responsable del comportamiento que ves. Por esta razón, siempre tenga cuidado al crear un contexto de apilamiento. No cree uno a menos que tenga una razón específica para ello. Esto es doblemente cierto para los elementos que abarcan grandes porciones de la página. Cuando sea posible, lleve elementos posicionados independientes como modales al nivel superior del DOM, justo antes de la etiqueta </body>
; de cierre, para que no tenga que liberarlos de ningún contexto de apilamiento externo.
Algunos desarrolladores caen en la trampa de colocar una gran cantidad de elementos por toda la página. Deberías luchar contra este impulso. Cuanto más utilice el posicionamiento, más complicada se volverá la página y más difícil será depurarla. Si descubre que está posicionando docenas de elementos, dé un paso atrás y vuelva a evaluar la situación. Esto es particularmente importante si se encuentra luchando para que el diseño se comporte de la manera deseada. Cuando su diseño se pueda lograr usando otros métodos, debe usar esos métodos en su lugar.
Si puede hacer que el flujo del documento haga el trabajo por usted, en lugar de colocar cosas explícitamente, el navegador se encargará de muchos casos extremos por usted. Recuerde, el posicionamiento elimina elementos del flujo de documentos. En términos generales, solo debe hacer esto cuando necesite apilar elementos uno frente al otro.
7.5. STICKY POSITIONING
Los cuatro tipos principales de posicionamiento (static, fixed, absolute y relative) existen desde hace mucho tiempo, pero hay un nuevo tipo de posicionamiento que se abre paso en los navegadores: sticky positioning. Es una especie de híbrido entre posicionamiento relative y fixed: el elemento se desplaza normalmente con la página hasta que llega a un punto específico en la pantalla, momento en el que se "bloqueará" en su lugar mientras el usuario continúa desplazándose. El caso de uso común para esto es la navegación de la barra lateral.
El (sticky positioning) solo se admite en Firefox durante algún tiempo. Pero en el momento de escribir este artículo, esta función está disponible en los navegadores Chrome y Edge. Safari lo admite con el prefijo de proveedor (position: -webkit-sticky
). Asegúrese de consultar https://caniuse.com/#feat=css-sticky para obtener la información de soporte más reciente. Por lo general, utilizará el posicionamiento fijo o absoluto como comportamiento alternativo para otros navegadores.
Actualicemos su página que tiene el diálogo modal y el menú desplegable. Lo cambiará a un diseño de dos columnas, agregando una barra lateral de sticky-positioned como la columna de la derecha. Esto se verá como la captura de pantalla de la figura 7.14.

Cuando la página se carga inicialmente, la posición de la barra lateral parece rutinaria. Se desplazará normalmente con la página, hasta cierto punto. Tan pronto como esté a punto de salir de la ventana gráfica, se bloqueará en su lugar. Luego permanecerá allí como un elemento de posición fija, permaneciendo en la pantalla mientras el resto de la página continúa desplazándose. Después de desplazarse un poco hacia abajo en la página, se verá como la figura 7.15.

Reestructuraremos un poco su página para definir dos columnas. Edite el contenedor en su HTML para que coincida con la siguiente lista. Esto coloca su contenido existente (el menú desplegable y el encabezado de la página) en una columna de la izquierda y agrega una columna de la derecha con un menú de "affix.
<div class="container">
<main class="col-main"> 1
<nav>
<div class="dropdown">
<div class="dropdown-label">Main Menu</div>
<div class="dropdown-menu">
<ul class="submenu">
<li><a href="/">Home</a></li>
<li><a href="/coffees">Coffees</a></li>
<li><a href="/brewers">Brewers</a></li>
<li><a href="/specials">Specials</a></li>
<li><a href="/about">About us</a></li>
</ul>
</div>
</div>
</nav>
<h1>Wombat Coffee Roasters</h1>
</main>
<aside class="col-sidebar"> 2
<div class="affix"> 2
<ul class="submenu">
<li><a href="/">Home</a></li>
<li><a href="/coffees">Coffees</a></li>
<li><a href="/brewers">Brewers</a></li>
<li><a href="/specials">Specials</a></li>
<li><a href="/about">About us</a></li>
</ul>
</div>
</aside>
</div>
Listado 7.11. Cambiar a un diseño de dos columnas con una barra lateral
- Envuelve el contenido existente en una columna principal para la columna principal
- Agrega una segunda columna con un elemento de afijo en su interior
A continuación, actualizará el CSS para que el contenedor se convierta en un para dimensionar las dos columnas. Para esta demostración, reutilizará los estilos del submenú del menú desplegable, aunque puede agregar alternativamente los elementos y estilos que desee en la barra lateral. Agregue estos estilos a su hoja de estilo.
.container {
display: flex; 1
width: 80%;
max-width: 1000px;
margin: 1em auto;
min-height: 100vh; 2
}
.col-main {
flex: 1 80%; 3
}
.col-sidebar {
flex: 20%; 3
}
.affix {
position: sticky; 4
top: 1em; 4
}
Listado 7.12. Crear un diseño de dos columnas y un menú lateral de sticky-position
- Hace que el contenedor sea un contenedor flexible para el diseño de dos columnas
- Agrega altura artificialmente al contenedor
- Traza las dos columnas
- Aplica sticky-positioning al menú lateral. Se acoplará 1em desde la parte superior de la ventana gráfica.
La mayoría de estos cambios están configurando el diseño de dos columnas. Con eso establecido, solo se necesitan dos declaraciones para colocar el elemento affix
. El valor top
establece la ubicación donde el elemento se bloqueará en su lugar: 1em
desde la parte superior de la ventana gráfica.
col-sidebar
en este caso. A medida que se desplaza hacia abajo en la página, la col-sidebar
siempre se desplazará normalmente, pero el elemento de affix
se desplazará hasta que encaje en su lugar. Continúe desplazándose lo suficiente y se desbloqueará y reanudará el desplazamiento. Esto ocurre cuando el borde inferior del padre llega al borde inferior del menú fijo. Tenga en cuenta que el padre debe ser más alto que el elemento sticky para que se adhiera en su lugar, por lo que aumenté artificialmente su altura agregando una min-height
a su contenedor flexible.
RESUMEN
- Utilice posicionamiento fijo para diálogos modales
- Utilice el posicionamiento absoluto para menús desplegables, información sobre herramientas y otras interacciones dinámicas.
- Tenga en cuenta los problemas de accesibilidad al crear estas funciones.
- Hay dos trampas de z-index: solo funciona en elementos posicionados y su uso crea un nuevo contexto de apilamiento.
- Tenga en cuenta los posibles obstáculos al crear varios contextos de apilamiento en una página.
- Esté atento a una mejor compatibilidad del navegador con el posicionamiento fijo.