Curso de CSS / combinadores y pseudoclases
Los combinadores seleccionan elementos según sus relaciones en la estructura HTML, mientras que las pseudoclases seleccionan estados o condiciones estructurales. Un selector de hijo difiere de un selector descendiente, y :first-child se refiere al primer elemento hijo en lugar del primer elemento de un tipo particular.
Lee las relaciones de padre, hijo, descendiente y hermano
En la siguiente estructura, section es el padre de h2, párrafo A, div y párrafo C. El párrafo B es un hijo de div, que es un descendiente de section. A y C son hermanos porque tienen los mismos padres, pero A y B no son hermanos porque tienen padres diferentes. La estructura HTML es más importante que si se ve cerca en la pantalla.
<section class="garden">
<h2>Visitor Information</h2>
<p>A: Operating hours</p>
<div>
<p>B: Greenhouse Guide</p>
</div>
<p>C: What you need</p>
</section>
section.garden
├─ h2
├─ p ← A
├─ div
│ └─ p ← B
└─ p ← C
| notación de relación | selector | Párrafo seleccionado | Párrafo no seleccionado |
|---|---|---|---|
| espacio: descendiente | .garden p |
A, B, C | p fuera de esta sección |
| >: hijo directo | .garden > p |
A, C | B está dentro de un div, un nivel más abajo |
| +: el siguiente hermano | h2 + p |
A | B tiene diferentes padres y hay un div antes de C. |
| ~: hermano subsecuente | h2 ~ p |
A, C | B tiene un padre diferente de h2. |
Un combinador normalmente apunta al elemento a su derecha. h2 + p estiliza el p que sigue inmediatamente a un h2 como hermano. Los nodos de texto en blanco debido a la indentación o saltos de línea no interrumpen esta relación de elemento-hermano. Para más detalles, consulta Selectores CSS básicos: Tipo, Clase, ID y Atributos.
Compara los selectores de descendientes y de hijos
.garden p { color: #087f5b; }
.garden > p { border-left: 4px solid #087f5b; padding-left: 12px; }
La primera regla hace que todos los p en garden sean verdes. Contiene a B incluso si hay un div en el medio. La segunda regla añade un borde izquierdo y relleno a la izquierda solo a los hijos directos A y C. Dado que color y border-left son propiedades diferentes, A y C pueden tener tanto verde como borde.
Un selector de descendientes es adecuado para el estilo compartido de párrafos a lo largo de una sección. Un selector de hijos directos puede excluir párrafos dentro de tarjetas anidadas. Los cambios de estructura afectan estas coincidencias; evita encadenar combinadores de hijos innecesarios que hagan que la hoja de estilo dependa de una profundidad rígida. Ver MDN: Combinadores.
Compara hermanos adyacentes y posteriores
h2 + p { background-color: #fff4cc; }
h2 ~ p { font-style: italic; }
La primera regla da un fondo amarillo al párrafo A, que es el siguiente elemento hermano del título. La segunda pone A y C en cursiva porque ambos son elementos p hermanos posteriores de h2. B tiene otro padre y no coincide. Ninguno de estos combinadores selecciona hermanos anteriores.
Si insertas <div>Additional notice</div> entre h2 y A, el fondo amarillo desaparecerá porque A ya no es el hermano inmediato. Sin embargo, la condición de que sigue a h2 dentro del mismo padre se mantiene, por lo que la cursiva permanece. Ver esta diferencia te ahorrará tener que memorizar + y ~ como “selectores similares.”
Selecciona estados y posiciones con pseudoclases
a:hover { background-color: #fff4cc; }
a:focus-visible { outline: 3px solid #1d4ed8; outline-offset: 3px; }
.plants li:first-child { font-weight: bold; }
.plants li:nth-child(odd) { background-color: #e9f7ef; }
:hover selecciona el estado en el que el puntero está sobre el elemento. :focus-visible selecciona el estado en el que el navegador determina que es necesaria la visualización del enfoque, y es útil para verificar al desplazarte entre controles con la tecla Tab. :focus selecciona el propio estado enfocado, por lo que el significado de los dos no es completamente el mismo. Este ejemplo especifica un contorno adicional sin eliminar el indicador de enfoque predeterminado. Puedes seguir practicando cómo distinguir color y enfoque por estado en un enlace real en CSS Estados de Enlaces y Enfoque Visible con Teclado.
Cuando pasas el cursor sobre el enlace, el fondo se vuelve amarillo, y cuando navegas al enlace con la tecla Tab, aparece un contorno azul. En un entorno táctil, no se puede garantizar que el usuario siempre experimente el efecto hover. Deja la información esencial, como el horario de funcionamiento o los nombres de los enlaces, todavía legible de manera predeterminada.
:first-child selecciona si es el primer elemento hijo de su padre. :nth-child(odd) selecciona casos donde el orden de los elementos hijos es impar, como 1, 3 o 5. La lista de plantas del ejemplo completo solo tiene elementos li, por lo que la menta número 1 se vuelve negrita y crea un fondo para los elementos 1 y 3. Si usas even en lugar de odd, los números 2 y 4 son los objetivos.
p:first-child significa “un elemento p que es el primer hijo de su padre,” en lugar de “el primer p.” El primer hijo de section en este ejemplo es h2, así que .garden > p:first-child no coincide con ningún párrafo. nth-child cuenta todos los elementos hermanos, no solo los elementos con la misma etiqueta. Usa una condición como nth-of-type cuando necesites posiciones dentro de un tipo de elemento. La referencia de pseudoclases de MDN explica estas condiciones de estado y posición.
Ejecuta el ejemplo completo
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Small Garden</title>
<style>
body { margin: 24px; font-family: sans-serif; line-height: 1.7; }
.garden p { color: #087f5b; }
.garden > p { border-left: 4px solid #087f5b; padding-left: 12px; }
h2 + p { background-color: #fff4cc; }
h2 ~ p { font-style: italic; }
.plants li:first-child { font-weight: bold; }
.plants li:nth-child(odd) { background-color: #e9f7ef; }
a:hover { background-color: #fff4cc; }
a:focus-visible { outline: 3px solid #1d4ed8; outline-offset: 3px; }
</style>
</head>
<body>
<h1>Small Garden</h1>
<section class="garden">
<h2>Visitor Information</h2>
<p>A: We open at 9am every day.</p>
<div>
<p>B: Please observe quietly in the greenhouse.</p>
</div>
<p>C: Bring a water bottle and comfortable shoes.</p>
</section>
<ul class="plants">
<li>1: Mint</li>
<li>2: Basil</li>
<li>3: Rosemary</li>
<li>4: Time</li>
</ul>
<a href="#contact">Go to the contact section</a>
<h2 id="contact">Contact</h2>
<p>Ask at the information desk.</p>
</body>
</html>
Al guardar y abrir el ejemplo, dentro de section.garden A, B y C se ven verdes, y solo A y C tienen un borde izquierdo. A tiene un fondo amarillo, y A·C tiene texto en cursiva. La lista de plantas tiene el primer ítem en negrita y los ítems con número impar tienen un fondo claro. Verifica los enlaces usando el ratón y el teclado respectivamente. Las letras A–C están escritas en el texto para comparar los elementos seleccionados. Fuera de section.garden, el párrafo de contacto también recibe fondo amarillo y cursiva: los selectores h2 + p y h2 ~ p no están limitados a esa sección.
Cambia la estructura y prueba cada condición.
- Agrega un div entre h2 y A. Verifica que solo desaparece el fondo de A, dejando las cursivas y los bordes. Después de practicar, elimina el div agregado.
- Haz que B sea un hijo directo de la sección eliminando solo la etiqueta div que rodea el párrafo B. Asegúrate de que B también tenga un borde izquierdo y texto en cursiva. Dentro de section.garden, solo A sigue cumpliendo la condición +. Después de la confirmación, restaura el div.
- Reemplaza
:nth-child(odd)con:nth-child(even). Comprueba que el fondo de la lista se mueva de los números 1 y 3 a los números 2 y 4, y que las letras en negrita para el primer hijo sigan permaneciendo en el número 1. - Aleja el ratón, haz clic dentro de la página y pulsa Tab hasta el enlace. Asegúrate de que el contorno de enfoque sea visible y puedas moverte a la sección de contacto con Enter. Si la barra de direcciones del navegador tiene el enfoque, vuelve primero a la página.
Comprueba cada condición por separado. Cambiar solo el valor del color para ampliar el rango de selección o agregar el efecto hover al problema de enfoque del teclado no solucionará la causa. En las herramientas de desarrollo, puedes forzar un estado para comparar sus reglas, pero al final, es mejor revisar los resultados visibles para el usuario a través del movimiento real de tabulación y de los movimientos del ratón.




