¿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>
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;
}
}
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;
}
}
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',
},
})
}),
],
}