Domina los positions en CSS: static, relative, absolute, fixed y sticky


Antes de empezar

El position en CSS es una de las propiedades más importantes para controlar dónde aparecen los elementos en tu página. Te va a permitir crear headers fijos, elementos flotantes, overlays y mucho más.

En este ejemplo interactivo puedes ver todos los tipos de position en acción. ¡Haz scroll para ver cómo funciona el sticky!

Pulsa el botón que aparece debajo, RUN PROJECT

Los 5 tipos de position

1. position: static (el valor por defecto)

Es el comportamiento normal de todos los elementos HTML. No hace nada especial.

.box-static {
  /* position: static; - No hace falta escribirlo, es por defecto */
  background: #8ed1fc;
}

Características:

  • Los elementos aparecen en el orden que están en el HTML
  • No responde a top, left, right, bottom
  • Sigue el flujo normal de la página
  • No se puede superponer a otros elementos

Cuándo usarlo: Prácticamente siempre, es el comportamiento normal. Solo cambias el position cuando necesitas algo específico.


2. position: relative

El elemento se mueve desde su posición original, pero reserva su espacio.

.box-relative {
  position: relative;
  left: 30px;   /* Se mueve 30px a la derecha */
  top: 10px;    /* Se mueve 10px hacia abajo */
  background: #fd98a8;
}

Características:

  • Mantiene su espacio en el flujo normal
  • Puedes moverlo con top, left, right, bottom
  • Punto de referencia para hijos con position: absolute
  • No afecta a otros elementos

Cuándo usarlo:

  • Para ajustes pequeños de posición
  • Como contenedor para elementos absolute
  • Para crear efectos de hover sutiles
/* Ejemplo: efecto hover sutil */
.card {
  position: relative;
  transition: top .2s linear;
}

.card:hover {
  top: -2px; /* Se eleva ligeramente */
}

3. position: absolute

El elemento se sale completamente del flujo (no ocupa espacio) y se posiciona respecto a su contenedor posicionado más cercano.

.relative-container {
  position: relative; /* Punto de referencia */
  height: 180px;
}

.box-absolute {
  position: absolute;
  top: 20px;    /* 20px desde arriba del contenedor */
  right: 20px;  /* 20px desde la derecha del contenedor */
  background: #00edb1;
}

Características:

  • No ocupa espacio en el flujo normal
  • Se posiciona respecto al primer padre con position (que no sea static)
  • Si no encuentra un padre posicionado, se posiciona respecto al viewport
  • Puede superponerse a otros elementos

Cuándo usarlo:

  • Tooltips y elementos emergentes
  • Iconos sobre imágenes
  • Overlays y modales
  • Elementos decorativos
/* Ejemplo: tooltip */
.tooltip {
  position: relative;
}

.tooltip-text {
  position: absolute;
  top: -30px;
  left: 50%;
  transform: translateX(-50%);
  background: black;
  color: white;
  padding: 5px;
  border-radius: 4px;
}

4. position: fixed

El elemento se fija respecto al viewport (la ventana del navegador) y siempre permanece visible.

.fixed-header {
  position: fixed;
  top: 0;           /* Pegado arriba */
  left: 0;          /* Pegado a la izquierda */
  width: 100%;      /* Ancho completo */
  background: #282828;
  z-index: 999;     /* Por encima de otros elementos */
}

.fixed-button {
  position: fixed;
  bottom: 15px;     /* 15px desde abajo */
  right: 15px;      /* 15px desde la derecha */
  background: #219ebc;
}

Características:

  • Siempre visible, no se mueve con el scroll
  • Se posiciona respecto al viewport, no a ningún contenedor
  • No ocupa espacio en el flujo normal
  • Perfecto para elementos que siempre deben estar accesibles

Cuándo usarlo:

  • Headers y navbars fijos
  • Botones flotantes (chat, “volver arriba”)
  • Notificaciones persistentes
  • Sidebars fijos

⚠️ Cuidado: Recuerda dejar espacio en el body para que el contenido no quede tapado por elementos fixed.

body {
  padding-top: 60px; /* Altura del header fijo */
}

5. position: sticky

Es una mezcla entre relative y fixed. Se comporta como relative hasta que llega a cierta posición, entonces se “pega” como fixed.

.sticky-bar {
  position: sticky;
  top: 70px;        /* Se pega cuando esté a 70px del top */
  background: #dea325;
}

Características:

  • Hybrid behavior: relative + fixed
  • Solo se activa cuando el scroll llega al threshold definido
  • Mantiene su espacio en el flujo (como relative)
  • Se pega solo dentro de su contenedor padre

Cuándo usarlo:

  • Menús que se fijan al hacer scroll
  • Headers de tablas que permanecen visibles
  • Sidebars que se fijan en cierto punto
  • Call-to-actions que aparecen al scrollear

Ejemplo práctico:

/* Navbar que se fija después del hero */
.navbar {
  position: sticky;
  top: 0;
  background: white;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

Conceptos importantes

Z-index: controlando las capas

Cuando tienes elementos superpuestos, z-index controla cuál aparece encima:

.modal-overlay {
  position: fixed;
  z-index: 9;    /* Fondo del modal */
}

.modal-content {
  position: fixed;
  z-index: 99;    /* Contenido por encima */
}

.tooltip {
  position: absolute;
  z-index: 999;    /* Tooltips por encima de todo */
}

Reglas del z-index:

  • Solo funciona en elementos posicionados (no static)
  • Números más altos = más arriba
  • Los hijos nunca pueden estar por encima de su padre
  • Sin z-index, el último en el HTML queda encima

Contenedor de referencia

Para position: absolute, es crucial entender cuál es su punto de referencia:

/* ❌ Problemático: se posiciona respecto al viewport */
.card {
  /* position: static por defecto */
}

.card-badge {
  position: absolute;
  top: 10px;        /* ¡Se posiciona respecto a toda la página! */
  right: 10px;
}

/* ✅ Correcto: contenedor de referencia */
.card {
  position: relative; /* Ahora es el punto de referencia */
}

.card-badge {
  position: absolute;
  top: 10px;          /* Respecto a .card */
  right: 10px;
}

Casos de uso comunes

Header fijo con navegación

.header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 60px;
  background: white;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  z-index: 99;
}

body {
  padding-top: 60px; /* Compensa la altura del header */
}
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0,0,0,0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 999;
}

.modal-content {
  position: relative; /* Para el botón de cerrar */
  background: white;
  padding: 2rem;
  border-radius: 8px;
  max-width: 500px;
  width: 90%;
}

.modal-close {
  position: absolute;
  top: 10px;
  right: 10px;
}
.sidebar {
  position: sticky;
  top: 80px;          /* Debajo del header fijo */
  height: calc(100vh - 80px);
  overflow-y: auto;
}

Badge sobre imagen

.image-container {
  position: relative;
  display: inline-block;
}

.badge {
  position: absolute;
  top: -8px;
  right: -8px;
  background: red;
  color: white;
  border-radius: 50%;
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
}

Experimenta con el código

Pulsa el botón que aparece debajo, RUN PROJECT

Prueba estos experimentos:

  1. Cambia el top del sticky - ¿Qué pasa si pones top: 0?
  2. Modifica las coordenadas del absolute - Prueba con bottom y left
  3. Juega con el z-index - ¿Puedes hacer que el botón fijo aparezca detrás?
  4. Agrega más elementos sticky - ¿Qué pasa si hay varios?

Errores comunes y cómo evitarlos

❌ Error 1: Absolute sin contenedor

/* Problemático */
.card-icon {
  position: absolute;
  top: 10px;
  right: 10px;
  /* Se posiciona respecto al viewport, no a la card */
}
/* Solución */
.card {
  position: relative; /* Contenedor de referencia */
}

.card-icon {
  position: absolute;
  top: 10px;
  right: 10px;
  /* Ahora se posiciona respecto a .card */
}

❌ Error 2: Fixed sin compensar espacio

/* Problemático */
.header {
  position: fixed;
  top: 0;
  height: 60px;
  /* El contenido queda tapado por debajo */
}
/* Solución */
.header {
  position: fixed;
  top: 0;
  height: 60px;
}

body {
  padding-top: 60px; /* Compensa la altura del header */
}

❌ Error 3: Z-index en elementos static

/* No funciona */
.element {
  /* position: static por defecto */
  z-index: 999; /* ¡No hace nada! */
}
/* Funciona */
.element {
  position: relative; /* O absolute, fixed, sticky */
  z-index: 999;
}

Resumen rápido

PositionFlujoReferenciaUso típico
static✅ Normal-Comportamiento por defecto
relative✅ Reserva espacioSu posición originalAjustes pequeños, contenedor para absolute
absolute❌ Sale del flujoPadre posicionadoTooltips, overlays, elementos flotantes
fixed❌ Sale del flujoViewportHeaders fijos, botones flotantes
sticky✅ HíbridoContenedor padreMenús que se fijan al scrollear

Recuerda:

  • static = comportamiento normal
  • relative = pequeños ajustes + contenedor para absolute
  • absolute = elementos flotantes respecto a su contenedor
  • fixed = siempre visible respecto al viewport
  • sticky = se fija al hacer scroll

¡Ahora ya puedes crear layouts más complejos y interfaces más dinámicas con total control sobre la posición de tus elementos!


Usamos cookies para mejorar tu experiencia. ¿Aceptas las cookies de análisis?