CSS: la presentación visual¶
Una página construida solo con HTML funciona, pero se ve como un documento de texto plano: títulos en negrilla, párrafos apilados, enlaces azules subrayados. Toda la información está ahí, y aun así resulta difícil de leer.
CSS (Cascading Style Sheets) es el lenguaje que resuelve eso. Define el estilo visual de la página: colores, espacios, tamaños, posiciones, fuentes y la disposición de los elementos en pantalla.
Su aporte va más allá de lo estético. CSS permite separar el contenido de la presentación: el HTML dice qué hay, el CSS dice cómo se ve. Gracias a esa separación, cambiar la apariencia de un sitio completo puede requerir tocar un solo archivo, sin modificar una línea de contenido. Es la misma idea que veremos formalizada más adelante en el patrón MVC.
Documentación de referencia
CSS tiene cientos de propiedades y ninguna persona las memoriza todas. La referencia recomendada para consultarlas es w3schools.com/cssref.
Sintaxis de una regla CSS¶
Toda hoja de estilos se compone de reglas, y toda regla tiene la misma estructura:

Sus partes son:
- Regla — el bloque completo.
- Selector — a qué elementos se aplica el estilo (en el ejemplo,
h1). - Declaración — cada instrucción de estilo dentro de las llaves, terminada en punto y coma.
- Propiedad — qué característica se modifica (
color). - Valor — qué valor recibe esa característica (
blue).
Se lee de forma casi literal: "a todos los h1 del documento, ponles el color de texto azul". Una regla puede contener tantas declaraciones como haga falta:
¿Dónde se escribe el CSS?¶
Hay tres formas de aplicar estilos, y no son equivalentes:
| Forma | Cómo se escribe | Cuándo usarla |
|---|---|---|
| Archivo externo | <link href="estilos.css"> en el <head> |
La forma correcta. Un solo archivo estiliza todo el sitio y el navegador puede guardarlo en caché. |
| Interno | Bloque <style> dentro del <head> |
Solo para pruebas rápidas o páginas de un único archivo. |
| En línea | Atributo style="..." en la etiqueta |
Evitar. Mezcla presentación con contenido y es casi imposible de mantener. |
El DOM: sobre qué actúan los selectores¶
Antes de escribir selectores hay que entender sobre qué operan. Cuando el navegador recibe el HTML no lo trata como texto: lo convierte en una estructura de datos llamada DOM (Document Object Model).

El DOM es la estructura de datos que guarda los contenidos del documento a desplegar, combinando contenido (del HTML) y presentación (del CSS). Es análogo a un árbol de sintaxis abstracta en un lenguaje de programación: así como un compilador convierte el código fuente en un árbol antes de procesarlo, el navegador convierte el HTML en un árbol antes de dibujarlo.
Ese árbol tiene la misma jerarquía que las etiquetas anidadas del documento:
html
├── head
│ ├── title
│ └── link
└── body
├── header
│ └── h1
├── main
│ ├── section
│ │ ├── h2
│ │ └── p
│ └── article
└── footer
Comprender esto es clave por dos razones. La primera es que un selector CSS es una consulta sobre ese árbol: cuando escribimos main p, estamos preguntando "¿qué nodos p cuelgan de un nodo main?". La segunda es que, más adelante, JavaScript modificará ese mismo árbol para cambiar la página en tiempo real. HTML, CSS y JS no son tres mundos separados: los tres convergen en el DOM.
Selectores¶
Un selector identifica uno o varios elementos del DOM para aplicarles estilo. Es la parte de CSS que más conviene dominar, porque de ella depende que los estilos lleguen exactamente a donde deben.
Selector de tipo¶
Selecciona todos los elementos de una etiqueta determinada: h1, span, body, p.
Afecta a todos los párrafos del documento, sin excepción. Es útil para definir la base tipográfica del sitio, pero demasiado amplio para casos concretos.
Selector de clase¶
Dentro de las etiquetas HTML existe un atributo class, un texto que define las clases que tiene ese elemento del DOM. Cada clase no debe tener espacios, y un mismo elemento puede declarar varias clases separadas por espacios.
<p class="destacado">Este párrafo va resaltado.</p>
<p class="destacado grande">Este además es grande.</p>
<p>Este no recibe ningún estilo especial.</p>
La clase se escribe en CSS precedida de un punto. Es el selector más usado en la práctica, porque permite reutilizar un mismo estilo en cualquier elemento y combinar varios estilos sobre uno solo.
Selector por identificador¶
El atributo id también vive dentro de las etiquetas, pero con una restricción importante: debe ser único en todo el documento. Los estilos definidos para un id se aplican solo al elemento que lo lleva.
El identificador se escribe precedido de almohadilla.
¿Clase o identificador?
Clase para estilos que se repiten —botones, tarjetas, alertas—, que es la mayoría de los casos. Identificador para elementos únicos de la página y, sobre todo, para que JavaScript los localice o para enlazar a una sección con #.
Como regla práctica: si dudas, usa clase. Un estilo que hoy parece único casi siempre termina repitiéndose.
Selectores de atributo¶
Permiten seleccionar los elementos del DOM según alguno de sus atributos, ya sea por su presencia o por su valor. Son especialmente útiles en formularios, enlaces y componentes dinámicos.
| Selector | Selecciona los elementos… |
|---|---|
[attr] |
que tienen el atributo attr, sin importar su valor. |
[attr=val] |
cuyo atributo attr vale exactamente val. |
[attr~=val] |
cuyo atributo attr contiene la palabra val dentro de una lista separada por espacios. |
[attr|=val] |
cuyo atributo attr vale val o empieza por val seguido de un guion (útil para idiomas: es, es-CO). |
[attr^=val] |
cuyo atributo attr empieza por el texto val. |
[attr$=val] |
cuyo atributo attr termina en el texto val. |
[attr*=val] |
cuyo atributo attr contiene el texto val en cualquier posición. |
/* Todos los campos deshabilitados */
[disabled] {
opacity: 0.5;
}
/* Solo los campos de texto */
input[type="text"] {
border: 1px solid black;
}
/* Enlaces a archivos PDF */
a[href$=".pdf"] {
font-weight: bold;
}
/* Enlaces externos */
a[href^="http"] {
color: darkgreen;
}
No confundir ^, $ y |
Son los tres que más se prestan a error:
^= empieza por, $= termina en, *= contiene en cualquier lugar.
El |= es un caso especial pensado para valores con guion, como los códigos de idioma.
Pseudoclases¶
Las pseudoclases se utilizan para describir una característica que el elemento está cumpliendo en un momento dado: que el mouse esté encima, que sea la página actual, que un campo esté enfocado. Se escriben con dos puntos.
a:hover {
color: red;
}
input:focus {
border-color: blue;
}
li:first-child {
font-weight: bold;
}
tr:nth-child(even) {
background-color: #f5f5f5;
}
Lo interesante de las pseudoclases es que permiten reaccionar a estados sin escribir una línea de JavaScript. El listado completo está en w3schools.com/css/css_pseudo_classes.asp.
Pseudoelementos¶
Se escriben con dos veces dos puntos y seleccionan una parte de un elemento, o generan contenido que no existe en el HTML:
Combinadores¶
Los combinadores se utilizan cuando necesitamos unir varios selectores para expresar una relación entre elementos dentro del árbol del DOM.
| Combinador | Sintaxis | Selecciona… | Ejemplo |
|---|---|---|---|
| Concatenación (sin espacio) | AB |
los elementos que cumplen ambos selectores a la vez. | p#pipol1, div.clase1 |
| Descendiente (espacio) | A B |
los elementos B que están dentro de A, a cualquier nivel de profundidad. |
p .clase1 |
| Hijo directo | A > B |
los elementos B que son hijos directos de A. |
p > b |
| Hermano adyacente | A + B |
el elemento B que aparece inmediatamente después de A, con el mismo padre. |
h1 + p |
| Hermanos generales | A ~ B |
todos los elementos B que son hermanos de A y aparecen después. |
h2 ~ p |
La diferencia entre concatenación y descendiente es la que más confusión genera, y es solo un espacio:
/* Concatenación: un <p> que ADEMÁS tiene la clase destacado */
p.destacado { color: blue; }
/* Descendiente: cualquier elemento con clase destacado DENTRO de un <p> */
p .destacado { color: blue; }
Ejemplos de cada combinador:
/* Concatenación */
div.clase1 {
color: blue;
}
/* Descendiente */
div p {
color: blue;
}
/* Hijo directo */
ul > li {
list-style: none;
}
/* Hermano adyacente */
h1 + p {
margin-top: 0;
}
/* Hermanos generales */
h2 ~ p {
color: gray;
}
/* Selector múltiple: el mismo estilo para varios selectores */
h1, h2, h3 {
font-family: Arial;
}
/* Universal: todos los elementos del documento */
* {
margin: 0;
}
La cascada: por qué se llama Cascading¶
El nombre del lenguaje no es decorativo. Cuando varias reglas afectan al mismo elemento y se contradicen, el navegador necesita un criterio para decidir cuál gana. Ese criterio es la cascada, y se resuelve en dos niveles:
- Especificidad. Gana el selector más específico. En orden creciente: selector universal
*→ selector de tipop→ selector de clase.destacado→ selector deid#menu→ estilos en líneastyle="...". - Orden de aparición. A igual especificidad, gana la última regla escrita.
p { color: black; } /* especificidad baja */
.destacado { color: blue; } /* gana sobre la anterior */
#unico { color: red; } /* gana sobre todas */
Sobre !important
Existe la posibilidad de forzar una regla añadiendo !important, y salta por encima de toda la cascada. Es tentador cuando un estilo "no aplica", pero casi siempre indica que el problema real es un selector mal diseñado. Usarlo convierte la hoja de estilos en una escalada de excepciones difícil de mantener.
Propiedades más utilizadas¶
| Propiedad | Descripción | Valores comunes |
|---|---|---|
color |
Color del texto. | red, blue, #333, rgb(0,0,0) |
background-color |
Color de fondo del elemento. | white, #f5f5f5, transparent |
font-size |
Tamaño del texto. | 12px, 16px, 1em, 1rem, % |
font-family |
Tipografía del texto. | Arial, Verdana, sans-serif |
font-weight |
Grosor del texto. | normal, bold, 100–900 |
text-align |
Alineación horizontal del texto. | left, center, right, justify |
margin |
Espacio externo alrededor del elemento. | 10px, 0 auto, 5px 10px |
padding |
Espacio interno entre el contenido y el borde. | 10px, 5px 15px |
border |
Borde del elemento. | 1px solid black, none |
width |
Ancho del elemento. | 100px, 50%, auto |
height |
Altura del elemento. | 200px, auto, 100% |
display |
Cómo se muestra el elemento. | block, inline, inline-block, none, flex, grid |
position |
Método de posicionamiento. | static, relative, absolute, fixed, sticky |
top, right, bottom, left |
Ajustan la posición del elemento. | 0, 10px, % |
overflow |
Comportamiento del contenido que desborda. | visible, hidden, scroll, auto |
cursor |
Cursor del mouse sobre el elemento. | pointer, default, text |
opacity |
Transparencia del elemento. | 0 a 1 |
box-shadow |
Sombra del elemento. | 2px 2px 5px gray |
border-radius |
Redondeo de las esquinas. | 5px, 50% |
z-index |
Orden de superposición entre elementos. | 1, 10, 100 |
Contenedores: el modelo de caja¶
En CSS todos los elementos HTML se representan como una caja. Este concepto, conocido como modelo de caja (Box Model), define cómo se distribuyen el contenido y los espacios de un elemento dentro de la página. Es, probablemente, el concepto que más problemas resuelve una vez se entiende bien.

La caja se compone, de adentro hacia afuera, de cuatro zonas:
- Contenido (content). El texto, la imagen o los elementos visibles. Sus dimensiones se controlan con
widthyheight. - Relleno (padding). El espacio interno entre el contenido y el borde. Evita que el contenido quede pegado al límite de la caja.
- Borde (border). La línea visible que delimita el elemento.
- Margen (margin). El espacio externo que separa este elemento de los demás.
El orden es siempre: contenido → padding → border → margin.
La confusión más común es entre padding y margin. La forma corta de recordarlo: el padding empuja el contenido hacia adentro; el margin empuja los elementos vecinos hacia afuera. Si el fondo de un elemento es de color, el padding se pinta de ese color y el margin no.
El truco de box-sizing
Por defecto, width define solo el ancho del contenido: el padding y el borde se suman por fuera, de modo que un elemento con width: 200px y padding: 20px ocupa realmente 240px. Añadir esta regla al inicio de la hoja de estilos hace que width incluya padding y borde, que es como casi todo el mundo espera que funcione:
Despliegue y posicionamiento de los contenedores¶
La propiedad position determina cómo se ubica un contenedor respecto al resto de la página:
| Valor | Comportamiento |
|---|---|
static |
Valor por defecto. Los elementos se ponen uno después del otro, siguiendo el flujo natural del documento. |
relative |
La posición se modifica a partir de la posición por defecto que debería tener el elemento. El espacio que ocupaba se conserva. |
absolute |
La posición se modifica relativa al padre más cercano que no tenga posición static. El elemento sale del flujo normal. |
fixed |
La posición se modifica con respecto a la ventana. El elemento permanece fijo aunque se haga scroll. |
float |
Pone los elementos uno al lado del otro, y cuando se acaba el espacio continúa en la parte inferior. |
float es una propiedad aparte
A diferencia de los otros cuatro, float no es un valor de position sino una propiedad independiente (float: left). Fue durante años la herramienta principal para construir layouts de columnas, y por eso aparece en muchísimo código existente. Hoy, para organizar la página, la recomendación es usar Flexbox o Grid, que están diseñados específicamente para eso y evitan los problemas clásicos de los flotantes.
Las cuatro propiedades top, right, bottom y left son las que efectivamente desplazan el elemento, y solo tienen efecto si position es distinto de static.
Diseño responsivo¶
Una misma página debe verse bien en un monitor de escritorio y en la pantalla de un teléfono. Dos herramientas hacen posible esa adaptación.
Flexbox y Grid¶
Ambas organizan el contenido en el espacio disponible sin recurrir a posiciones absolutas:
/* Flexbox: distribución en una dirección (fila o columna) */
.contenedor {
display: flex;
gap: 16px;
justify-content: space-between;
}
/* Grid: distribución en dos dimensiones (filas y columnas) */
.galeria {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}
Media queries¶
Una media query aplica un bloque de estilos solo cuando se cumple una condición sobre el dispositivo, típicamente el ancho de la pantalla:
/* Estilos base: escritorio */
.contenedor {
display: flex;
flex-direction: row;
}
/* En pantallas de 768px o menos, apilar en columna */
@media (max-width: 768px) {
.contenedor {
flex-direction: column;
}
}
Nunca debe haber desplazamiento horizontal
El síntoma más claro de una página mal adaptada es que en el teléfono se pueda desplazar hacia los lados. Suele deberse a un ancho fijo en píxeles, a una imagen sin max-width: 100% o a una tabla demasiado ancha. Es uno de los criterios de verificación de la actividad.
Actividad 2 · CSS responsivo¶
Dale estilo a la página creada en la actividad anterior.
Objetivo
Mejorar la presentación visual y adaptar la página a pantallas de escritorio y móvil.
Pasos
- Crea
estilos.cssy enlázalo desdeindex.html. - Define colores, tipografía, espaciado y modelo de caja.
- Organiza el contenido con Flexbox o Grid.
- Agrega una media query para reorganizar la página en móvil.
Entregable
index.html + estilos.css + capturas en escritorio y móvil.
Verificación
✓ Selectores claros y estilos reutilizables. ✓ Jerarquía visual, contraste y espaciado consistentes. ✓ Sin desplazamiento horizontal en móvil. ✓ Contenido legible y bien organizado en ambos tamaños.
Lo que sigue¶
La página ya tiene contenido y presentación. Falta la tercera capa: hacer que responda a lo que el usuario hace. Continúa en JavaScript.