Apuntes sobre Html2

Cuando uno enseña, dos aprenden.

Posicionamiento y float

La propiedad position

Por defecto, los elementos siguen el flujo normal del documento. La propiedad position permite alterar ese comportamiento: sacar elementos del flujo, desplazarlos respecto a una referencia, o fijarlos en la pantalla.

Cuando position tiene un valor distinto de static, se activan cuatro propiedades de coordenadas: top, right, bottom, left. Indican el desplazamiento del elemento respecto a su punto de referencia.

static: el flujo normal

Es el valor por defecto. El elemento ocupa su lugar en el flujo. Las propiedades de coordenadas no tienen efecto. No hace falta declararlo explícitamente salvo para anular un posicionamiento heredado.

relative: desplazarse sin salir del flujo

El elemento permanece en el flujo (sigue reservando su espacio original), pero puede desplazarse visualmente usando las coordenadas:

.desplazado {
    position: relative;
    top: 10px;     /* baja 10px de su posición natural */
    left: 20px;    /* se mueve 20px a la derecha */
}

El uso más frecuente de relative no es desplazar el elemento en sí, sino crear un contenedor de referencia para un hijo con position: absolute.

absolute: posición respecto a un contenedor

El elemento se saca del flujo (no ocupa espacio). Se posiciona respecto al ancestro posicionado más cercano, es decir, el primer ancestro con position distinto de static. Si no existe ninguno, el elemento se posiciona respecto al elemento raíz (<html>).

.contenedor {
    position: relative;   /* punto de referencia para el hijo */
}

.etiqueta {
    position: absolute;
    top: 0;
    right: 0;
    background: #84ba3f;
    color: white;
    padding: 2px 8px;
    font-size: 0.75rem;
}
<div class="contenedor">
    <img src="producto.jpg" alt="Producto">
    <span class="etiqueta">Nuevo</span>
</div>

El patrón relativo/absoluto es uno de los más usados en CSS: el contenedor es relative para ser el punto de referencia, y el hijo es absolute para posicionarse dentro de él.

Centrar un elemento con absolute:

.centrado {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

fixed: fijo en la ventana

El elemento se saca del flujo y se posiciona respecto a la ventana del navegador. Al hacer scroll, no se mueve: permanece en la misma posición visual.

/* Barra de navegación que acompaña al scroll */
.nav-fija {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    z-index: 1000;
    background: white;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

/* Botón "volver arriba" en esquina inferior derecha */
.btn-volver {
    position: fixed;
    bottom: 2rem;
    right: 2rem;
}

Como el elemento fijo no ocupa espacio, el contenido de la página puede quedar debajo. La solución habitual es añadir un padding-top al <body> equivalente a la altura del elemento fijo.

sticky: entre relativo y fijo

El elemento se comporta como relative hasta que el scroll llega a un umbral definido, momento en el que se "pega" como si fuera fixed. Cuando su contenedor sale de la pantalla, vuelve a fluir con él.

/* Cabecera de tabla que sigue el scroll hasta el final de la tabla */
thead th {
    position: sticky;
    top: 0;
    background: white;
}

/* Índice lateral que se queda visible al scrollear */
.indice {
    position: sticky;
    top: 2rem;
}

Para que sticky funcione, el contenedor padre no debe tener overflow: hidden ni overflow: auto, ya que eso rompe el comportamiento sticky.

z-index y contextos de apilamiento

Cuando varios elementos posicionados se superponen, z-index determina cuál queda encima. Un valor mayor implica estar más al frente:

.modal-fondo {
    position: fixed;
    z-index: 100;
}
.modal {
    position: fixed;
    z-index: 101;
}
.tooltip {
    position: absolute;
    z-index: 200;
}

z-index solo funciona en elementos con position distinto de static. En elementos sin posición, no tiene efecto.

Un elemento con position distinto de static y z-index crea un contexto de apilamiento: los z-index de sus hijos son relativos a ese contexto, no al documento global. Esto puede producir situaciones donde un hijo con z-index: 9999 queda debajo de otro elemento porque su padre tiene un contexto de apilamiento inferior.

float: rodear contenido

float desplaza un elemento hacia la izquierda o la derecha y permite que el contenido siguiente lo rodee. Fue diseñado para flotar imágenes junto a texto, y sigue siendo la herramienta correcta para ese uso específico:

img.foto {
    float: left;
    margin-right: 1.5rem;
    margin-bottom: 0.5rem;
}

El elemento flotante se saca parcialmente del flujo: el texto lo rodea, pero otros elementos de bloque se comportan como si el flotante no estuviera.

clear impide que un elemento quede al lado de un flotante anterior:

/* El footer baja debajo de cualquier flotante */
footer {
    clear: both;
}

Un contenedor que solo tiene hijos flotantes colapsa a altura cero porque los flotantes están fuera del flujo. La solución moderna es usar display: flow-root en el contenedor, lo que crea un contexto de formato de bloque que contiene los flotantes:

.contenedor-con-floats {
    display: flow-root;
}

La técnica más antigua (pero aún muy vista en código heredado) es el clearfix:

.clearfix::after {
    content: "";
    display: block;
    clear: both;
}

Para maquetación de página (columnas, layouts), hoy se usan flexbox y grid. float en ese contexto es código legado.

Ocultar elementos

Hay dos formas de ocultar un elemento, con efectos distintos:

/* El elemento no se ve, pero sigue ocupando espacio */
.invisible {
    visibility: hidden;
}

/* El elemento no se ve y no ocupa espacio */
.eliminado {
    display: none;
}

display: none elimina el elemento del flujo por completo. Los lectores de pantalla también lo ignoran. visibility: hidden mantiene el espacio y el elemento sigue en el árbol de accesibilidad.

Para ocultar algo visualmente pero mantenerlo accesible para lectores de pantalla (por ejemplo, texto descriptivo para iconos), se usa la técnica del clip:

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
}

Recapitulación

  • position: static es el flujo normal. Los otros valores permiten alterar el posicionamiento.
  • relative desplaza el elemento visualmente pero mantiene su espacio. Se usa principalmente como contenedor de referencia para hijos absolute.
  • absolute saca el elemento del flujo y lo posiciona respecto al ancestro posicionado más cercano. El patrón relativo/absoluto es muy común.
  • fixed fija el elemento respecto a la ventana, inmune al scroll.
  • sticky combina comportamiento relativo y fijo según el scroll. No funciona si el contenedor tiene overflow: hidden.
  • z-index controla el orden de apilamiento entre elementos posicionados. Crea contextos de apilamiento.
  • float envuelve el contenido alrededor del elemento. Útil para imágenes con texto, no para layouts de página. clear cancela el efecto. display: flow-root contiene los flotantes en su contenedor.
  • display: none elimina el elemento del flujo y de la accesibilidad. visibility: hidden lo oculta pero mantiene el espacio.

Tu proyecto

Haz que el <header> permanezca visible al hacer scroll con position: sticky. Es uno de los patrones más usados en portfolios:

header {
    position: sticky;
    top: 0;
    background-color: #fafaf8;
    z-index: 10;
    border-bottom: 1px solid #eee;
}

Guarda y prueba desplazándote por la página. El header se queda fijo al llegar al borde superior. Si el efecto no te convence para tu diseño, reviértelo: no todos los portfolios necesitan navegación fija.

En la próxima lección: Flexbox: la herramienta moderna para distribuir elementos en una fila o columna con control total sobre el alineado y el espacio.

TOP