Pseudo-Elementos y Estilos Basados en Estado: Enfoques Críticos para CSS Dinámico
CompleteURL: https://ruvebal.github.io/web-atelier-udit/lessons/es/pseudo-elementos-y-estilos-de-estado/
📋 Tabla de Contenidos
- Lo Esencial en Cinco Ideas
- Mapa de Pseudo-Selectores
- Patrones sin JavaScript
- Taller Exprés: Dropdown Accesible
- Checklist Crítica
- Ejercicios Guiados
- Buenas Prácticas
- Recursos Clave
- Conclusión
Al finalizar esta lección, podrás:
- Distinguir rápidamente entre pseudo-clases y pseudo-elementos
- Mejorar estados de interacción sin perder accesibilidad
- Aplicar decoraciones con pseudo-elementos sin alterar el contenido
- Evaluar cuándo un selector afecta el rendimiento
- Documentar decisiones para sostener la mejora progresiva
Lo Esencial en Cinco Ideas
- Pseudo-clases reaccionan a estados (
:hover,:focus-visible,:nth-child()) - Pseudo-elementos añaden refuerzos visuales (
::before,::after,::selection) - Accesibilidad exige foco visible y atributos ARIA sincronizados
- Rendimiento mejora con selectores cortos y poco anidamiento
- Mejora progresiva usa
@supportsy:focuscomo fallback seguro
Mapa de Pseudo-Selectores
Pseudo-clases por intención
| Intención | Selectores clave | Aplicación práctica |
|---|---|---|
| Interacción | :hover, :focus-visible, :active, :focus-within |
Retroalimentación inmediata y accesible |
| Estructura | :first-child, :nth-of-type(odd), :last-child |
Ritmo visual sin clases auxiliares |
| Formularios | :required, :valid, :placeholder-shown, :has() |
Validación inmediata y estados dependientes de campos |
| Estado sin JavaScript | :target, :checked, :focus-within |
Acordeones, popovers y tabs controlados solo con CSS |
/* Referencias rápidas a la hora de auditar estados */
.nav a:focus-visible {
outline: 2px solid var(--focus-ring);
outline-offset: 2px;
}
input:required:invalid {
border-color: #f87171;
box-shadow: 0 0 0 1px rgba(248, 113, 113, 0.35);
}
Pseudo-elementos por propósito
| Propósito | Selectores | Ejemplo rápido |
|---|---|---|
| Decoración visual | ::before, ::after, ::marker |
Iconos inline, contadores y separadores |
| Tipografía | ::first-letter, ::first-line, ::selection |
Capitulare, titulares destacados y selección personalizada |
| Experiencia | ::placeholder, ::backdrop, ::cue |
Ajustar texto de ayuda, overlays y pistas multimedia |
/* Decoración ligera sin alterar el HTML */
.badge::before {
content: '●';
color: currentColor;
margin-inline-end: 0.25rem;
}
Demo: Tipografía con pseudo-elementos (solo CSS)
Patrones sin JavaScript
Las pseudo-clases gestionan gran parte de la interacción si combinas HTML semántico y controles nativos:
:focus-withinabre menús, acordeones o tooltips al recibir foco desde teclado o pantalla táctil.:checkedydetails[open]alternan paneles sin necesitar scripts.:targetpermite modales o pestañas enlazables mediante el hash de la URL.
<input type="checkbox" id="info-toggle" class="accordion__toggle" />
<label for="info-toggle" class="accordion__label">Ver contenidos</label>
<div class="accordion__panel">Contenido accesible sin JavaScript.</div>
.accordion__toggle {
position: absolute;
inline-size: 1px;
block-size: 1px;
opacity: 0;
}
.accordion__panel {
max-block-size: 0;
overflow: hidden;
transition: max-block-size 0.3s ease;
}
.accordion__toggle:checked + .accordion__label + .accordion__panel {
max-block-size: 20rem;
}
Demo: Tooltip accesible sin JavaScript
Taller Exprés: Dropdown Accesible
- Estructura mínima
<nav class="dropdown">
<button class="dropdown__trigger" aria-haspopup="true" aria-expanded="false">Menú</button>
<ul class="dropdown__content" hidden>
<li><a href="#inicio">Inicio</a></li>
<li><a href="#acerca">Acerca</a></li>
<li><a href="#contacto">Contacto</a></li>
</ul>
</nav>
- Estados clave
.dropdown {
position: relative;
--focus-ring: 2px solid #2563eb;
}
.dropdown__trigger {
padding: 0.75rem 1rem;
min-height: 44px;
}
.dropdown__trigger:focus {
outline: var(--focus-ring);
outline-offset: 2px;
}
.dropdown__trigger:focus:not(:focus-visible) {
outline: none;
}
- Pseudo-elementos + despliegue controlado
.dropdown__trigger::before {
content: '▾';
margin-right: 0.5rem;
transition: transform 0.2s ease;
}
.dropdown[data-expanded='true'] .dropdown__trigger::before {
transform: rotate(180deg);
}
.dropdown__content {
position: absolute;
inset-inline-start: 0;
right: 0;
margin-top: 0.5rem;
background: white;
border: 1px solid #e2e8f0;
box-shadow: 0 8px 16px rgba(15, 23, 42, 0.1);
list-style: none;
padding: 0;
}
.dropdown__content[hidden] {
display: none;
}
.dropdown__content li:nth-child(odd) {
background: #f7fafc;
}
.dropdown__content li:not(:last-child) {
border-bottom: 1px solid #e2e8f0;
}
const dropdown = document.querySelector('.dropdown');
const trigger = dropdown.querySelector('.dropdown__trigger');
const content = dropdown.querySelector('.dropdown__content');
dropdown.dataset.expanded = trigger.getAttribute('aria-expanded');
trigger.addEventListener('click', () => {
const expanded = trigger.getAttribute('aria-expanded') === 'true';
trigger.setAttribute('aria-expanded', String(!expanded));
content.hidden = expanded;
dropdown.dataset.expanded = String(!expanded);
});
Mantén
aria-expandedsincronizado con el estado visual mediante una pequeña función de JavaScript o el mecanismo propio de tu framework.
Demo en vivo: Dropdown accesible
Checklist Crítica
- Foco visible con
:focus-visibley fallback en:focus Tab,EnteryEsccubren la navegación completahiddenalterna conaria-expandedpara lectores de pantalla- Prefiere selectores simples (
.dropdown__item) antes que:nth-child()
Ejercicios Guiados
Ejercicio 1 · Auditoría Exprés
- Revisa un dropdown existente con la checklist
- Documenta dos mejoras de accesibilidad y regístralas como issue o PR
- Prioriza cambios que beneficien a quien navega solo con teclado
Ejercicio 2 · Dropdown sin JavaScript
- Usa
:focus-withincomo disparador principal - Limita animaciones a 300 ms y respeta
prefers-reduced-motion - Prueba en móvil, modo oscuro y alto contraste antes de publicar
Demo: Patrones combinados (solo CSS + pseudo-elementos)
Buenas Prácticas
- Mantén el contenido esencial en HTML y reserva pseudo-elementos para decoración
- Combina
:hovery:focuspara cubrir mouse y teclado - Activa mejoras progresivas con
@supports selector(:focus-visible) - Evalúa rendimiento con DevTools Performance y accesibilidad con axe DevTools
Recursos Clave
Conclusión
Pseudo-clases y pseudo-elementos amplían CSS para responder a la interacción manteniendo el HTML semántico. Con prácticas accesibles y mediciones de rendimiento, tus componentes escalan sin sorpresas.
Ahora, aplica estas técnicas en tus repositorios de GitHub, experimenta con diferentes estilos y comparte tus resultados completando un dropdown accesible, documentando dos decisiones de diseño en el README y publicando una captura o GIF del comportamiento final.