Utilidades CSS para JavaFX al estilo Tailwind
Un sistema de clases utilitarias CSS inspirado en Tailwind que puedes usar directamente en tus proyectos JavaFX para estilizar componentes con padding, colores, tipografía, botones y más sin escribir CSS personalizado.
JavaFX Master
3 de marzo de 2025 • 12 min de lectura
Si vienes del mundo web probablemente conoces Tailwind CSS — un framework de utilidades que te permite estilizar elementos directamente con clases como p-4, text-lg o bg-primary. ¿Y si pudieras hacer lo mismo en JavaFX?
En este artículo te presentamos un archivo CSS de utilidades inspirado en Tailwind, diseñado específicamente para JavaFX. En lugar de escribir estilos manuales para cada componente, simplemente agregas clases utilitarias.
Descarga el Archivo Completo
El archivo contiene más de 400 líneas de utilidades listas para usar, incluyendo variables, paleta de colores, botones, badges y soporte para modo oscuro.
Descargar javafx-utilities.cssCómo Usarlo
- Descarga el archivo
javafx-utilities.css - Colócalo en
src/main/resources/css/de tu proyecto - Cárgalo en tu aplicación:
scene.getStylesheets().add(
getClass().getResource("/css/javafx-utilities.css").toExternalForm()
);
- Aplica las clases directamente en tu código Java:
Label titulo = new Label("Hola Mundo");
titulo.getStyleClass().addAll("text-2xl", "font-bold", "text-primary");
VBox contenedor = new VBox(titulo);
contenedor.getStyleClass().addAll("p-4", "gap-4", "bg-white", "rounded-lg");
O en tus archivos FXML:
<VBox styleClass="p-4, gap-4, bg-white, rounded-lg">
<Label text="Hola Mundo" styleClass="text-2xl, font-bold, text-primary"/>
</VBox>
Paleta de Colores
El sistema incluye una paleta completa con 6 familias de colores, cada una con múltiples tonalidades definidas como variables CSS de JavaFX:
| Color | Variable Base | Hex | Uso |
|---|---|---|---|
| Primary | -color-primary-600 | #2563eb | Acciones principales |
| Success | -color-success-600 | #059669 | Éxito, confirmación |
| Danger | -color-danger-600 | #dc2626 | Error, eliminación |
| Warning | -color-warning-600 | #d97706 | Advertencias |
| Info | -color-info-600 | #7c3aed | Información |
| Slate | -color-slate-600 | #475569 | Texto neutral |
Cada familia tiene tonalidades desde 50 (muy claro) hasta 900 (muy oscuro):
.root {
/* Blue (Primary) */
-color-primary-50: #eff6ff;
-color-primary-100: #dbeafe;
-color-primary-200: #bfdbfe;
-color-primary-300: #60a5fa;
-color-primary-500: #3b82f6;
-color-primary-600: #2563eb;
-color-primary-700: #1d4ed8;
/* Slate (Neutral) */
-color-slate-50: #f8fafc;
-color-slate-100: #f1f5f9;
-color-slate-200: #e2e8f0;
-color-slate-300: #cbd5e1;
-color-slate-400: #94a3b8;
-color-slate-500: #64748b;
-color-slate-600: #475569;
-color-slate-700: #334155;
-color-slate-800: #1e293b;
-color-slate-900: #0f172a;
}
Espaciado (Padding y Gap)
Padding
| Clase | Valor | Descripción |
|---|---|---|
.p-0 | 0 | Sin padding |
.p-1 | 4px | Extra pequeño |
.p-2 | 8px | Pequeño |
.p-3 | 12px | Medio |
.p-4 | 16px | Normal |
.p-5 | 24px | Grande |
.p-6 | 32px | Extra grande |
.p-8 | 48px | Máximo |
También disponibles .px-* (horizontal) y .py-* (vertical):
/* Padding uniforme */
.p-4 {
-fx-padding: 16px;
}
/* Padding horizontal (izquierda/derecha) */
.px-4 {
-fx-padding: 0 16px;
}
/* Padding vertical (arriba/abajo) */
.py-4 {
-fx-padding: 16px 0;
}
Gap (Espaciado entre hijos)
Para VBox y HBox, usa .gap-* que controla -fx-spacing:
.gap-2 {
-fx-spacing: 8px;
}
.gap-4 {
-fx-spacing: 16px;
}
.gap-6 {
-fx-spacing: 24px;
}
Ejemplo práctico:
VBox sidebar = new VBox();
sidebar.getStyleClass().addAll("p-4", "gap-4");
// Resultado: padding de 16px y 16px entre cada hijo
Tamaños (Width y Height)
/* Width */
.w-full {
-fx-pref-width: 100%;
-fx-max-width: Infinity;
}
.w-75 {
-fx-pref-width: 75%;
}
.w-50 {
-fx-pref-width: 50%;
}
.w-25 {
-fx-pref-width: 25%;
}
/* Max Width */
.max-w-sm {
-fx-max-width: 384px;
}
.max-w-md {
-fx-max-width: 448px;
}
.max-w-lg {
-fx-max-width: 512px;
}
.max-w-xl {
-fx-max-width: 576px;
}
/* Height */
.h-full {
-fx-pref-height: 100%;
-fx-max-height: Infinity;
}
Tipografía
Tamaños de Texto
| Clase | Tamaño | Uso típico |
|---|---|---|
.text-xs | 11px | Etiquetas menores |
.text-sm | 13px | Texto secundario |
.text-base | 14px | Texto normal |
.text-lg | 16px | Subtítulos |
.text-xl | 20px | Títulos |
.text-2xl | 24px | Encabezados |
.text-3xl | 30px | Títulos grandes |
Peso y Estilo
.font-bold {
-fx-font-weight: bold;
}
.font-semibold {
-fx-font-weight: 600;
}
.font-normal {
-fx-font-weight: normal;
}
.font-italic {
-fx-font-style: italic;
}
Alineación
.text-center {
-fx-alignment: center;
-fx-text-alignment: center;
}
.text-left {
-fx-alignment: center-left;
-fx-text-alignment: left;
}
.text-right {
-fx-alignment: center-right;
-fx-text-alignment: right;
}
Ejemplo completo:
Label titulo = new Label("Dashboard");
titulo.getStyleClass().addAll("text-3xl", "font-bold");
Label subtitulo = new Label("Resumen del sistema");
subtitulo.getStyleClass().addAll("text-sm", "text-slate-500");
Colores de Texto y Fondo
Texto
label.getStyleClass().add("text-primary"); // Azul
label.getStyleClass().add("text-success"); // Verde
label.getStyleClass().add("text-danger"); // Rojo
label.getStyleClass().add("text-warning"); // Naranja
label.getStyleClass().add("text-info"); // Violeta
label.getStyleClass().add("text-slate-500"); // Gris medio
Fondos
panel.getStyleClass().add("bg-white"); // Blanco
panel.getStyleClass().add("bg-slate-50"); // Gris muy claro
panel.getStyleClass().add("bg-primary"); // Azul primario
panel.getStyleClass().add("bg-danger-50"); // Rojo suave de fondo
Bordes y Redondeo
Bordes
.border {
-fx-border-color: ...;
-fx-border-width: 1px;
}
.border-b {
-fx-border-width: 0 0 1px 0;
} /* Solo borde inferior */
.border-primary {
-fx-border-color: -color-primary-500;
}
.border-danger {
-fx-border-color: -color-danger-500;
}
Border Radius
| Clase | Radio | Resultado |
|---|---|---|
.rounded-none | 0 | Sin redondeo |
.rounded-sm | 2px | Sutil |
.rounded | 4px | Normal |
.rounded-md | 6px | Medio |
.rounded-lg | 8px | Grande |
.rounded-xl | 12px | Extra grande |
.rounded-full | 9999px | Completamente redondo |
Ejemplo de tarjeta:
VBox card = new VBox();
card.getStyleClass().addAll(
"bg-white", "rounded-lg", "border", "p-4", "gap-3"
);
Botones
El sistema incluye botones listos para usar con variantes sólidas, light, outline y dashed:
Button guardar = new Button("Guardar");
guardar.getStyleClass().addAll("btn", "btn-primary");
Button eliminar = new Button("Eliminar");
eliminar.getStyleClass().addAll("btn", "btn-danger");
Button cancelar = new Button("Cancelar");
cancelar.getStyleClass().addAll("btn", "btn-secondary");
Button especial = new Button("Info");
especial.getStyleClass().addAll("btn", "btn-light-primary");
Variantes disponibles:
| Clase | Estilo |
|---|---|
.btn-primary | Azul sólido |
.btn-success | Verde sólido |
.btn-danger | Rojo sólido |
.btn-warning | Naranja sólido |
.btn-info | Violeta sólido |
.btn-dark | Negro sólido |
.btn-secondary | Gris suave |
.btn-light-primary | Azul claro con texto azul |
.btn-outline-primary | Borde azul, fondo transparente |
.btn-dashed | Borde punteado |
Tamaños: .btn-sm (pequeño) y .btn-lg (grande).
Badges
Etiquetas pequeñas para estados o categorías:
Label badge = new Label("Nuevo");
badge.getStyleClass().addAll("badge", "badge-primary");
Label badgeEstado = new Label("Activo");
badgeEstado.getStyleClass().addAll("badge", "badge-light-success");
Layout y Alineación
/* Alineamiento para contenedores (VBox, HBox, StackPane) */
.items-center {
-fx-alignment: center;
}
.items-top-center {
-fx-alignment: top-center;
}
.items-top-left {
-fx-alignment: top-left;
}
.items-center-left {
-fx-alignment: center-left;
}
.items-center-right {
-fx-alignment: center-right;
}
Ejemplo:
HBox toolbar = new HBox();
toolbar.getStyleClass().addAll("items-center", "gap-3", "px-4", "py-2", "bg-white", "border-b");
Modo Oscuro
El archivo incluye un bloque .root.dark que redefine los tokens semánticos. Para activarlo:
// Activar modo oscuro
scene.getRoot().getStyleClass().add("dark");
// Desactivar modo oscuro
scene.getRoot().getStyleClass().remove("dark");
Los tokens que cambian automáticamente son:
.root.dark {
-color-bg-body: -color-slate-900; /* Fondo general */
-color-bg-surface: -color-slate-800; /* Tarjetas */
-color-text-primary: -color-slate-100; /* Texto principal */
-color-text-secondary: -color-slate-400; /* Texto secundario */
-color-border-default: -color-slate-700; /* Bordes */
}
Tip: Si usas tokens semánticos como
-color-bg-surfaceen lugar de colores hardcodeados, el modo oscuro funciona automáticamente sin cambiar tu código.
Ejemplo Completo: Formulario Estilizado
// Título
Label titulo = new Label("Crear Cuenta");
titulo.getStyleClass().addAll("text-2xl", "font-bold");
Label subtitulo = new Label("Ingresa tus datos para registrarte");
subtitulo.getStyleClass().addAll("text-sm", "text-slate-500");
// Campos
TextField nombre = new TextField();
nombre.setPromptText("Nombre completo");
nombre.getStyleClass().addAll("rounded-md");
TextField email = new TextField();
email.setPromptText("Email");
email.getStyleClass().addAll("rounded-md");
// Botones
Button registrar = new Button("Registrarse");
registrar.getStyleClass().addAll("btn", "btn-primary", "w-full");
Button google = new Button("Continuar con Google");
google.getStyleClass().addAll("btn", "btn-outline-primary", "w-full");
// Layout
VBox form = new VBox();
form.getStyleClass().addAll(
"bg-white", "rounded-xl", "p-6", "gap-4",
"border", "max-w-sm"
);
form.getChildren().addAll(titulo, subtitulo, nombre, email, registrar, google);
Siguiente Paso
Con estas utilidades ya puedes estilizar rápidamente cualquier componente JavaFX. En el próximo artículo veremos cómo crear componentes avanzados como tablas, barras de navegación y tarjetas estadísticas usando estas mismas clases.