CSS Styling in JavaFX in Java

Table of Contents

  1. Introduction to JavaFX CSS
  2. Basic CSS Styling
  3. CSS Selectors and Specificity
  4. Layout and Positioning
  5. Colors and Gradients
  6. Typography and Fonts
  7. Borders and Backgrounds
  8. Animations and Transitions
  9. Custom Controls and Skinning
  10. Best Practices and Patterns

Introduction to JavaFX CSS

JavaFX uses CSS for styling user interfaces, providing a powerful way to customize the appearance of applications. Unlike web CSS, JavaFX CSS has some unique properties and selectors specific to JavaFX controls.

Key Features:

  • Styleable properties: Most JavaFX controls have CSS-styleable properties
  • Type-safe styling: CSS properties are validated against control types
  • Scene graph styling: Styles can be applied at different levels
  • Runtime styling: Styles can be changed dynamically
  • Custom properties: Support for custom CSS properties

Basic CSS Styling

1. Basic JavaFX Application with CSS

// BasicCssApplication.java
public class BasicCssApplication extends Application {
@Override
public void start(Stage primaryStage) {
VBox root = new VBox(20);
root.setPadding(new Insets(20));
root.setAlignment(Pos.CENTER);
// Apply CSS to the scene
Scene scene = new Scene(root, 400, 300);
scene.getStylesheets().add(getClass().getResource("/styles/basic.css").toExternalForm());
// Create controls
Label titleLabel = new Label("JavaFX CSS Styling");
titleLabel.getStyleClass().add("title-label");
Button primaryButton = new Button("Primary Action");
primaryButton.getStyleClass().add("primary-button");
Button secondaryButton = new Button("Secondary Action");
secondaryButton.getStyleClass().add("secondary-button");
TextField textField = new TextField();
textField.setPromptText("Enter text here...");
CheckBox checkBox = new CheckBox("Enable feature");
ProgressBar progressBar = new ProgressBar(0.75);
// Add controls to layout
root.getChildren().addAll(
titleLabel, primaryButton, secondaryButton, 
textField, checkBox, progressBar
);
primaryStage.setTitle("JavaFX CSS Styling Demo");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
/* styles/basic.css */
.root {
-fx-background-color: linear-gradient(to bottom, #667eea 0%, #764ba2 100%);
-fx-font-family: "Segoe UI", Arial, sans-serif;
}
.title-label {
-fx-text-fill: white;
-fx-font-size: 24px;
-fx-font-weight: bold;
-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.3), 10, 0.5, 0, 2);
}
.primary-button {
-fx-background-color: #4CAF50;
-fx-text-fill: white;
-fx-font-size: 14px;
-fx-font-weight: bold;
-fx-padding: 10 20;
-fx-background-radius: 5px;
-fx-border-radius: 5px;
-fx-cursor: hand;
}
.primary-button:hover {
-fx-background-color: #45a049;
-fx-scale-x: 1.05;
-fx-scale-y: 1.05;
}
.primary-button:pressed {
-fx-background-color: #3d8b40;
-fx-scale-x: 0.95;
-fx-scale-y: 0.95;
}
.secondary-button {
-fx-background-color: transparent;
-fx-text-fill: white;
-fx-border-color: white;
-fx-border-width: 2px;
-fx-border-radius: 5px;
-fx-background-radius: 5px;
-fx-padding: 8 18;
-fx-cursor: hand;
}
.secondary-button:hover {
-fx-background-color: rgba(255,255,255,0.1);
-fx-text-fill: #f0f0f0;
}
.text-field {
-fx-background-color: white;
-fx-background-radius: 5px;
-fx-border-color: #ddd;
-fx-border-radius: 5px;
-fx-padding: 8 12;
-fx-font-size: 14px;
}
.text-field:focused {
-fx-border-color: #667eea;
-fx-border-width: 2px;
-fx-effect: dropshadow(gaussian, rgba(102,126,234,0.3), 10, 0.5, 0, 0);
}
.check-box {
-fx-text-fill: white;
-fx-font-size: 14px;
}
.check-box .box {
-fx-background-color: white;
-fx-border-color: #ddd;
-fx-border-radius: 3px;
}
.check-box:selected .mark {
-fx-background-color: #4CAF50;
}
.progress-bar {
-fx-accent: #4CAF50;
-fx-background-color: rgba(255,255,255,0.2);
-fx-background-radius: 5px;
}
.progress-bar .track {
-fx-background-color: rgba(255,255,255,0.3);
-fx-background-radius: 5px;
}
.progress-bar .bar {
-fx-background-color: linear-gradient(to right, #4CAF50, #45a049);
-fx-background-radius: 5px;
}

2. Inline Styles and Dynamic Styling

// DynamicStylingExample.java
public class DynamicStylingExample extends Application {
private int clickCount = 0;
private Label counterLabel;
@Override
public void start(Stage primaryStage) {
VBox root = new VBox(15);
root.setPadding(new Insets(20));
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 500, 400);
scene.getStylesheets().add(getClass().getResource("/styles/dynamic.css").toExternalForm());
// Title with inline style
Label title = new Label("Dynamic Styling Demo");
title.setStyle("-fx-font-size: 28px; -fx-text-fill: #2c3e50; -fx-font-weight: bold;");
// Counter label
counterLabel = new Label("Clicks: 0");
counterLabel.getStyleClass().add("counter-label");
// Interactive buttons
Button incrementBtn = new Button("Increment");
incrementBtn.getStyleClass().add("action-button");
incrementBtn.setOnAction(e -> incrementCounter());
Button resetBtn = new Button("Reset");
resetBtn.getStyleClass().add("reset-button");
resetBtn.setOnAction(e -> resetCounter());
// Style toggle buttons
ToggleButton darkModeToggle = new ToggleButton("Dark Mode");
darkModeToggle.getStyleClass().add("toggle-button");
darkModeToggle.selectedProperty().addListener((obs, oldVal, newVal) -> {
toggleDarkMode(scene, newVal);
});
// Color picker for dynamic styling
ColorPicker colorPicker = new ColorPicker(Color.BLUE);
colorPicker.getStyleClass().add("color-picker");
colorPicker.setOnAction(e -> {
updateButtonColor(incrementBtn, colorPicker.getValue());
});
// Progress indicator that changes with clicks
ProgressIndicator progress = new ProgressIndicator(0);
progress.getStyleClass().add("progress-indicator");
// Layout
HBox buttonBox = new HBox(10, incrementBtn, resetBtn);
buttonBox.setAlignment(Pos.CENTER);
root.getChildren().addAll(title, counterLabel, buttonBox, darkModeToggle, colorPicker, progress);
primaryStage.setTitle("Dynamic CSS Styling");
primaryStage.setScene(scene);
primaryStage.show();
}
private void incrementCounter() {
clickCount++;
updateCounterDisplay();
updateProgressAnimation();
}
private void resetCounter() {
clickCount = 0;
updateCounterDisplay();
updateProgressAnimation();
}
private void updateCounterDisplay() {
counterLabel.setText("Clicks: " + clickCount);
// Dynamic style based on count
if (clickCount > 10) {
counterLabel.setStyle("-fx-text-fill: #e74c3c; -fx-font-weight: bold;");
} else if (clickCount > 5) {
counterLabel.setStyle("-fx-text-fill: #f39c12; -fx-font-weight: bold;");
} else {
counterLabel.setStyle("-fx-text-fill: #2c3e50; -fx-font-weight: normal;");
}
}
private void updateProgressAnimation() {
double progress = Math.min(clickCount / 20.0, 1.0);
// This would update a progress bar in a real implementation
}
private void toggleDarkMode(Scene scene, boolean darkMode) {
if (darkMode) {
scene.getStylesheets().add(getClass().getResource("/styles/dark-theme.css").toExternalForm());
} else {
scene.getStylesheets().remove(getClass().getResource("/styles/dark-theme.css").toExternalForm());
}
}
private void updateButtonColor(Button button, Color color) {
String hexColor = String.format("#%02X%02X%02X",
(int) (color.getRed() * 255),
(int) (color.getGreen() * 255),
(int) (color.getBlue() * 255));
button.setStyle("-fx-background-color: " + hexColor + "; -fx-text-fill: white;");
}
public static void main(String[] args) {
launch(args);
}
}
/* styles/dynamic.css */
.root {
-fx-background-color: #ecf0f1;
-fx-font-family: "Segoe UI", Arial, sans-serif;
}
.counter-label {
-fx-font-size: 18px;
-fx-text-fill: #2c3e50;
-fx-font-weight: bold;
}
.action-button {
-fx-background-color: #3498db;
-fx-text-fill: white;
-fx-font-size: 14px;
-fx-font-weight: bold;
-fx-padding: 10 20;
-fx-background-radius: 25px;
-fx-border-radius: 25px;
-fx-cursor: hand;
-fx-effect: dropshadow(gaussian, rgba(52,152,219,0.3), 10, 0.5, 0, 2);
-fx-transition: all 0.3s;
}
.action-button:hover {
-fx-background-color: #2980b9;
-fx-scale-x: 1.05;
-fx-scale-y: 1.05;
-fx-effect: dropshadow(gaussian, rgba(52,152,219,0.5), 15, 0.5, 0, 4);
}
.reset-button {
-fx-background-color: #e74c3c;
-fx-text-fill: white;
-fx-font-size: 14px;
-fx-font-weight: bold;
-fx-padding: 10 20;
-fx-background-radius: 25px;
-fx-border-radius: 25px;
-fx-cursor: hand;
}
.reset-button:hover {
-fx-background-color: #c0392b;
-fx-scale-x: 1.05;
-fx-scale-y: 1.05;
}
.toggle-button {
-fx-background-color: #9b59b6;
-fx-text-fill: white;
-fx-font-size: 14px;
-fx-padding: 8 16;
-fx-background-radius: 5px;
-fx-cursor: hand;
}
.toggle-button:selected {
-fx-background-color: #8e44ad;
-fx-text-fill: #ecf0f1;
}
.color-picker {
-fx-background-color: white;
-fx-border-color: #bdc3c7;
-fx-border-radius: 5px;
-fx-padding: 5;
}
.progress-indicator {
-fx-progress-color: #3498db;
}
/* styles/dark-theme.css */
.root {
-fx-background-color: #2c3e50;
}
.counter-label {
-fx-text-fill: #ecf0f1;
}
.action-button {
-fx-background-color: #34495e;
-fx-text-fill: #ecf0f1;
}
.action-button:hover {
-fx-background-color: #3d566e;
}

CSS Selectors and Specificity

1. Advanced Selector Examples

// SelectorExample.java
public class SelectorExample extends Application {
@Override
public void start(Stage primaryStage) {
GridPane root = new GridPane();
root.setPadding(new Insets(20));
root.setHgap(15);
root.setVgap(15);
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 600, 500);
scene.getStylesheets().add(getClass().getResource("/styles/selectors.css").toExternalForm());
// Different types of buttons with various selectors
Button btnDefault = new Button("Default Button");
Button btnPrimary = new Button("Primary Button");
btnPrimary.getStyleClass().add("primary");
Button btnDanger = new Button("Danger Button");
btnDanger.getStyleClass().addAll("btn", "danger");
Button btnSuccess = new Button("Success Button");
btnSuccess.getStyleClass().addAll("btn", "success");
Button btnLarge = new Button("Large Button");
btnLarge.getStyleClass().addAll("btn", "large");
Button btnDisabled = new Button("Disabled Button");
btnDisabled.setDisable(true);
// Text fields with different states
TextField normalField = new TextField();
normalField.setPromptText("Normal field");
TextField focusedField = new TextField();
focusedField.setPromptText("Will be focused");
TextField errorField = new TextField();
errorField.setPromptText("Error state");
errorField.getStyleClass().add("error");
// Checkboxes and radio buttons
CheckBox check1 = new CheckBox("Standard Checkbox");
CheckBox check2 = new CheckBox("Custom Checkbox");
check2.getStyleClass().add("custom-check");
ToggleGroup group = new ToggleGroup();
RadioButton radio1 = new RadioButton("Option 1");
radio1.setToggleGroup(group);
RadioButton radio2 = new RadioButton("Option 2");
radio2.setToggleGroup(group);
radio2.getStyleClass().add("custom-radio");
// Special container with ID
VBox specialContainer = new VBox(10);
specialContainer.setId("special-container");
specialContainer.getChildren().addAll(
new Label("Special Container"),
new Button("Container Button")
);
// Layout
root.add(btnDefault, 0, 0);
root.add(btnPrimary, 1, 0);
root.add(btnDanger, 0, 1);
root.add(btnSuccess, 1, 1);
root.add(btnLarge, 0, 2);
root.add(btnDisabled, 1, 2);
root.add(normalField, 2, 0);
root.add(focusedField, 2, 1);
root.add(errorField, 2, 2);
root.add(check1, 0, 3);
root.add(check2, 1, 3);
root.add(radio1, 0, 4);
root.add(radio2, 1, 4);
root.add(specialContainer, 2, 3, 1, 2);
// Programmatically focus a field to demonstrate :focused selector
Platform.runLater(focusedField::requestFocus);
primaryStage.setTitle("CSS Selectors Demo");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
/* styles/selectors.css */
/* Type Selector - applies to all buttons */
.button {
-fx-background-color: #bdc3c7;
-fx-text-fill: #2c3e50;
-fx-padding: 8 16;
-fx-background-radius: 4px;
-fx-cursor: hand;
-fx-font-size: 12px;
}
/* Class Selector - applies to elements with class "primary" */
.primary {
-fx-background-color: #3498db;
-fx-text-fill: white;
-fx-font-weight: bold;
}
/* Multiple Class Selector - applies to elements with both "btn" and "danger" classes */
.btn.danger {
-fx-background-color: #e74c3c;
-fx-text-fill: white;
-fx-font-weight: bold;
}
.btn.success {
-fx-background-color: #2ecc71;
-fx-text-fill: white;
-fx-font-weight: bold;
}
.btn.large {
-fx-font-size: 16px;
-fx-padding: 12 24;
}
/* Pseudo-class Selector - disabled state */
.button:disabled {
-fx-background-color: #ecf0f1;
-fx-text-fill: #bdc3c7;
-fx-cursor: default;
}
/* Hover state for buttons */
.button:hover {
-fx-scale-x: 1.05;
-fx-scale-y: 1.05;
}
/* Focused state */
.text-field:focused {
-fx-border-color: #3498db;
-fx-border-width: 2px;
-fx-effect: dropshadow(gaussian, rgba(52,152,219,0.3), 10, 0.5, 0, 0);
}
/* Class-based styling for text fields */
.text-field.error {
-fx-border-color: #e74c3c;
-fx-background-color: #fadbd8;
}
/* ID Selector - very specific */
#special-container {
-fx-background-color: #34495e;
-fx-padding: 15;
-fx-background-radius: 8px;
-fx-border-color: #3498db;
-fx-border-width: 2px;
-fx-border-radius: 8px;
}
/* Child Selector - buttons inside #special-container */
#special-container .button {
-fx-background-color: #3498db;
-fx-text-fill: white;
}
/* Custom checkbox styling */
.check-box.custom-check .box {
-fx-background-color: #ecf0f1;
-fx-border-color: #3498db;
-fx-border-width: 2px;
-fx-border-radius: 3px;
}
.check-box.custom-check:selected .box {
-fx-background-color: #3498db;
}
.check-box.custom-check:selected .mark {
-fx-background-color: white;
}
/* Custom radio button styling */
.radio-button.custom-radio .radio {
-fx-background-color: #ecf0f1;
-fx-border-color: #9b59b6;
-fx-border-width: 2px;
-fx-border-radius: 50%;
}
.radio-button.custom-radio:selected .radio {
-fx-background-color: #9b59b6;
}
.radio-button.custom-radio:selected .dot {
-fx-background-color: white;
}
/* Adjacent sibling selector simulation */
/* Note: JavaFX CSS doesn't support adjacent sibling selectors like + */
/* We use class combinations instead */
/* First-child simulation */
.grid-pane > .button:first-child {
-fx-background-color: #f1c40f;
}
/* nth-child simulation using classes */
/* This would need to be handled programmatically in Java */
/* Attribute selector simulation */
.text-field[promptText*="Error"] {
-fx-border-color: #e74c3c;
}

Layout and Positioning

1. Advanced Layout Styling

// LayoutStylingExample.java
public class LayoutStylingExample extends Application {
@Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
Scene scene = new Scene(root, 800, 600);
scene.getStylesheets().add(getClass().getResource("/styles/layout.css").toExternalForm());
// Header
HBox header = createHeader();
root.setTop(header);
// Sidebar
VBox sidebar = createSidebar();
root.setLeft(sidebar);
// Main content
ScrollPane mainContent = createMainContent();
root.setCenter(mainContent);
// Footer
HBox footer = createFooter();
root.setBottom(footer);
primaryStage.setTitle("Advanced Layout Styling");
primaryStage.setScene(scene);
primaryStage.show();
}
private HBox createHeader() {
HBox header = new HBox();
header.getStyleClass().add("header");
Label logo = new Label("Dashboard");
logo.getStyleClass().add("logo");
HBox nav = new HBox(20);
nav.getStyleClass().add("navigation");
Button[] navButtons = {
createNavButton("Home"),
createNavButton("Dashboard"),
createNavButton("Analytics"),
createNavButton("Settings")
};
nav.getChildren().addAll(navButtons);
HBox userArea = new HBox(10);
userArea.getStyleClass().add("user-area");
userArea.setAlignment(Pos.CENTER_RIGHT);
Label userName = new Label("John Doe");
userName.getStyleClass().add("user-name");
Circle avatar = new Circle(20);
avatar.getStyleClass().add("avatar");
userArea.getChildren().addAll(userName, avatar);
HBox.setHgrow(nav, Priority.ALWAYS);
header.getChildren().addAll(logo, nav, userArea);
return header;
}
private Button createNavButton(String text) {
Button btn = new Button(text);
btn.getStyleClass().add("nav-button");
return btn;
}
private VBox createSidebar() {
VBox sidebar = new VBox();
sidebar.getStyleClass().add("sidebar");
String[] menuItems = {
"Overview", "Users", "Products", "Orders", 
"Inventory", "Reports", "Integrations", "Settings"
};
for (String item : menuItems) {
Button menuBtn = new Button(item);
menuBtn.getStyleClass().add("menu-button");
menuBtn.setMaxWidth(Double.MAX_VALUE);
sidebar.getChildren().add(menuBtn);
}
return sidebar;
}
private ScrollPane createMainContent() {
VBox content = new VBox(20);
content.getStyleClass().add("main-content");
content.setPadding(new Insets(20));
// Stats cards
HBox statsRow = new HBox(15);
statsRow.getStyleClass().add("stats-row");
VBox[] statCards = {
createStatCard("Total Users", "1,234", "#3498db", "users-icon"),
createStatCard("Revenue", "$45,678", "#2ecc71", "revenue-icon"),
createStatCard("Orders", "567", "#e74c3c", "orders-icon"),
createStatCard("Growth", "+12.5%", "#f39c12", "growth-icon")
};
statsRow.getChildren().addAll(statCards);
// Charts section
VBox chartsSection = new VBox(10);
chartsSection.getStyleClass().add("charts-section");
Label chartsTitle = new Label("Analytics");
chartsTitle.getStyleClass().add("section-title");
HBox chartsRow = new HBox(15);
VBox chart1 = createChartPlaceholder("Sales Trend");
VBox chart2 = createChartPlaceholder("User Activity");
chartsRow.getChildren().addAll(chart1, chart2);
chartsSection.getChildren().addAll(chartsTitle, chartsRow);
content.getChildren().addAll(statsRow, chartsSection);
ScrollPane scrollPane = new ScrollPane(content);
scrollPane.getStyleClass().add("scroll-pane");
scrollPane.setFitToWidth(true);
return scrollPane;
}
private VBox createStatCard(String title, String value, String color, String iconClass) {
VBox card = new VBox(10);
card.getStyleClass().add("stat-card");
card.setStyle("-fx-border-color: " + color + ";");
HBox header = new HBox(10);
header.setAlignment(Pos.CENTER_LEFT);
Pane icon = new Pane();
icon.getStyleClass().addAll("stat-icon", iconClass);
icon.setStyle("-fx-background-color: " + color + ";");
Label titleLabel = new Label(title);
titleLabel.getStyleClass().add("stat-title");
header.getChildren().addAll(icon, titleLabel);
Label valueLabel = new Label(value);
valueLabel.getStyleClass().add("stat-value");
card.getChildren().addAll(header, valueLabel);
return card;
}
private VBox createChartPlaceholder(String title) {
VBox chart = new VBox();
chart.getStyleClass().add("chart-placeholder");
Label titleLabel = new Label(title);
titleLabel.getStyleClass().add("chart-title");
Pane chartArea = new Pane();
chartArea.getStyleClass().add("chart-area");
chart.getChildren().addAll(titleLabel, chartArea);
VBox.setVgrow(chartArea, Priority.ALWAYS);
return chart;
}
private HBox createFooter() {
HBox footer = new HBox();
footer.getStyleClass().add("footer");
Label copyright = new Label("© 2024 MyApplication. All rights reserved.");
copyright.getStyleClass().add("footer-text");
HBox links = new HBox(15);
links.setAlignment(Pos.CENTER_RIGHT);
String[] footerLinks = {"Privacy Policy", "Terms of Service", "Contact", "Help"};
for (String link : footerLinks) {
Label linkLabel = new Label(link);
linkLabel.getStyleClass().add("footer-link");
links.getChildren().add(linkLabel);
}
HBox.setHgrow(links, Priority.ALWAYS);
footer.getChildren().addAll(copyright, links);
return footer;
}
public static void main(String[] args) {
launch(args);
}
}
/* styles/layout.css */
/* Root and general styles */
.root {
-fx-background-color: #f8f9fa;
-fx-font-family: "Segoe UI", Arial, sans-serif;
}
/* Header Styles */
.header {
-fx-background-color: white;
-fx-padding: 15 25;
-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.1), 10, 0, 0, 2);
-fx-border-color: #e9ecef;
-fx-border-width: 0 0 1 0;
}
.logo {
-fx-font-size: 24px;
-fx-font-weight: bold;
-fx-text-fill: #3498db;
}
.navigation {
-fx-alignment: center-left;
-fx-padding: 0 40;
}
.nav-button {
-fx-background-color: transparent;
-fx-text-fill: #6c757d;
-fx-font-size: 14px;
-fx-font-weight: 500;
-fx-padding: 8 16;
-fx-cursor: hand;
-fx-border-width: 0;
-fx-background-radius: 6px;
}
.nav-button:hover {
-fx-background-color: #e9ecef;
-fx-text-fill: #495057;
}
.nav-button:pressed {
-fx-background-color: #dee2e6;
}
.user-area {
-fx-padding: 0 10;
}
.user-name {
-fx-font-size: 14px;
-fx-text-fill: #495057;
-fx-font-weight: 500;
}
.avatar {
-fx-fill: #3498db;
-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.2), 5, 0, 0, 2);
}
/* Sidebar Styles */
.sidebar {
-fx-background-color: #2c3e50;
-fx-padding: 20 0;
-fx-spacing: 5;
-fx-pref-width: 250px;
}
.menu-button {
-fx-background-color: transparent;
-fx-text-fill: #bdc3c7;
-fx-font-size: 14px;
-fx-padding: 12 25;
-fx-alignment: center-left;
-fx-cursor: hand;
-fx-border-width: 0;
-fx-background-radius: 0;
}
.menu-button:hover {
-fx-background-color: #34495e;
-fx-text-fill: #ecf0f1;
}
.menu-button:pressed {
-fx-background-color: #3498db;
-fx-text-fill: white;
}
/* Main Content Styles */
.scroll-pane {
-fx-background-color: transparent;
-fx-border-width: 0;
-fx-padding: 0;
}
.scroll-pane .viewport {
-fx-background-color: transparent;
}
.main-content {
-fx-background-color: transparent;
}
.stats-row {
-fx-alignment: center;
}
.stat-card {
-fx-background-color: white;
-fx-padding: 20;
-fx-pref-width: 200px;
-fx-pref-height: 100px;
-fx-border-width: 0 0 0 4px;
-fx-border-radius: 0;
-fx-background-radius: 8px;
-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.1), 10, 0, 0, 2);
}
.stat-icon {
-fx-pref-width: 30px;
-fx-pref-height: 30px;
-fx-background-radius: 6px;
}
.stat-title {
-fx-font-size: 14px;
-fx-text-fill: #6c757d;
-fx-font-weight: 500;
}
.stat-value {
-fx-font-size: 24px;
-fx-text-fill: #2c3e50;
-fx-font-weight: bold;
}
/* Charts Section */
.charts-section {
-fx-padding: 20 0;
}
.section-title {
-fx-font-size: 20px;
-fx-text-fill: #2c3e50;
-fx-font-weight: bold;
}
.chart-placeholder {
-fx-background-color: white;
-fx-padding: 20;
-fx-pref-width: 350px;
-fx-pref-height: 250px;
-fx-background-radius: 8px;
-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.1), 10, 0, 0, 2);
}
.chart-title {
-fx-font-size: 16px;
-fx-text-fill: #495057;
-fx-font-weight: 600;
}
.chart-area {
-fx-background-color: #f8f9fa;
-fx-border-color: #e9ecef;
-fx-border-width: 1px;
-fx-border-radius: 4px;
}
/* Footer Styles */
.footer {
-fx-background-color: #2c3e50;
-fx-padding: 15 25;
-fx-border-color: #34495e;
-fx-border-width: 1 0 0 0;
}
.footer-text {
-fx-text-fill: #bdc3c7;
-fx-font-size: 12px;
}
.footer-link {
-fx-text-fill: #3498db;
-fx-font-size: 12px;
-fx-cursor: hand;
}
.footer-link:hover {
-fx-text-fill: #2980b9;
-fx-underline: true;
}

Colors and Gradients

1. Advanced Color and Gradient Styling

// ColorGradientExample.java
public class ColorGradientExample extends Application {
@Override
public void start(Stage primaryStage) {
VBox root = new VBox(20);
root.setPadding(new Insets(20));
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 700, 600);
scene.getStylesheets().add(getClass().getResource("/styles/colors-gradients.css").toExternalForm());
// Title
Label title = new Label("Colors & Gradients Gallery");
title.getStyleClass().add("gallery-title");
// Solid Colors Section
Label solidColorsTitle = new Label("Solid Colors");
solidColorsTitle.getStyleClass().add("section-title");
HBox solidColors = new HBox(15);
solidColors.setAlignment(Pos.CENTER);
String[] solidColorClasses = {"color-primary", "color-secondary", "color-success", 
"color-danger", "color-warning", "color-info"};
String[] solidColorNames = {"Primary", "Secondary", "Success", "Danger", "Warning", "Info"};
for (int i = 0; i < solidColorClasses.length; i++) {
VBox colorCard = createColorCard(solidColorNames[i], solidColorClasses[i], "solid");
solidColors.getChildren().add(colorCard);
}
// Gradient Section
Label gradientsTitle = new Label("Gradients");
gradientsTitle.getStyleClass().add("section-title");
HBox gradients = new HBox(15);
gradients.setAlignment(Pos.CENTER);
String[] gradientClasses = {"gradient-sunset", "gradient-ocean", "gradient-forest", 
"gradient-lavender", "gradient-sunrise", "gradient-midnight"};
String[] gradientNames = {"Sunset", "Ocean", "Forest", "Lavender", "Sunrise", "Midnight"};
for (int i = 0; i < gradientClasses.length; i++) {
VBox gradientCard = createColorCard(gradientNames[i], gradientClasses[i], "gradient");
gradients.getChildren().add(gradientCard);
}
// Transparency Section
Label transparencyTitle = new Label("Transparency & Effects");
transparencyTitle.getStyleClass().add("section-title");
HBox transparency = new HBox(15);
transparency.setAlignment(Pos.CENTER);
String[] transparencyClasses = {"transparent-10", "transparent-25", "transparent-50", 
"transparent-75", "blur-effect", "shadow-effect"};
String[] transparencyNames = {"10%", "25%", "50%", "75%", "Blur", "Shadow"};
for (int i = 0; i < transparencyClasses.length; i++) {
VBox transparencyCard = createColorCard(transparencyNames[i], transparencyClasses[i], "effect");
transparency.getChildren().add(transparencyCard);
}
// Color Picker Demo
Label pickerTitle = new Label("Interactive Color Picker");
pickerTitle.getStyleClass().add("section-title");
HBox colorPickerDemo = createColorPickerDemo();
root.getChildren().addAll(
title, solidColorsTitle, solidColors,
gradientsTitle, gradients,
transparencyTitle, transparency,
pickerTitle, colorPickerDemo
);
primaryStage.setTitle("Colors & Gradients");
primaryStage.setScene(scene);
primaryStage.show();
}
private VBox createColorCard(String name, String styleClass, String type) {
VBox card = new VBox(10);
card.getStyleClass().add("color-card");
card.setAlignment(Pos.CENTER);
Pane colorDisplay = new Pane();
colorDisplay.getStyleClass().addAll("color-display", styleClass);
colorDisplay.setPrefSize(80, 80);
if ("effect".equals(type)) {
colorDisplay.getStyleClass().add("effect-display");
}
Label nameLabel = new Label(name);
nameLabel.getStyleClass().add("color-name");
card.getChildren().addAll(colorDisplay, nameLabel);
return card;
}
private HBox createColorPickerDemo() {
HBox demo = new HBox(20);
demo.setAlignment(Pos.CENTER);
VBox controls = new VBox(10);
controls.setAlignment(Pos.CENTER_LEFT);
Label demoLabel = new Label("Dynamic Styling Demo");
demoLabel.getStyleClass().add("demo-label");
ColorPicker bgPicker = new ColorPicker(Color.web("#3498db"));
bgPicker.getStyleClass().add("demo-picker");
bgPicker.setPromptText("Background Color");
ColorPicker textPicker = new ColorPicker(Color.web("#2c3e50"));
textPicker.getStyleClass().add("demo-picker");
textPicker.setPromptText("Text Color");
Slider borderRadius = new Slider(0, 50, 5);
borderRadius.getStyleClass().add("demo-slider");
borderRadius.setShowTickLabels(true);
borderRadius.setShowTickMarks(true);
Label borderRadiusLabel = new Label("Border Radius: 5px");
Pane preview = new Pane();
preview.getStyleClass().add("demo-preview");
preview.setPrefSize(200, 120);
// Bind properties
bgPicker.valueProperty().addListener((obs, oldVal, newVal) -> {
String hex = toHex(newVal);
preview.setStyle("-fx-background-color: " + hex + ";");
});
textPicker.valueProperty().addListener((obs, oldVal, newVal) -> {
String hex = toHex(newVal);
demoLabel.setStyle("-fx-text-fill: " + hex + ";");
});
borderRadius.valueProperty().addListener((obs, oldVal, newVal) -> {
int radius = newVal.intValue();
preview.setStyle(preview.getStyle() + "-fx-background-radius: " + radius + "px;");
borderRadiusLabel.setText("Border Radius: " + radius + "px");
});
// Set initial style
preview.setStyle("-fx-background-color: #3498db; -fx-background-radius: 5px;");
controls.getChildren().addAll(demoLabel, bgPicker, textPicker, borderRadius, borderRadiusLabel);
demo.getChildren().addAll(controls, preview);
return demo;
}
private String toHex(Color color) {
return String.format("#%02X%02X%02X",
(int) (color.getRed() * 255),
(int) (color.getGreen() * 255),
(int) (color.getBlue() * 255));
}
public static void main(String[] args) {
launch(args);
}
}
/* styles/colors-gradients.css */
.root {
-fx-background-color: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-fx-font-family: "Segoe UI", Arial, sans-serif;
}
.gallery-title {
-fx-text-fill: white;
-fx-font-size: 32px;
-fx-font-weight: bold;
-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.3), 10, 0.5, 0, 2);
}
.section-title {
-fx-text-fill: white;
-fx-font-size: 20px;
-fx-font-weight: 600;
-fx-padding: 10 0 5 0;
}
.color-card {
-fx-background-color: rgba(255,255,255,0.1);
-fx-background-radius: 10px;
-fx-padding: 15;
-fx-border-color: rgba(255,255,255,0.2);
-fx-border-width: 1px;
-fx-border-radius: 10px;
}
.color-display {
-fx-background-radius: 8px;
-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.2), 5, 0.5, 0, 2);
}
.color-name {
-fx-text-fill: white;
-fx-font-size: 12px;
-fx-font-weight: 500;
}
/* Solid Colors */
.color-primary {
-fx-background-color: #3498db;
}
.color-secondary {
-fx-background-color: #95a5a6;
}
.color-success {
-fx-background-color: #2ecc71;
}
.color-danger {
-fx-background-color: #e74c3c;
}
.color-warning {
-fx-background-color: #f39c12;
}
.color-info {
-fx-background-color: #9b59b6;
}
/* Gradient Colors */
.gradient-sunset {
-fx-background-color: linear-gradient(to right, #ff6b6b, #ffa726);
}
.gradient-ocean {
-fx-background-color: linear-gradient(to right, #4facfe, #00f2fe);
}
.gradient-forest {
-fx-background-color: linear-gradient(to right, #43e97b, #38f9d7);
}
.gradient-lavender {
-fx-background-color: linear-gradient(to right, #a18cd1, #fbc2eb);
}
.gradient-sunrise {
-fx-background-color: linear-gradient(to right, #fa709a, #fee140);
}
.gradient-midnight {
-fx-background-color: linear-gradient(to right, #4c669f, #3b5998, #192f6a);
}
/* Transparency & Effects */
.transparent-10 {
-fx-background-color: rgba(52, 152, 219, 0.1);
}
.transparent-25 {
-fx-background-color: rgba(52, 152, 219, 0.25);
}
.transparent-50 {
-fx-background-color: rgba(52, 152, 219, 0.5);
}
.transparent-75 {
-fx-background-color: rgba(52, 152, 219, 0.75);
}
.blur-effect {
-fx-background-color: #3498db;
-fx-effect: dropshadow(gaussian, rgba(52,152,219,0.5), 15, 0.5, 0, 5);
}
.shadow-effect {
-fx-background-color: #3498db;
-fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.8), 10, 0, 0, 5);
}
.effect-display {
-fx-background-color: #3498db;
}
/* Color Picker Demo Styles */
.demo-label {
-fx-font-size: 16px;
-fx-font-weight: bold;
-fx-text-fill: #2c3e50;
}
.demo-picker {
-fx-background-color: white;
-fx-background-radius: 5px;
-fx-border-color: #bdc3c7;
-fx-border-radius: 5px;
-fx-padding: 5;
}
.demo-slider {
-fx-pref-width: 200px;
}
.demo-slider .track {
-fx-background-color: #bdc3c7;
-fx-background-radius: 2px;
}
.demo-slider .thumb {
-fx-background-color: #3498db;
-fx-background-radius: 10px;
}
.demo-preview {
-fx-background-color: #3498db;
-fx-background-radius: 5px;
-fx-border-color: rgba(255,255,255,0.3);
-fx-border-width: 2px;
-fx-border-radius: 5px;
-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.3), 10, 0.5, 0, 3);
}
/* Additional Color Utilities */
.hover-glow:hover {
-fx-effect: dropshadow(gaussian, rgba(52,152,219,0.5), 20, 0.5, 0, 0);
-fx-scale-x: 1.02;
-fx-scale-y: 1.02;
}
.pulse-animation {
-fx-effect: dropshadow(gaussian, rgba(52,152,219,0.7), 20, 0.5, 0, 0);
-fx-animation: pulse 2s infinite;
}
@keyframes pulse {
0% {
-fx-effect: dropshadow(gaussian, rgba(52,152,219,0.7), 20, 0.5, 0, 0);
}
50% {
-fx-effect: dropshadow(gaussian, rgba(52,152,219,0.3), 25, 0.5, 0, 0);
}
100% {
-fx-effect: dropshadow(gaussian, rgba(52,152,219,0.7), 20, 0.5, 0, 0);
}
}
/* Glass morphism effect */
.glass-effect {
-fx-background-color: rgba(255, 255, 255, 0.1);
-fx-background-radius: 15px;
-fx-border-color: rgba(255, 255, 255, 0.2);
-fx-border-width: 1px;
-fx-border-radius: 15px;
-fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.1), 10, 0.5, 0, 4);
}
.glass-effect:hover {
-fx-background-color: rgba(255, 255, 255, 0.15);
-fx-border-color: rgba(255, 255, 255, 0.3);
}

Typography and Fonts

1. Advanced Typography Styling

// TypographyExample.java
public class TypographyExample extends Application {
@Override
public void start(Stage primaryStage) {
ScrollPane root = new ScrollPane();
VBox content = new VBox(20);
content.setPadding(new Insets(20));
Scene scene = new Scene(root, 800, 600);
scene.getStylesheets().addAll(
getClass().getResource("/styles/typography.css").toExternalForm(),
"https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&family=Montserrat:wght@400;600;700&family=Open+Sans:wght@300;400;600&display=swap"
);
// Headers Section
VBox headersSection = createHeadersSection();
// Body Text Section
VBox bodyTextSection = createBodyTextSection();
// Font Weights Section
VBox fontWeightsSection = createFontWeightsSection();
// Text Effects Section
VBox textEffectsSection = createTextEffectsSection();
// Custom Fonts Section
VBox customFontsSection = createCustomFontsSection();
content.getChildren().addAll(
headersSection, bodyTextSection, fontWeightsSection,
textEffectsSection, customFontsSection
);
root.setContent(content);
root.setFitToWidth(true);
primaryStage.setTitle("Typography & Fonts");
primaryStage.setScene(scene);
primaryStage.show();
}
private VBox createHeadersSection() {
VBox section = new VBox(10);
section.getStyleClass().add("typography-section");
Label sectionTitle = new Label("Headers");
sectionTitle.getStyleClass().add("section-title");
Label h1 = new Label("Heading 1 - The Quick Brown Fox");
h1.getStyleClass().add("h1");
Label h2 = new Label("Heading 2 - The Quick Brown Fox");
h2.getStyleClass().add("h2");
Label h3 = new Label("Heading 3 - The Quick Brown Fox");
h3.getStyleClass().add("h3");
Label h4 = new Label("Heading 4 - The Quick Brown Fox");
h4.getStyleClass().add("h4");
Label h5 = new Label("Heading 5 - The Quick Brown Fox");
h5.getStyleClass().add("h5");
Label h6 = new Label("Heading 6 - The Quick Brown Fox");
h6.getStyleClass().add("h6");
section.getChildren().addAll(sectionTitle, h1, h2, h3, h4, h5, h6);
return section;
}
private VBox createBodyTextSection() {
VBox section = new VBox(10);
section.getStyleClass().add("typography-section");
Label sectionTitle = new Label("Body Text");
sectionTitle.getStyleClass().add("section-title");
Label largeText = new Label("Large Body Text - Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
largeText.getStyleClass().add("body-large");
Label normalText = new Label("Normal Body Text - Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
normalText.getStyleClass().add("body-normal");
Label smallText = new Label("Small Body Text - Ut enim ad minim veniam, quis nostrud exercitation ullamco.");
smallText.getStyleClass().add("body-small");
Label caption = new Label("Caption Text - This is a caption or helper text");
caption.getStyleClass().add("caption");
section.getChildren().addAll(sectionTitle, largeText, normalText, smallText, caption);
return section;
}
private VBox createFontWeightsSection() {
VBox section = new VBox(10);
section.getStyleClass().add("typography-section");
Label sectionTitle = new Label("Font Weights");
sectionTitle.getStyleClass().add("section-title");
String[] weights = {"light", "normal", "medium", "semibold", "bold", "black"};
String[] weightNames = {"Light (300)", "Normal (400)", "Medium (500)", "Semibold (600)", "Bold (700)", "Black (900)"};
for (int i = 0; i < weights.length; i++) {
Label weightLabel = new Label(weightNames[i] + " - The Quick Brown Fox");
weightLabel.getStyleClass().addAll("font-weight", "weight-" + weights[i]);
section.getChildren().add(weightLabel);
}
return section;
}
private VBox createTextEffectsSection() {
VBox section = new VBox(10);
section.getStyleClass().add("typography-section");
Label sectionTitle = new Label("Text Effects");
sectionTitle.getStyleClass().add("section-title");
Label shadow = new Label("Text with Shadow Effect");
shadow.getStyleClass().add("text-shadow");
Label glow = new Label("Text with Glow Effect");
glow.getStyleClass().add("text-glow");
Label outline = new Label("Text with Outline");
outline.getStyleClass().add("text-outline");
Label gradient = new Label("Gradient Text Effect");
gradient.getStyleClass().add("text-gradient");
Label reflection = new Label("Text with Reflection");
reflection.getStyleClass().add("text-reflection");
section.getChildren().addAll(sectionTitle, shadow, glow, outline, gradient, reflection);
return section;
}
private VBox createCustomFontsSection() {
VBox section = new VBox(10);
section.getStyleClass().add("typography-section");
Label sectionTitle = new Label("Custom Font Families");
sectionTitle.getStyleClass().add("section-title");
Label roboto = new Label("Roboto - The Quick Brown Fox");
roboto.getStyleClass().add("font-roboto");
Label montserrat = new Label("Montserrat - The Quick Brown Fox");
montserrat.getStyleClass().add("font-montserrat");
Label openSans = new Label("Open Sans - The Quick Brown Fox");
openSans.getStyleClass().add("font-open-sans");
Label codeFont = new Label("Monospace - System.out.println('Hello World');");
codeFont.getStyleClass().add("font-monospace");
section.getChildren().addAll(sectionTitle, roboto, montserrat, openSans, codeFont);
return section;
}
public static void main(String[] args) {
launch(args);
}
}
/* styles/typography.css */
.root {
-fx-background-color: #f8f9fa;
-fx-font-family: "Segoe UI", Arial, sans-serif;
}
.typography-section {
-fx-background-color: white;
-fx-padding: 20;
-fx-background-radius: 10px;
-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.1), 10, 0.5, 0, 2);
-fx-border-color: #e9ecef;
-fx-border-width: 1px;
-fx-border-radius: 10px;
}
.section-title {
-fx-text-fill: #2c3e50;
-fx-font-size: 24px;
-fx-font-weight: bold;
-fx-padding: 0 0 10 0;
-fx-border-color: #3498db;
-fx-border-width: 0 0 3 0;
}
/* Headers */
.h1 {
-fx-font-family: "Montserrat", "Segoe UI", sans-serif;
-fx-font-size: 48px;
-fx-font-weight: bold;
-fx-text-fill: #2c3e50;
-fx-line-spacing: 1.1;
}
.h2 {
-fx-font-family: "Montserrat", "Segoe UI", sans-serif;
-fx-font-size: 36px;
-fx-font-weight: 600;
-fx-text-fill: #2c3e50;
-fx-line-spacing: 1.2;
}
.h3 {
-fx-font-family: "Montserrat", "Segoe UI", sans-serif;
-fx-font-size: 28px;
-fx-font-weight: 600;
-fx-text-fill: #34495e;
-fx-line-spacing: 1.3;
}
.h4 {
-fx-font-size: 24px;
-fx-font-weight: 600;
-fx-text-fill: #34495e;
-fx-line-spacing: 1.3;
}
.h5 {
-fx-font-size: 20px;
-fx-font-weight: 600;
-fx-text-fill: #34495e;
-fx-line-spacing: 1.4;
}
.h6 {
-fx-font-size: 16px;
-fx-font-weight: 600;
-fx-text-fill: #34495e;
-fx-line-spacing: 1.4;
}
/* Body Text */
.body-large {
-fx-font-size: 18px;
-fx-text-fill: #495057;
-fx-line-spacing: 1.5;
}
.body-normal {
-fx-font-size: 16px;
-fx-text-fill: #495057;
-fx-line-spacing: 1.5;
}
.body-small {
-fx-font-size: 14px;
-fx-text-fill: #6c757d;
-fx-line-spacing: 1.4;
}
.caption {
-fx-font-size: 12px;
-fx-text-fill: #868e96;
-fx-font-style: italic;
}
/* Font Weights */
.font-weight {
-fx-font-size: 16px;
-fx-text-fill: #2c3e50;
}
.weight-light {
-fx-font-weight: 300;
}
.weight-normal {
-fx-font-weight: 400;
}
.weight-medium {
-fx-font-weight: 500;
}
.weight-semibold {
-fx-font-weight: 600;
}
.weight-bold {
-fx-font-weight: 700;
}
.weight-black {
-fx-font-weight: 900;
}
/* Text Effects */
.text-shadow {
-fx-font-size: 24px;
-fx-font-weight: bold;
-fx-text-fill: #2c3e50;
-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.3), 8, 0.5, 2, 2);
}
.text-glow {
-fx-font-size: 24px;
-fx-font-weight: bold;
-fx-text-fill: #3498db;
-fx-effect: dropshadow(gaussian, rgba(52,152,219,0.7), 15, 0.7, 0, 0);
}
.text-outline {
-fx-font-size: 24px;
-fx-font-weight: bold;
-fx-text-fill: white;
-fx-effect: dropshadow(three-pass-box, black, 4, 0, 0, 0);
}
.text-gradient {
-fx-font-size: 24px;
-fx-font-weight: bold;
-fx-text-fill: linear-gradient(to right, #ff6b6b, #ffa726);
}
.text-reflection {
-fx-font-size: 24px;
-fx-font-weight: bold;
-fx-text-fill: #2c3e50;
-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.3), 8, 0.5, 2, 2),
innershadow(gaussian, rgba(255,255,255,0.5), 0, 0, 0, 1);
}
/* Custom Font Families */
.font-roboto {
-fx-font-family: "Roboto", sans-serif;
-fx-font-size: 18px;
-fx-text-fill: #2c3e50;
}
.font-montserrat {
-fx-font-family: "Montserrat", sans-serif;
-fx-font-size: 18px;
-fx-font-weight: 600;
-fx-text-fill: #2c3e50;
}
.font-open-sans {
-fx-font-family: "Open Sans", sans-serif;
-fx-font-size: 18px;
-fx-text-fill: #2c3e50;
}
.font-monospace {
-fx-font-family: "Consolas", "Monaco", "Courier New", monospace;
-fx-font-size: 16px;
-fx-text-fill: #e74c3c;
-fx-background-color: #f8f9fa;
-fx-padding: 10;
-fx-background-radius: 5px;
-fx-border-color: #e9ecef;
-fx-border-width: 1px;
-fx-border-radius: 5px;
}
/* Text Alignment Classes */
.text-left {
-fx-text-alignment: left;
}
.text-center {
-fx-text-alignment: center;
}
.text-right {
-fx-text-alignment: right;
}
.text-justify {
-fx-text-alignment: justify;
}
/* Text Transformation */
.text-uppercase {
-fx-text-transform: uppercase;
}
.text-lowercase {
-fx-text-transform: lowercase;
}
.text-capitalize {
-fx-text-transform: capitalize;
}
/* Letter and Word Spacing */
.letter-spacing-wide {
-fx-letter-spacing: 2px;
}
.letter-spacing-tight {
-fx-letter-spacing: -1px;
}
.word-spacing-wide {
-fx-word-spacing: 8px;
}
/* Text Decoration */
.text-underline {
-fx-underline: true;
}
.text-line-through {
-fx-strikethrough: true;
}
.text-overline {
/* JavaFX doesn't support overline directly */
-fx-border-color: currentColor;
-fx-border-width: 1 0 0 0;
}

Borders and Backgrounds

1. Advanced Border and Background Styling

// BorderBackgroundExample.java
public class BorderBackgroundExample extends Application {
@Override
public void start(Stage primaryStage) {
ScrollPane root = new ScrollPane();
VBox content = new VBox(25);
content.setPadding(new Insets(25));
Scene scene = new Scene(root, 900, 700);
scene.getStylesheets().add(getClass().getResource("/styles/borders-backgrounds.css").toExternalForm());
// Border Styles Section
VBox borderSection = createBorderStylesSection();
// Border Radius Section
VBox borderRadiusSection = createBorderRadiusSection();
// Background Styles Section
VBox backgroundSection = createBackgroundStylesSection();
// Combined Effects Section
VBox combinedSection = createCombinedEffectsSection();
content.getChildren().addAll(borderSection, borderRadiusSection, backgroundSection, combinedSection);
root.setContent(content);
root.setFitToWidth(true);
primaryStage.setTitle("Borders & Backgrounds");
primaryStage.setScene(scene);
primaryStage.show();
}
private VBox createBorderStylesSection() {
VBox section = new VBox(15);
section.getStyleClass().add("demo-section");
Label sectionTitle = new Label("Border Styles");
sectionTitle.getStyleClass().add("section-title");
HBox borderExamples = new HBox(20);
borderExamples.setAlignment(Pos.CENTER);
String[] borderStyles = {
"border-solid", "border-dashed", "border-dotted",
"border-double", "border-groove", "border-ridge"
};
String[] borderNames = {
"Solid", "Dashed", "Dotted", "Double", "Groove", "Ridge"
};
for (int i = 0; i < borderStyles.length; i++) {
VBox borderExample = createBorderExample(borderNames[i], borderStyles[i]);
borderExamples.getChildren().add(borderExample);
}
section.getChildren().addAll(sectionTitle, borderExamples);
return section;
}
private VBox createBorderExample(String name, String styleClass) {
VBox example = new VBox(10);
example.setAlignment(Pos.CENTER);
Pane borderBox = new Pane();
borderBox.getStyleClass().addAll("border-box", styleClass);
borderBox.setPrefSize(100, 80);
Label nameLabel = new Label(name);
nameLabel.getStyleClass().add("example-name");
example.getChildren().addAll(borderBox, nameLabel);
return example;
}
private VBox createBorderRadiusSection() {
VBox section = new VBox(15);
section.getStyleClass().add("demo-section");
Label sectionTitle = new Label("Border Radius Variations");
sectionTitle.getStyleClass().add("section-title");
HBox radiusExamples = new HBox(20);
radiusExamples.setAlignment(Pos.CENTER);
String[] radiusStyles = {
"radius-small", "radius-medium", "radius-large",
"radius-pill", "radius-circle", "radius-custom"
};
String[] radiusNames = {
"Small (4px)", "Medium (8px)", "Large (16px)",
"Pill (25px)", "Circle", "Custom Shape"
};
for (int i = 0; i < radiusStyles.length; i++) {
VBox radiusExample = createBorderExample(radiusNames[i], radiusStyles[i]);
radiusExamples.getChildren().add(radiusExample);
}
section.getChildren().addAll(sectionTitle, radiusExamples);
return section;
}
private VBox createBackgroundStylesSection() {
VBox section = new VBox(15);
section.getStyleClass().add("demo-section");
Label sectionTitle = new Label("Background Styles");
sectionTitle.getStyleClass().add("section-title");
HBox backgroundExamples = new HBox(20);
backgroundExamples.setAlignment(Pos.CENTER);
String[] backgroundStyles = {
"bg-solid", "bg-gradient-linear", "bg-gradient-radial",
"bg-pattern", "bg-image", "bg-glass"
};
String[] backgroundNames = {
"Solid Color", "Linear Gradient", "Radial Gradient",
"Pattern", "Image", "Glass Effect"
};
for (int i = 0; i < backgroundStyles.length; i++) {
VBox bgExample = createBackgroundExample(backgroundNames[i], backgroundStyles[i]);
backgroundExamples.getChildren().add(bgExample);
}
section.getChildren().addAll(sectionTitle, backgroundExamples);
return section;
}
private VBox createBackgroundExample(String name, String styleClass) {
VBox example = new VBox(10);
example.setAlignment(Pos.CENTER);
Pane bgBox = new Pane();
bgBox.getStyleClass().addAll("background-box", styleClass);
bgBox.setPrefSize(120, 100);
Label nameLabel = new Label(name);
nameLabel.getStyleClass().add("example-name");
example.getChildren().addAll(bgBox, nameLabel);
return example;
}
private VBox createCombinedEffectsSection() {
VBox section = new VBox(15);
section.getStyleClass().add("demo-section");
Label sectionTitle = new Label("Combined Effects");
sectionTitle.getStyleClass().add("section-title");
HBox combinedExamples = new HBox(20);
combinedExamples.setAlignment(Pos.CENTER);
String[] combinedStyles = {
"effect-neomorphic", "effect-floating", "effect-embossed",
"effect-debossed", "effect-glow", "effect-shadow-deep"
};
String[] combinedNames = {
"Neomorphic", "Floating", "Embossed",
"Debossed", "Glow", "Deep Shadow"
};
for (int i = 0; i < combinedStyles.length; i++) {
VBox combinedExample = createCombinedExample(combinedNames[i], combinedStyles[i]);
combinedExamples.getChildren().add(combinedExample);
}
section.getChildren().addAll(sectionTitle, combinedExamples);
return section;
}
private VBox createCombinedExample(String name, String styleClass) {
VBox example = new VBox(10);
example.setAlignment(Pos.CENTER);
Pane effectBox = new Pane();
effectBox.getStyleClass().addAll("effect-box", styleClass);
effectBox.setPrefSize(120, 100);
Label nameLabel = new Label(name);
nameLabel.getStyleClass().add("example-name");
example.getChildren().addAll(effectBox, nameLabel);
return example;
}
public static void main(String[] args) {
launch(args);
}
}
/* styles/borders-backgrounds.css */
.root {
-fx-background-color: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-fx-font-family: "Segoe UI", Arial, sans-serif;
}
.demo-section {
-fx-background-color: rgba(255, 255, 255, 0.95);
-fx-padding: 25;
-fx-background-radius: 15px;
-fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.1), 15, 0.5, 0, 5);
-fx-border-color: rgba(255, 255, 255, 0.2);
-fx-border-width: 1px;
-fx-border-radius: 15px;
}
.section-title {
-fx-text-fill: #2c3e50;
-fx-font-size: 28px;
-fx-font-weight: bold;
-fx-padding: 0 0 15 0;
-fx-border-color: #3498db;
-fx-border-width: 0 0 3 0;
-fx-border-radius: 0;
}
.example-name {
-fx-text-fill: #2c3e50;
-fx-font-size: 14px;
-fx-font-weight: 500;
}
/* Border Box Base Style */
.border-box {
-fx-background-color: #ecf0f1;
-fx-border-width: 3px;
-fx-border-color: #3498db;
}
/* Border Style Variations */
.border-solid {
-fx-border-style: solid;
}
.border-dashed {
-fx-border-style: dashed;
-fx-border-width: 3px;
}
.border-dotted {
-fx-border-style: dotted;
-fx-border-width: 3px;
}
.border-double {
-fx-border-style: double;
-fx-border-width: 5px;
}
.border-groove {
-fx-border-style: groove;
-fx-border-width: 5px;
-fx-border-color: #3498db #2980b9 #2980b9 #3498db;
}
.border-ridge {
-fx-border-style: ridge;
-fx-border-width: 5px;
-fx-border-color: #2980b9 #3498db #3498db #2980b9;
}
/* Border Radius Variations */
.radius-small {
-fx-background-radius: 4px;
-fx-border-radius: 4px;
}
.radius-medium {
-fx-background-radius: 8px;
-fx-border-radius: 8px;
}
.radius-large {
-fx-background-radius: 16px;
-fx-border-radius: 16px;
}
.radius-pill {
-fx-background-radius: 25px;
-fx-border-radius: 25px;
}
.radius-circle {
-fx-background-radius: 50%;
-fx-border-radius: 50%;
-fx-pref-width: 80px;
-fx-pref-height: 80px;
}
.radius-custom {
-fx-background-radius: 15px 5px 15px 5px;
-fx-border-radius: 15px 5px 15px 5px;
}
/* Background Box Base Style */
.background-box {
-fx-border-color: #bdc3c7;
-fx-border-width: 1px;
-fx-border-radius: 8px;
-fx-background-radius: 8px;
}
/* Background Style Variations */
.bg-solid {
-fx-background-color: #3498db;
}
.bg-gradient-linear {
-fx-background-color: linear-gradient(to right bottom, #667eea, #764ba2);
}
.bg-gradient-radial {
-fx-background-color: radial-gradient(center 50% 50%, radius 70%, #667eea, #764ba2);
}
.bg-pattern {
-fx-background-color: repeating-linear-gradient(
45deg,
#3498db,
#3498db 10px,
#2980b9 10px,
#2980b9 20px
);
}
.bg-image {
-fx-background-color: linear-gradient(rgba(52, 152, 219, 0.8), rgba(41, 128, 185, 0.8)),
url('https://via.placeholder.com/120x100/3498db/ffffff?text=BG+Image');
-fx-background-size: cover;
-fx-background-position: center;
}
.bg-glass {
-fx-background-color: rgba(255, 255, 255, 0.1);
-fx-border-color: rgba(255, 255, 255, 0.2);
-fx-border-width: 1px;
-fx-background-radius: 8px;
-fx-border-radius: 8px;
-fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.1), 10, 0.5, 0, 2);
}
/* Effect Box Base Style */
.effect-box {
-fx-background-color: #ecf0f1;
-fx-background-radius: 8px;
}
/* Combined Effect Variations */
.effect-neomorphic {
-fx-background-color: #ecf0f1;
-fx-background-radius: 15px;
-fx-effect: dropshadow(gaussian, #d1d9e6, 10, 0, 5, 5),
dropshadow(gaussian, #ffffff, 10, 0, -5, -5);
}
.effect-floating {
-fx-background-color: white;
-fx-background-radius: 12px;
-fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.15), 20, 0.5, 0, 8);
-fx-border-color: rgba(255, 255, 255, 0.5);
-fx-border-width: 1px;
-fx-border-radius: 12px;
}
.effect-embossed {
-fx-background-color: linear-gradient(to bottom right, #ffffff, #e0e0e0);
-fx-background-radius: 10px;
-fx-border-color: #c0c0c0 #e0e0e0 #e0e0e0 #c0c0c0;
-fx-border-width: 2px;
-fx-border-radius: 10px;
-fx-effect: innershadow(gaussian, rgba(0, 0, 0, 0.1), 5, 0.5, 1, 1);
}
.effect-debossed {
-fx-background-color: linear-gradient(to bottom right, #e0e0e0, #ffffff);
-fx-background-radius: 10px;
-fx-border-color: #e0e0e0 #c0c0c0 #c0c0c0 #e0e0e0;
-fx-border-width: 2px;
-fx-border-radius: 10px;
-fx-effect: innershadow(gaussian, rgba(0, 0, 0, 0.2), 5, 0.5, 1, 1);
}
.effect-glow {
-fx-background-color: #3498db;
-fx-background-radius: 10px;
-fx-effect: dropshadow(gaussian, rgba(52, 152, 219, 0.6), 20, 0.7, 0, 0);
-fx-border-color: rgba(255, 255, 255, 0.3);
-fx-border-width: 1px;
-fx-border-radius: 10px;
}
.effect-shadow-deep {
-fx-background-color: white;
-fx-background-radius: 10px;
-fx-effect: dropshadow(three-pass-box, rgba(0, 0, 0, 0.3), 15, 0.5, 0, 5);
-fx-border-color: #f0f0f0;
-fx-border-width: 1px;
-fx-border-radius: 10px;
}
/* Interactive Effects */
.border-box:hover, .background-box:hover, .effect-box:hover {
-fx-scale-x: 1.05;
-fx-scale-y: 1.05;
-fx-cursor: hand;
}
/* Border Width Variations */
.border-thin {
-fx-border-width: 1px;
}
.border-medium {
-fx-border-width: 3px;
}
.border-thick {
-fx-border-width: 5px;
}
.border-extra-thick {
-fx-border-width: 8px;
}
/* Border Color Variations */
.border-primary {
-fx-border-color: #3498db;
}
.border-success {
-fx-border-color: #2ecc71;
}
.border-warning {
-fx-border-color: #f39c12;
}
.border-danger {
-fx-border-color: #e74c3c;
}
/* Complex Border Examples */
.border-multi-color {
-fx-border-color: #3498db #2ecc71 #e74c3c #f39c12;
-fx-border-width: 4px;
}
.border-gradient {
-fx-border-color: linear-gradient(to right, #3498db, #2ecc71);
-fx-border-width: 4px;
}
/* Background Size and Position */
.bg-cover {
-fx-background-size: cover;
}
.bg-contain {
-fx-background-size: contain;
}
.bg-center {
-fx-background-position: center;
}
.bg-top-left {
-fx-background-position: top left;
}
/* Multiple Backgrounds */
.bg-multiple {
-fx-background-color: linear-gradient(rgba(52, 152, 219, 0.8), rgba(41, 128, 185, 0.8)),
url('pattern.png');
-fx-background-size: cover, auto;
}

Animations and Transitions

1. CSS Animations and Transitions

// AnimationExample.java
public class AnimationExample extends Application {
@Override
public void start(Stage primaryStage) {
VBox root = new VBox(20);
root.setPadding(new Insets(20));
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 800, 600);
scene.getStylesheets().add(getClass().getResource("/styles/animations.css").toExternalForm());
// Title
Label title = new Label("CSS Animations & Transitions");
title.getStyleClass().add("animation-title");
// Transitions Section
VBox transitionsSection = createTransitionsSection();
// Keyframe Animations Section
VBox animationsSection = createAnimationsSection();
// Interactive Animations Section
VBox interactiveSection = createInteractiveSection();
// Loading Animations Section
VBox loadingSection = createLoadingAnimationsSection();
root.getChildren().addAll(title, transitionsSection, animationsSection, interactiveSection, loadingSection);
primaryStage.setTitle("CSS Animations");
primaryStage.setScene(scene);
primaryStage.show();
}
private VBox createTransitionsSection() {
VBox section = new VBox(15);
section.getStyleClass().add("animation-section");
Label sectionTitle = new Label("CSS Transitions");
sectionTitle.getStyleClass().add("section-title");
HBox transitions = new HBox(20);
transitions.setAlignment(Pos.CENTER);
// Color Transition
Button colorTransition = new Button("Color Transition");
colorTransition.getStyleClass().add("transition-color");
// Scale Transition
Button scaleTransition = new Button("Scale Transition");
scaleTransition.getStyleClass().add("transition-scale");
// Rotation Transition
Pane rotateBox = new Pane();
rotateBox.getStyleClass().addAll("transition-box", "transition-rotate");
rotateBox.setPrefSize(80, 80);
VBox rotateExample = new VBox(10, new Label("Rotation"), rotateBox);
rotateExample.setAlignment(Pos.CENTER);
// Opacity Transition
Pane opacityBox = new Pane();
opacityBox.getStyleClass().addAll("transition-box", "transition-opacity");
opacityBox.setPrefSize(80, 80);
VBox opacityExample = new VBox(10, new Label("Opacity"), opacityBox);
opacityExample.setAlignment(Pos.CENTER);
transitions.getChildren().addAll(colorTransition, scaleTransition, rotateExample, opacityExample);
section.getChildren().addAll(sectionTitle, transitions);
return section;
}
private VBox createAnimationsSection() {
VBox section = new VBox(15);
section.getStyleClass().add("animation-section");
Label sectionTitle = new Label("Keyframe Animations");
sectionTitle.getStyleClass().add("section-title");
HBox animations = new HBox(20);
animations.setAlignment(Pos.CENTER);
// Bounce Animation
Pane bounceBox = new Pane();
bounceBox.getStyleClass().addAll("animation-box", "animation-bounce");
bounceBox.setPrefSize(60, 60);
VBox bounceExample = new VBox(10, new Label("Bounce"), bounceBox);
bounceExample.setAlignment(Pos.CENTER);
// Pulse Animation
Pane pulseBox = new Pane();
pulseBox.getStyleClass().addAll("animation-box", "animation-pulse");
pulseBox.setPrefSize(60, 60);
VBox pulseExample = new VBox(10, new Label("Pulse"), pulseBox);
pulseExample.setAlignment(Pos.CENTER);
// Spin Animation
Pane spinBox = new Pane();
spinBox.getStyleClass().addAll("animation-box", "animation-spin");
spinBox.setPrefSize(60, 60);
VBox spinExample = new VBox(10, new Label("Spin"), spinBox);
spinExample.setAlignment(Pos.CENTER);
// Slide Animation
Pane slideBox = new Pane();
slideBox.getStyleClass().addAll("animation-box", "animation-slide");
slideBox.setPrefSize(60, 60);
VBox slideExample = new VBox(10, new Label("Slide"), slideBox);
slideExample.setAlignment(Pos.CENTER);
animations.getChildren().addAll(bounceExample, pulseExample, spinExample, slideExample);
section.getChildren().addAll(sectionTitle, animations);
return section;
}
private VBox createInteractiveSection() {
VBox section = new VBox(15);
section.getStyleClass().add("animation-section");
Label sectionTitle = new Label("Interactive Animations");
sectionTitle.getStyleClass().add("section-title");
HBox interactive = new HBox(20);
interactive.setAlignment(Pos.CENTER);
// Hover Effects
Button hoverButton = new Button("Hover Me");
hoverButton.getStyleClass().add("interactive-hover");
// Click Effects
Button clickButton = new Button("Click Me");
clickButton.getStyleClass().add("interactive-click");
// Focus Effects
TextField focusField = new TextField();
focusField.setPromptText("Focus me");
focusField.getStyleClass().add("interactive-focus");
// Drag Hint
Pane dragBox = new Pane();
dragBox.getStyleClass().addAll("interactive-box", "interactive-drag");
dragBox.setPrefSize(80, 80);
VBox dragExample = new VBox(10, new Label("Drag Hint"), dragBox);
dragExample.setAlignment(Pos.CENTER);
interactive.getChildren().addAll(hoverButton, clickButton, focusField, dragExample);
section.getChildren().addAll(sectionTitle, interactive);
return section;
}
private VBox createLoadingAnimationsSection() {
VBox section = new VBox(15);
section.getStyleClass().add("animation-section");
Label sectionTitle = new Label("Loading Animations");
sectionTitle.getStyleClass().add("section-title");
HBox loading = new HBox(30);
loading.setAlignment(Pos.CENTER);
// Spinner
Pane spinner = new Pane();
spinner.getStyleClass().add("loading-spinner");
spinner.setPrefSize(60, 60);
VBox spinnerExample = new VBox(10, new Label("Spinner"), spinner);
spinnerExample.setAlignment(Pos.CENTER);
// Progress Bar
Pane progressBar = new Pane();
progressBar.getStyleClass().add("loading-progress");
progressBar.setPrefSize(150, 20);
VBox progressExample = new VBox(10, new Label("Progress"), progressBar);
progressExample.setAlignment(Pos.CENTER);
// Pulse Dots
HBox pulseDots = new HBox(5);
pulseDots.setAlignment(Pos.CENTER);
for (int i = 0; i < 3; i++) {
Pane dot = new Pane();
dot.getStyleClass().add("loading-dot");
dot.setPrefSize(15, 15);
pulseDots.getChildren().add(dot);
}
VBox dotsExample = new VBox(10, new Label("Pulse Dots"), pulseDots);
dotsExample.setAlignment(Pos.CENTER);
loading.getChildren().addAll(spinnerExample, progressExample, dotsExample);
section.getChildren().addAll(sectionTitle, loading);
return section;
}
public static void main(String[] args) {
launch(args);
}
}
/* styles/animations.css */
.root {
-fx-background-color: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-fx-font-family: "Segoe UI", Arial, sans-serif;
}
.animation-title {
-fx-text-fill: white;
-fx-font-size: 32px;
-fx-font-weight: bold;
-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.3), 10, 0.5, 0, 2);
}
.animation-section {
-fx-background-color: rgba(255, 255, 255, 0.95);
-fx-padding: 25;
-fx-background-radius: 15px;
-fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.1), 15, 0.5, 0, 5);
-fx-border-color: rgba(255, 255, 255, 0.2);
-fx-border-width: 1px;
-fx-border-radius: 15px;
}
.section-title {
-fx-text-fill: #2c3e50;
-fx-font-size: 24px;
-fx-font-weight: bold;
-fx-padding: 0 0 15 0;
-fx-border-color: #3498db;
-fx-border-width: 0 0 3 0;
}
/* Transition Styles */
.transition-color {
-fx-background-color: #3498db;
-fx-text-fill: white;
-fx-font-size: 14px;
-fx-font-weight: bold;
-fx-padding: 12 24;
-fx-background-radius: 6px;
-fx-border-radius: 6px;
-fx-cursor: hand;
-fx-transition: all 0.3s ease-in-out;
}
.transition-color:hover {
-fx-background-color: #2980b9;
-fx-scale-x: 1.05;
-fx-scale-y: 1.05;
}
.transition-scale {
-fx-background-color: #2ecc71;
-fx-text-fill: white;
-fx-font-size: 14px;
-fx-font-weight: bold;
-fx-padding: 12 24;
-fx-background-radius: 6px;
-fx-border-radius: 6px;
-fx-cursor: hand;
-fx-transition: transform 0.2s ease-in-out;
}
.transition-scale:hover {
-fx-scale-x: 1.1;
-fx-scale-y: 1.1;
}
.transition-box {
-fx-background-color: #3498db;
-fx-background-radius: 8px;
}
.transition-rotate {
-fx-transition: rotate 0.5s ease-in-out;
}
.transition-rotate:hover {
-fx-rotate: 45;
}
.transition-opacity {
-fx-opacity: 1;
-fx-transition: opacity 0.5s ease-in-out;
}
.transition-opacity:hover {
-fx-opacity: 0.5;
}
/* Keyframe Animation Styles */
.animation-box {
-fx-background-color: #e74c3c;
-fx-background-radius: 8px;
}
.animation-bounce {
-fx-animation: bounce 2s infinite;
}
@keyframes bounce {
0%, 20%, 50%, 80%, 100% {
-fx-translate-y: 0;
}
40% {
-fx-translate-y: -30px;
}
60% {
-fx-translate-y: -15px;
}
}
.animation-pulse {
-fx-animation: pulse 2s infinite;
}
@keyframes pulse {
0% {
-fx-scale-x: 1;
-fx-scale-y: 1;
-fx-opacity: 1;
}
50% {
-fx-scale-x: 1.1;
-fx-scale-y: 1.1;
-fx-opacity: 0.7;
}
100% {
-fx-scale-x: 1;
-fx-scale-y: 1;
-fx-opacity: 1;
}
}
.animation-spin {
-fx-animation: spin 3s linear infinite;
}
@keyframes spin {
from {
-fx-rotate: 0;
}
to {
-fx-rotate: 360;
}
}
.animation-slide {
-fx-animation: slide 3s ease-in-out infinite;
}
@keyframes slide {
0%, 100% {
-fx-translate-x: 0;
}
50% {
-fx-translate-x: 100px;
}
}
/* Interactive Animation Styles */
.interactive-hover {
-fx-background-color: #9b59b6;
-fx-text-fill: white;
-fx-font-size: 14px;
-fx-font-weight: bold;
-fx-padding: 12 24;
-fx-background-radius: 25px;
-fx-border-radius: 25px;
-fx-cursor: hand;
-fx-transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.interactive-hover:hover {
-fx-background-color: #8e44ad;
-fx-scale-x: 1.05;
-fx-scale-y: 1.05;
-fx-effect: dropshadow(gaussian, rgba(155, 89, 182, 0.4), 15, 0.5, 0, 4);
}
.interactive-click {
-fx-background-color: #f39c12;
-fx-text-fill: white;
-fx-font-size: 14px;
-fx-font-weight: bold;
-fx-padding: 12 24;
-fx-background-radius: 6px;
-fx-border-radius: 6px;
-fx-cursor: hand;
-fx-transition: all 0.1s ease-in-out;
}
.interactive-click:pressed {
-fx-background-color: #e67e22;
-fx-scale-x: 0.95;
-fx-scale-y: 0.95;
-fx-effect: innershadow(gaussian, rgba(0, 0, 0, 0.2), 10, 0.5, 0, 2);
}
.interactive-focus {
-fx-background-color: white;
-fx-background-radius: 6px;
-fx-border-color: #bdc3c7;
-fx-border-radius: 6px;
-fx-padding: 8 12;
-fx-font-size: 14px;
-fx-transition: all 0.3s ease-in-out;
}
.interactive-focus:focused {
-fx-border-color: #3498db;
-fx-border-width: 2px;
-fx-effect: dropshadow(gaussian, rgba(52, 152, 219, 0.3), 10, 0.5, 0, 0);
-fx-scale-x: 1.02;
-fx-scale-y: 1.02;
}
.interactive-box {
-fx-background-color: #3498db;
-fx-background-radius: 8px;
-fx-cursor: hand;
}
.interactive-drag {
-fx-transition: all 0.3s ease-in-out;
}
.interactive-drag:hover {
-fx-background-color: #2980b9;
-fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.3), 10, 0.5, 0, 5);
}
/* Loading Animation Styles */
.loading-spinner {
-fx-background-color: transparent;
-fx-border-color: #3498db #e3e3e3 #e3e3e3 #e3e3e7;
-fx-border-width: 4px;
-fx-border-radius: 50%;
-fx-animation: spinner-rotate 1s linear infinite;
}
@keyframes spinner-rotate {
0% {
-fx-rotate: 0;
}
100% {
-fx-rotate: 360;
}
}
.loading-progress {
-fx-background-color: #ecf0f1;
-fx-background-radius: 10px;
-fx-border-radius: 10px;
-fx-effect: innershadow(gaussian, rgba(0, 0, 0, 0.1), 5, 0.5, 0, 1);
}
.loading-progress:before {
-fx-background-color: #3498db;
-fx-background-radius: 10px;
-fx-pref-width: 50%;
-fx-animation: progress-loading 2s ease-in-out infinite;
}
@keyframes progress-loading {
0% {
-fx-pref-width: 0%;
}
50% {
-fx-pref-width: 100%;
}
100% {
-fx-pref-width: 0%;
}
}
.loading-dot {
-fx-background-color: #3498db;
-fx-background-radius: 50%;
-fx-animation: dot-pulse 1.5s ease-in-out infinite;
}
.loading-dot:nth-child(2) {
-fx-animation-delay: 0.2s;
}
.loading-dot:nth-child(3) {
-fx-animation-delay: 0.4s;
}
@keyframes dot-pulse {
0%, 100% {
-fx-scale-x: 1;
-fx-scale-y: 1;
-fx-opacity: 1;
}
50% {
-fx-scale-x: 1.5;
-fx-scale-y: 1.5;
-fx-opacity: 0.5;
}
}
/* Additional Animation Effects */
.fade-in {
-fx-opacity: 0;
-fx-animation: fadeIn 0.5s ease-in-out forwards;
}
@keyframes fadeIn {
from {
-fx-opacity: 0;
-fx-translate-y: 20px;
}
to {
-fx-opacity: 1;
-fx-translate-y: 0;
}
}
.slide-in-left {
-fx-translate-x: -100%;
-fx-animation: slideInLeft 0.5s ease-out forwards;
}
@keyframes slideInLeft {
to {
-fx-translate-x: 0;
}
}
.zoom-in {
-fx-scale-x: 0;
-fx-scale-y: 0;
-fx-animation: zoomIn 0.3s ease-out forwards;
}
@keyframes zoomIn {
to {
-fx-scale-x: 1;
-fx-scale-y: 1;
}
}
/* Staggered animations for multiple elements */
.stagger-item {
-fx-opacity: 0;
-fx-translate-y: 20px;
}
.stagger-item:nth-child(1) {
-fx-animation: fadeInUp 0.5s ease-out 0.1s forwards;
}
.stagger-item:nth-child(2) {
-fx-animation: fadeInUp 0.5s ease-out 0.2s forwards;
}
.stagger-item:nth-child(3) {
-fx-animation: fadeInUp 0.5s ease-out 0.3s forwards;
}
@keyframes fadeInUp {
to {
-fx-opacity: 1;
-fx-translate-y: 0;
}
}

Best Practices and Patterns

1. CSS Architecture and Organization

/* styles/theme.css */
/* 
* JavaFX CSS Theme Architecture
* Organized by: Variables, Base Styles, Components, Utilities
*/
/* ===== CSS VARIABLES ===== */
.root {
/* Primary Colors */
-primary-color: #3498db;
-primary-dark: #2980b9;
-primary-light: #5dade2;
/* Secondary Colors */
-secondary-color: #2ecc71;
-secondary-dark: #27ae60;
-secondary-light: #58d68d;
/* Neutral Colors */
-text-primary: #2c3e50;
-text-secondary: #7f8c8d;
-text-muted: #95a5a6;
-bg-primary: #ffffff;
-bg-secondary: #f8f9fa;
-bg-tertiary: #e9ecef;
/* Semantic Colors */
-success-color: #2ecc71;
-warning-color: #f39c12;
-error-color: #e74c3c;
-info-color: #3498db;
/* Border Colors */
-border-color: #dee2e6;
-border-color-light: #e9ecef;
-border-color-dark: #adb5bd;
/* Shadows */
-shadow-sm: dropshadow(gaussian, rgba(0,0,0,0.05), 4, 0.5, 0, 1);
-shadow-md: dropshadow(gaussian, rgba(0,0,0,0.1), 8, 0.5, 0, 2);
-shadow-lg: dropshadow(gaussian, rgba(0,0,0,0.15), 16, 0.5, 0, 4);
-shadow-xl: dropshadow(gaussian, rgba(0,0,0,0.2), 24, 0.5, 0, 8);
/* Border Radius */
-radius-sm: 4px;
-radius-md: 8px;
-radius-lg: 12px;
-radius-xl: 16px;
-radius-pill: 25px;
-radius-circle: 50%;
/* Spacing */
-spacing-xs: 4px;
-spacing-sm: 8px;
-spacing-md: 16px;
-spacing-lg: 24px;
-spacing-xl: 32px;
/* Typography */
-font-family-primary: "Segoe UI", Arial, sans-serif;
-font-family-mono: "Consolas", "Monaco", monospace;
-font-size-xs: 12px;
-font-size-sm: 14px;
-font-size-md: 16px;
-font-size-lg: 18px;
-font-size-xl: 20px;
-font-size-2xl: 24px;
-font-size-3xl: 30px;
-font-weight-light: 300;
-font-weight-normal: 400;
-font-weight-medium: 500;
-font-weight-semibold: 600;
-font-weight-bold: 700;
/* Transitions */
-transition-fast: 0.15s ease-in-out;
-transition-normal: 0.3s ease-in-out;
-transition-slow: 0.5s ease-in-out;
}
/* ===== BASE STYLES ===== */
.root {
-fx-font-family: -font-family-primary;
-fx-background-color: -bg-primary;
-fx-text-fill: -text-primary;
}
/* ===== COMPONENT STYLES ===== */
/* Buttons */
.btn {
-fx-background-color: -bg-primary;
-fx-text-fill: -text-primary;
-fx-font-size: -font-size-sm;
-fx-font-weight: -font-weight-medium;
-fx-padding: -spacing-sm -spacing-md;
-fx-background-radius: -radius-md;
-fx-border-radius: -radius-md;
-fx-border-color: -border-color;
-fx-border-width: 1px;
-fx-cursor: hand;
-fx-transition: all -transition-fast;
}
.btn:hover {
-fx-background-color: -bg-secondary;
-fx-border-color: -border-color-dark;
}
.btn:armed {
-fx-background-color: -bg-tertiary;
-fx-scale-x: 0.98;
-fx-scale-y: 0.98;
}
/* Button Variants */
.btn-primary {
-fx-background-color: -primary-color;
-fx-text-fill: white;
-fx-border-color: -primary-color;
}
.btn-primary:hover {
-fx-background-color: -primary-dark;
-fx-border-color: -primary-dark;
}
.btn-secondary {
-fx-background-color: -secondary-color;
-fx-text-fill: white;
-fx-border-color: -secondary-color;
}
.btn-success {
-fx-background-color: -success-color;
-fx-text-fill: white;
-fx-border-color: -success-color;
}
.btn-warning {
-fx-background-color: -warning-color;
-fx-text-fill: white;
-fx-border-color: -warning-color;
}
.btn-error {
-fx-background-color: -error-color;
-fx-text-fill: white;
-fx-border-color: -error-color;
}
/* Button Sizes */
.btn-sm {
-fx-padding: -spacing-xs -spacing-sm;
-fx-font-size: -font-size-xs;
}
.btn-lg {
-fx-padding: -spacing-md -spacing-lg;
-fx-font-size: -font-size-md;
}
/* Form Controls */
.text-field, .password-field, .text-area {
-fx-background-color: -bg-primary;
-fx-border-color: -border-color;
-fx-border-width: 1px;
-fx-border-radius: -radius-md;
-fx-background-radius: -radius-md;
-fx-padding: -spacing-sm;
-fx-font-size: -font-size-sm;
-fx-transition: all -transition-fast;
}
.text-field:focused, .password-field:focused, .text-area:focused {
-fx-border-color: -primary-color;
-fx-border-width: 2px;
-fx-effect: -shadow-sm;
}
/* Cards */
.card {
-fx-background-color: -bg-primary;
-fx-background-radius: -radius-lg;
-fx-border-radius: -radius-lg;
-fx-effect: -shadow-sm;
-fx-padding: -spacing-lg;
}
.card:hover {
-fx-effect: -shadow-md;
}
/* Alerts */
.alert {
-fx-background-color: -bg-primary;
-fx-background-radius: -radius-md;
-fx-border-radius: -radius-md;
-fx-padding: -spacing-md;
-fx-border-width: 1px;
-fx-border-color: -border-color;
}
.alert-success {
-fx-border-color: -success-color;
-fx-background-color: derive(-success-color, 90%);
}
.alert-warning {
-fx-border-color: -warning-color;
-fx-background-color: derive(-warning-color, 90%);
}
.alert-error {
-fx-border-color: -error-color;
-fx-background-color: derive(-error-color, 90%);
}
.alert-info {
-fx-border-color: -info-color;
-fx-background-color: derive(-info-color, 90%);
}
/* ===== UTILITY CLASSES ===== */
/* Spacing Utilities */
.p-0 { -fx-padding: 0; }
.p-1 { -fx-padding: -spacing-xs; }
.p-2 { -fx-padding: -spacing-sm; }
.p-3 { -fx-padding: -spacing-md; }
.p-4 { -fx-padding: -spacing-lg; }
.p-5 { -fx-padding: -spacing-xl; }
.m-0 { -fx-margin: 0; }
.m-1 { -fx-margin: -spacing-xs; }
.m-2 { -fx-margin: -spacing-sm; }
.m-3 { -fx-margin: -spacing-md; }
.m-4 { -fx-margin: -spacing-lg; }
.m-5 { -fx-margin: -spacing-xl; }
/* Text Utilities */
.text-xs { -fx-font-size: -font-size-xs; }
.text-sm { -fx-font-size: -font-size-sm; }
.text-md { -fx-font-size: -font-size-md; }
.text-lg { -fx-font-size: -font-size-lg; }
.text-xl { -fx-font-size: -font-size-xl; }
.text-light { -fx-font-weight: -font-weight-light; }
.text-normal { -fx-font-weight: -font-weight-normal; }
.text-medium { -fx-font-weight: -font-weight-medium; }
.text-semibold { -fx-font-weight: -font-weight-semibold; }
.text-bold { -fx-font-weight: -font-weight-bold; }
.text-primary { -fx-text-fill: -text-primary; }
.text-secondary { -fx-text-fill: -text-secondary; }
.text-muted { -fx-text-fill: -text-muted; }
.text-left { -fx-text-alignment: left; }
.text-center { -fx-text-alignment: center; }
.text-right { -fx-text-alignment: right; }
/* Background Utilities */
.bg-primary { -fx-background-color: -bg-primary; }
.bg-secondary { -fx-background-color: -bg-secondary; }
.bg-tertiary { -fx-background-color: -bg-tertiary; }
.bg-success { -fx-background-color: -success-color; }
.bg-warning { -fx-background-color: -warning-color; }
.bg-error { -fx-background-color: -error-color; }
.bg-info { -fx-background-color: -info-color; }
/* Border Utilities */
.border { -fx-border-width: 1px; -fx-border-color: -border-color; }
.border-0 { -fx-border-width: 0; }
.border-2 { -fx-border-width: 2px; }
.border-4 { -fx-border-width: 4px; }
.border-primary { -fx-border-color: -primary-color; }
.border-success { -fx-border-color: -success-color; }
.border-warning { -fx-border-color: -warning-color; }
.border-error { -fx-border-color: -error-color; }
.rounded-sm { -fx-background-radius: -radius-sm; -fx-border-radius: -radius-sm; }
.rounded-md { -fx-background-radius: -radius-md; -fx-border-radius: -radius-md; }
.rounded-lg { -fx-background-radius: -radius-lg; -fx-border-radius: -radius-lg; }
.rounded-full { -fx-background-radius: -radius-circle; -fx-border-radius: -radius-circle; }
/* Shadow Utilities */
.shadow-sm { -fx-effect: -shadow-sm; }
.shadow-md { -fx-effect: -shadow-md; }
.shadow-lg { -fx-effect: -shadow-lg; }
.shadow-xl { -fx-effect: -shadow-xl; }
.shadow-none { -fx-effect: null; }
/* Display Utilities */
.d-block { -fx-visibility: visible; }
.d-none { -fx-visibility: hidden; }
.d-inline { /* JavaFX doesn't have inline display */ }
/* Opacity Utilities */
.opacity-0 { -fx-opacity: 0; }
.opacity-25 { -fx-opacity: 0.25; }
.opacity-50 { -fx-opacity: 0.5; }
.opacity-75 { -fx-opacity: 0.75; }
.opacity-100 { -fx-opacity: 1; }
/* ===== RESPONSIVE DESIGN ===== */
/* Note: JavaFX doesn't have media queries like web CSS */
/* Responsive behavior must be handled programmatically */
/* ===== DARK THEME ===== */
.root:dark {
-bg-primary: #1a1a1a;
-bg-secondary: #2d2d2d;
-bg-tertiary: #3d3d3d;
-text-primary: #ffffff;
-text-secondary: #b3b3b3;
-text-muted: #666666;
-border-color: #404040;
-border-color-light: #4d4d4d;
-border-color-dark: #333333;
}
/* ===== ACCESSIBILITY ===== */
/* High contrast support */
.root:high-contrast {
-primary-color: #0000ff;
-text-primary: #000000;
-border-color: #000000;
}
/* Focus indicators for keyboard navigation */
*:focus-visible {
-fx-border-color: -primary-color;
-fx-border-width: 2px;
-fx-border-radius: -radius-sm;
}
/* ===== PRINT STYLES ===== */
/* Note: JavaFX doesn't have print media queries */
/* Print-specific styles would need programmatic handling */

Conclusion

JavaFX CSS provides a powerful and flexible way to style your Java applications. Key takeaways:

  1. Use CSS variables for maintainable and consistent theming
  2. Follow a structured approach with base styles, components, and utilities
  3. Leverage JavaFX-specific properties for advanced styling
  4. Implement responsive design patterns programmatically
  5. Use animations and transitions to enhance user experience
  6. Follow accessibility best practices for inclusive design
  7. Organize your CSS files logically for better maintainability
  8. Test across different platforms to ensure consistency

By following these patterns and best practices, you can create beautiful, maintainable, and user-friendly JavaFX applications with professional-grade styling.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper