Conceptos Principales, Estilos personalizados

¿Qué son los estilos personalizados en Tailwind CSS?

Uno de los retos mas importantes cuando se trabaja con un framework es determinar que hacer cuando se necesita algo que el framework no provee por default.

Tailwind ha sido diseñado desde sus cimientos para ser extensible y personalizable, de tal forma que no importa que estés construyendo, no sientas que estas yendo en contra de la filosofía del framework.

Los siguientes puntos cubren algunas recomendaciones para expandir y configurar los estilos en Tailwind de manera correcta.

Personalización de un tema

Si deseas cambiar aspectos como la paleta de colores, el espaciado, tamaño de la tipografía, o breakpoints, agrega dichas personalizaciones a la sección theme del archivo tailwind.config.js.

/** @type {import('tailwindcss').Config} */
module.exports = {
    theme: {
        screens: {
            sm: '320px',
            md: '640px',
            lg: '1024px',
            xl: '1280px',
        },
        colors: {
            blue: '#...',
            pink: '#...',
            orange: '#...',
            green: '#...',
            gray: '#...',
        },
        fontFamily: {
            sans: ['Roboto', 'sans-serif'],
            serif: ['Genova', 'serif'],
        },
        extend: {
            spacing: {
                128: '##rem',
                144: '##rem',
            },
        },
    },
}

Uso de valores arbitrarios

Si bien es posible utilizar las clases predefinidas para la mayoría de los escenarios, en ocasiones se requieren valores personalizados, en dichos casos utiliza la sintaxis para especificar valores arbitrarios.

Ejemplos:

<div class="top-[120px]">
    <!-- ... -->
</div>
<div class="bg-[#cccccc] text-[32px]">
    <!-- ... -->
</div>

Uso de propiedades arbitrarias

Si requires utilizar una propiedad CSS para la cual Tailwind no incluya una utilidad, puedes utilizar la notación de paréntesis para escribir CSS de forma arbitraria.

<p class="lg:[&:nth-child(3)]:hover:underline">Lorem ipsum dolor</p>

Manejo de espacio en blanco

Cuando un valor arbitrario necesita contener un espacio, utiliza un guión bajo _, con esto Tailwind lo convertirá automáticamente en un espacio.

<div class="bg-white p-10 [border:1px_solid_#000]">
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Placeat repellendus
    ad assumenda unde perferendis molestiae doloribus eligendi temporibus nobis?
    Architecto dolorum nesciunt illo officia quo enim itaque ex maxime adipisci.
</div>

Ejemplo

En algunos casos se require utilizar espacios en blanco que son ambiguos, para estos casos podemos utilizar un backslash.

<p class="after:content-['_(@martha\_dez)'] after:text-orange-700">
    Porro apquam fugit ipsum provident eos adipisci odio, id vero facere illum
    quos ipsa accusantium reiciendis nobis ipsam enim natus error vel doloribus
    at. Voluptatem id deleniti illum fugiat omnis?
</p>

Uso de CSS y @layer

Cuando se requiere agregar CSS personalizados a un proyecto Tailwind, la solución mas sencilla es simplemente agregarlo a la hoja de estilos.

@tailwind base;
@tailwind components;
@tailwind utilities;

.mi-estilo {
  /* ... */
}

Para agregar mas poder a esto, se puede utilizar la directiva @layer que agrega estilos a Tailwind a las capas components, components y utilities.

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
    .mi-estilo {
        /* ... */
    }
}

¿Por qué Tailwind agrupa los estilos en layers?

En CSS el orden en que se definen los estilos decide que declaración tiene precedencia sobre la otra.

.mi-boton {
    background: black;
}

.boton-purpura {
    background: purple;
}

Aquí ambos botones utilizan ambas clases anteriores y ambos serán purpuras ya que la clase .mi-boton es definida antes que .boton-purpura.

<button class="mi-boton bg-purpura">...</button>
<button class="bg-purpura mi-boton">...</button>

Para lidiar con esto, Tailwind organiza los estilos en tres diferentes capas.

  • base, contiene cosas como reglas de reseteo o estilos por default aplicados a elementos HTML planos.
  • components, estilos basados en clases que puedes sobreescribir con utilities.
  • utilities, clases de propósito único, y que deben tener siempre precedencia sobre el resto.

La directiva @layer ayuda a controlar la declaración del orden, al reubicar automáticamente tus estilos en su directiva correspondiente de @tailwind, y también habilita características como los modifiers y tree-shaking para tu propio CSS personalizado.

Agregar estilos base

Si deseas iniciar con algunos estilos por default para la página, como el color de fondo, la fuente, etc. la forma mas sencilla es agregar estos estilos a la etiqueta <html> o <body>.

<!DOCTYPE html>
<html lang="es" class="text-slate-500 bg-gray-100 font-bold">
    <!-- -->
</html>

Esto mantiene tus estilos base en a través de toda la página, en lugar de esconderlos en un archivo separado.

Si agregas estilos en el archivo main.css para algunos elementos específicos HTML, utiliza la directiva @layer para agregar estos estilos a la capa base de Tailwind.

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
    h1 {
        @apply font-bold;
    }

    h2 {
        @apply font-normal;
    }

    /* ... */
}

Utiliza la función theme o la directiva @apply cuando agregues estilos personalizados si quieres sobreescribir los valores definidos en tu tema.

Agregar clases componentes

La capa components permite agregar clases mas avanzadas al proyecto, que sobreescriben las utilities. Estamos hablando de por ejemplo card, btn, badge, etc.

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
    .card {
        background-color: theme('colors.white');
        padding: 2rem;
    }

    .card h1 {
        font-weight: bold;
        margin: 0 0 1rem 0;
    }
}

Ejemplo

Al definir clases dentro de components puedes combinarlas con utilities para sobreescribir aquellos estilos que creas necesarios.

La capa components también es es un buen lugar para agregar estilos personalizados para cualquier componente de terceros que estes utilizando.

<div class="card">
    <h2 class="card-title">Lorem ipsum dolor sit amet</h2>

    <p class="card-content">
        Consectetur adipisicing elit. Iure officia accusamus illum facere a
        tempore nam, aperiam vitae eos expedita repudiandae veritatis sint odio
        modi eius sapiente nostrum recusandae cupiditate tenetur excepturi velit
        explicabo similique unde aut! Enim, tenetur! Consectetur laborum
        possimus provident obcaecati voluptas molestias vel maiores. Tenetur,
        minima.
    </p>
</div>
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
    .card {
        @apply bg-white p-5 rounded-lg;
    }

    .card-title {
        @apply font-bold mb-4 text-2xl;
    }

    .card-content {
        @apply text-lg font-normal;
    }
}

Ejemplo

Utiliza la función theme o la directiva @apply si al agregar estilos de componentes personalizados si deseas referirte a cualquiera de los valores definidos en el theme.

Utilizar modificadores con CSS personalizados

Cualquier estilo personalizado que agregues mediante @layer tendrá soporte automático dentro de la sintaxis de tailwind para manejar cosas como hovers, breakpoints, dark mode y otros.

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer utilities {
    .contenido {
        content-visibility: auto;
    }
}
<div class="lg:dark:contenido">
    <!-- ... -->
</div>

¿Qué sucede con los estilos personalizados que no se utilizan?

Cualquier estilo personalizado agregado al base, components o utilities será incluido solamente en tu archivo compilado CSS si dicho estilo es utilizado en algún momento dentro de tu proyecto.

Utilizando múltiples archivos CSS

Si estas organizando el proyecto en múltiples archivos CSS, asegurate de que estos archivos estan siendo combinados en uno solo antesd e procesarlos con Tailwind, o verás un error que se presenta cuando utilizas @layer sin la directiva @tailwind correspondiente.

La manera mas sencilla de solucionar esto es utilizando el plugin postcss-import.

// postcss.config.js
module.exports = {
    plugins: {
        'postcss-import': {},
        tailwindcss: {},
        autoprefixer: {},
    },
}

Layers y CSS que reside en el componente

Los frameworks como Vue y Svelte permiten el uso de estilos a nivel del componente utilizando uan etiqueta <style> que vive en cada componente.

Si bien puedes utilizar @apply y theme dentro de los estilos de los componentes, la directiva @layer no funcionara y mostrará un error acerca de @layer siendo utilizando sin una directiva @tailwind.

No utilices @layer en el style de los componentes

<div>
    <slot></slot>
</div>

<style>
    /* esto genera un error debido a que es procesado individualmente */
    @layer components {
        div {
            background-color: theme('colors.white');
            border-radius: theme('borderRadius.lg');
            padding: theme('spacing.6');
            box-shadow: theme('boxShadow.xl');
        }
    }
</style>

Esto es debido a que frameworks como Vue y Svelte procesan cada bloque <style> de manera independiente, y ejecutando el plugin PostCSS para cada uno de forma independiente.

Lo que quiere decir que si tienes 10 componentes que utilizan <style>, Tailwind se ejecutará 10 ocasiones y cada uno tiene conocimiento nulo de la ejecución de los otros. Debido a esto, Tailwind no puede tomar los estilos que definas en @layer y moverlos a la directiva @tailwind correspondiente, ya que no existe para tailwind dicha directiva.

Una solución para esto es no usar @layer dentro de los style en los componentes.

<div>
    <slot></slot>
</div>

<style>
    div {
        background-color: theme('colors.white');
        border-radius: theme('borderRadius.lg');
        padding: theme('spacing.6');
        box-shadow: theme('boxShadow.xl');
    }
</style>

Se pierde la habilidad de controlar la precedencia de los estilos, pero desafortunadamente la manera en la que funcionan estas herramientas esta fuera del control de Tailwind.

La recomendación ees no usar componentes de estilos, y enfocarse al uso de Tailwind de la manera en la que se pensó, haciendo uso de las clases directamente.

<div class="bg-white rounded-lg p-6 shadow-xl">
    <slot></slot>
</div>

Escribir plugins de Tailwind

Es posible crear estilos personalizados en tu proyecto utilizando el sistema de plugins de Tailwind en lugar de utilizar un archivo CSS.

// tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
    // ...
    plugins: [
        plugin(function ({ addBase, addComponents, addUtilities, theme }) {
            addBase({
                h1: {
                    fontSize: theme('fontSize.2xl'),
                },
                h2: {
                    fontSize: theme('fontSize.xl'),
                },
            })
            // crear componente
            addComponents({
                '.card': {
                    backgroundColor: theme('colors.white'),
                    borderRadius: theme('borderRadius.lg'),
                    padding: theme('spacing.6'),
                    boxShadow: theme('boxShadow.xl'),
                },
            })
            // crear utility
            addUtilities({
                '.content-auto': {
                    contentVisibility: 'auto',
                },
            })
        }),
    ],
}