Conceptos Principales, Pseudo-Classes (Pseudo-Clases)

¿Qué son las Pseudo Clases?

Las pseudo-clases en CSS son un componente crucial para diseñar páginas web dinámicas y altamente interactivas. Estas etiquetas adicionales permiten seleccionar elementos HTML en función de su estado o relación con el usuario. Desde :hover para resaltar elementos cuando el cursor se desplaza sobre ellos, hasta :nth-child() para seleccionar elementos en una secuencia específica, las pseudo-clases abren un abanico de posibilidades para personalizar la apariencia y el comportamiento de un sitio web. Además, son esenciales para crear estilos receptivos y aplicar efectos de animación sutil. En resumen, las pseudo-clases en CSS son una herramienta esencial para mejorar la usabilidad y la estética de las páginas web modernas.

¿Cómo se utilizan las pseudo-clases en Tailwind?

Cada clases en Tailwind CSS puede ser aplicada condicionalmente añadiendo un modificador al inicio de la clase que describe la condición con la que se desea trabajar.

Por ejemplo, vamos a crear un botón que tenga un efecto de hover que cambie el color del fondo cuando el cursor se ponga encima utilizando una transición.

<button
    class="bg-sky-700 px-10 py-5 rounded-3xl text-white text-2xl font-black hover:bg-slate-800 duration-200 ease-in shadow-md"
>
    Guardar Cambios
</button>

Link del Ejemplo

¿Cómo se compara este ejemplo con el CSS tradicional?

Cuando se utiliza CSS tradicional, el nombre de una clase puede hacer diferentes cosas dependiendo de su estado.

.btn-primary {
    background-color: #0ea5e9;
}
.btn-primary:hover {
    background-color: #0369a1;
}

En tailwind, distintas clases son utilizadas para el estado default y el hover.

.bg-sky-500 {
    background-color: #0ea5e9;
}
.hover\:bg-sky-700:hover {
    background-color: #0369a1;
}

Tailwind incluye modificadores para cada uno de los casos necesarios, incluyendo:

Modificadores Descripción
Pseudo-classes :hover, :focus, :first-child y :required
Pseudo-elements ::before, ::after, ::placeholder y ::selection
Media y queries Como breakpoints (límites), dark mode (modo oscuro) y prefers-reduced-motion
Attribute selectors Como [dir="rtl"] y [open]

Estos modificadores pueden incluso combinarse entre sí para efectos avanzados.

Hover, focus y active

Los estilos hover, focus y active utilizan los modificadores hover, focus y active.

<button
    class="py-5 px-10 rounded-2xl bg-violet-500 hover:bg-violet-600 active:bg-violet-700 focus:outline-none focus:ring focus:ring-violet-300 text-white text-2xl font-bold"
>
    Save changes
</button>

Link del ejemplo

First, last y even

Los elementos de estilo se utilizan para hacer referencia a first-child y last-child mediante los modificadores first y last.

<div class="p-10">
    <ul role="list" class="divide-y divide-slate-200 border-gray-400 shadow-md">
        <li class="py-4 px-5 first:bg-slate-50 last:bg-slate-100">
            <p class="text-sm font-medium text-slate-900">Raul Jimenez</p>
            <p class="truncate text-sm text-slate-500">[email protected]</p>
        </li>
        <li class="py-4 px-5 first:bg-slate-50 last:bg-slate-100">
            <p class="text-sm font-medium text-slate-900">Raul Jimenez</p>
            <p class="truncate text-sm text-slate-500">[email protected]</p>
        </li>
        <li class="py-4 px-5 first:bg-slate-50 last:bg-slate-100">
            <p class="text-sm font-medium text-slate-900">Raul Jimenez</p>
            <p class="truncate text-sm text-slate-500">[email protected]</p>
        </li>
    </ul>
</div>

Link del ejemplo

También es posible utilizar odd (impar) y even (par).

<div class="p-10">
    <ul role="list" class="divide-y divide-slate-200 border-gray-400 shadow-md">
        <li class="py-4 px-5 odd:bg-slate-50 even:bg-slate-100">
            <p class="text-sm font-medium text-slate-900">Raul Jimenez</p>
            <p class="truncate text-sm text-slate-500">[email protected]</p>
        </li>
        <li class="py-4 px-5 odd:bg-slate-50 even:bg-slate-100">
            <p class="text-sm font-medium text-slate-900">Raul Jimenez</p>
            <p class="truncate text-sm text-slate-500">[email protected]</p>
        </li>
        <li class="py-4 px-5 odd:bg-slate-50 even:bg-slate-100">
            <p class="text-sm font-medium text-slate-900">Raul Jimenez</p>
            <p class="truncate text-sm text-slate-500">[email protected]</p>
        </li>
        <li class="py-4 px-5 odd:bg-slate-50 even:bg-slate-100">
            <p class="text-sm font-medium text-slate-900">Raul Jimenez</p>
            <p class="truncate text-sm text-slate-500">[email protected]</p>
        </li>
        <li class="py-4 px-5 odd:bg-slate-50 even:bg-slate-100">
            <p class="text-sm font-medium text-slate-900">Raul Jimenez</p>
            <p class="truncate text-sm text-slate-500">[email protected]</p>
        </li>
        <li class="py-4 px-5 odd:bg-slate-50 even:bg-slate-100">
            <p class="text-sm font-medium text-slate-900">Raul Jimenez</p>
            <p class="truncate text-sm text-slate-500">[email protected]</p>
        </li>
    </ul>
</div>

Link del ejemplo

Tailwind también incluye modificadores para otras pseudo clases como :only-child, :first-of-type, :empty y otros.

Manejo de estilos para estados en formularios

Aplicar estilos a los elementos de formularios mediante los modificadores required, invalid y disabled.

<div class="p-10 bg-slate-100">
    <form class="bg-white shadow-lg rounded-lg p-10">
        <label class="block">
            <span class="block text-sm font-normal">Nombre de usuario:</span>

            <input
                class="block mt-2 bg-white rounded-lg px-3 py-2 border border-slate-300 shadow-sm outline-none w-full placeholder:text-gray-400"
                placeholder="Tu nombre de usuario"
            />
        </label>

        <label class="block mt-5">
            <span class="block text-sm font-normal">Edad:</span>

            <input
                disabled
                value="18"
                class="block mt-2 bg-white rounded-lg px-3 py-2 border border-slate-300 shadow-sm outline-none w-full placeholder:text-gray-400 disabled:bg-slate-100"
            />
        </label>

        <label class="block mt-5">
            <span class="block text-sm font-normal">Email:</span>

            <input
                type="email"
                class="block mt-2 bg-white rounded-lg px-3 py-2 border border-slate-300 shadow-sm outline-none w-full placeholder:text-gray-400 invalid:border-red-500 invalid:text-red-500"
            />
        </label>
    </form>
</div>

Link del ejemplo

Utilizar modificadores para este tipo de cosas reduce la cantidad de lógica en sus templates. Tailwind también ofrece soporte para los estados como :read-only, :indeterminate, :checked y otros.

Utilizar estilos basados en el estado del contenedor (group-{modifier})

Cuando es necesario aplicar estilos a un elemento en base a el estado de su contenedor (padre), indica el grupo group del contenedor utilizando el modificador group-*, por ejemplo group-hover para aplicar el estilo al elemento objetivo.

<div class="p-10">
    <a
        href="#"
        class="block group p-5 shadow-lg rounded-lg border border-slate-200 hover:bg-blue-600"
    >
        <span class="font-bold group-hover:text-white">Nuevo Proyecto</span>

        <p class="mt-2 group-hover:text-white">
            Crea un nuevo proyecto a partir de un template
        </p>
    </a>
</div>

Link del ejemplo

Este patrón funciona con modificadores de pseudoclase, por ejemplo group-focus, group-active o incluso con group-odd.

También es posible utilizar diferentes grupos y asignarles un nombre a cada uno de ellos, para esto usamos group/nombre y el trabajamos con el modificador group-hover/nombre.

<div class="p-5 bg-white rounded-xl group/container">
    <ul class="group-hover/container:bg-slate-100 rounded-md">
        <li class="block rounded-md p-5 group/item hover:bg-slate-800">
            <a href="#" class="block">
                <span class="name font-bold group-hover/item:text-white"
                    >Ada Dominguez</span
                >
                <p class="text-slate-500 group-hover/item:text-slate-300">
                    Especialista en administración de proyectos
                </p>
            </a>
        </li>
        <li class="block rounded-md p-5 group/item hover:bg-slate-800">
            <a href="#" class="block">
                <span class="name font-bold group-hover/item:text-white"
                    >Ada Dominguez</span
                >
                <p class="text-slate-500 group-hover/item:text-slate-300">
                    Especialista en administración de proyectos
                </p>
            </a>
        </li>
        <li class="block rounded-md p-5 group/item hover:bg-slate-800">
            <a href="#" class="block">
                <span class="name font-bold group-hover/item:text-white"
                    >Ada Dominguez</span
                >
                <p class="text-slate-500 group-hover/item:text-slate-300">
                    Especialista en administración de proyectos
                </p>
            </a>
        </li>
    </ul>
</div>

Link del ejemplo

Los grupos pueden ser nombrados como desees y no necesitan ser configurados en alguna forma en especial, solo asigna un nombre y Tailwind CSS generará automáticamente el CSS.

Estilos basados en los estados de los elementos hermanos (peer-{modifier})

Cuando necesitas asignar estilos a un elemento basado en el estado de un elemento hermano, señala el hermano con la clase peer y utiliza los modificadores peer-* como peer-invalid para asignar los estilos.

En este ejemplo construimos un formulario que despliega el mensaje de error cuando existe un elemento hermano con el estado invalid.

<form>
    <label class="block">
        <span class="block">Email:</span>

        <input
            type="email"
            value="lorem ipsum dolor"
            class="block p-5 bg-white outline-none border border-slate-400 mt-3 text-slate-500 invalid:border-pink-500 invalid:text-pink-500 peer"
        />

        <span
            class="text-pink-500 mt-3 block opacity-0 peer-invalid:opacity-100 transition"
            >El correo electrónico no es valido</span
        >
    </label>
</form>

Link del ejemplo

El elemento peer aplica siempre al hermano anterior en el orden en el que se van declarando.

Como asignar nombres a los en peers

Cuando se utilizan multiples peers, puedes hacer referencia a el estado de cada peer especifico dándole un nombre con una clase peer/{nombre} e incluyendo ese nombre en los modificadores utilizando los modificadores peer-*/{nombre}.

En este ejemplo vamos a tener dos campos radio, que van a alternar sus estilos de selección y la visibilidad de un mensaje dependiendo su estado peer-checked.

<fieldset>
    <legend class="block mb-5 text-xl border border-b-slate-700 w-full">
        Estado Civil
    </legend>

    <input type="radio" name="status" class="peer/single mr-1" checked />
    <label class="peer-checked:text-sky-600 mr-5">Soltero</label>

    <input type="radio" name="status" class="peer/married mr-1" />
    <label class="peer-checked:text-sky-600">Casado</label>

    <p class="hidden mt-3 peer-checked/single:block">
        Tu estado civil es soltero
    </p>
    <p class="hidden mt-3 peer-checked/married:block">
        Tu estado civil es casado
    </p>
</fieldset>

Link del ejemplo