Styling with CSS
Styling with CSS
JavaFX has a first-class CSS engine built directly into the scene graph. Every node in the scene carries a style class, can hold inline -fx- properties, and participates in a cascade almost identical to browser CSS. The result is a clean separation between your application logic and its visual presentation — the same principle web developers apply every day, but targeting a desktop scene graph instead of a browser DOM.
How JavaFX CSS Works
When the JavaFX runtime lays out a scene it also runs a CSS pass. It loads stylesheets in order — the default Modena theme first, then any application stylesheets, then inline style attributes — and resolves the final set of visual properties for every node. All CSS properties in JavaFX are prefixed with -fx- to avoid clashing with standard CSS properties.
Adding a Stylesheet to a Scene
Call getStylesheets().add() on any Scene or Parent. Use getClass().getResource() to resolve the path relative to your class — that makes the app work whether it is run from an IDE, a JAR, or a module path.
You can also scope a stylesheet to a subtree by adding it to a Parent node (like a VBox or AnchorPane). Styles added there apply only to that node and its descendants.
Selectors: Class, ID, and Type
JavaFX CSS supports three selector types mapped to JavaFX concepts:
- Type selector — matches a JavaFX control class.
.button { }targets allButtonnodes. The selector name follows the JavaFX CSS convention (lowercase with hyphens). - Style-class selector (
.name) — matches nodes that have that style class in theirgetStyleClass()list. This is the main tool for semantic grouping. - ID selector (
#name) — matches the single node whoseidproperty equals the string. Use sparingly; IDs should be unique per scene.
In Java code you add and remove style classes at runtime, just as you would toggle CSS classes in JavaScript:
Pseudo-Classes: Hover, Focused, and Disabled
JavaFX automatically applies pseudo-classes to nodes based on their state. You style them the same way as in web CSS, using the : colon syntax:
PseudoClass.getPseudoClass("error") and node.pseudoClassStateChanged(errorClass, true) to apply :error { } CSS from your validation logic — no style-class toggling needed.
Common -fx- Properties
The most frequently used CSS properties in JavaFX applications:
-fx-background-color— solid colour, gradient, or layered paint list.-fx-text-fill— text colour for labels and buttons.-fx-font-family,-fx-font-size,-fx-font-weight— typography.-fx-padding— insets (top right bottom left, same shorthand as CSS).-fx-background-radius/-fx-border-radius— rounded corners.-fx-border-color,-fx-border-width— border decoration.-fx-effect— drop shadows, blurs, inner-glow.-fx-cursor— cursor shape (hand, crosshair, wait, etc.).
Theming: Light and Dark Modes
A clean theming strategy uses CSS variables (looked-up colours in JavaFX terminology). Define named colours at the root level and reference them everywhere else. Switching the root overrides the entire theme instantly.
To toggle the theme at runtime, swap the stylesheet:
Inline Styles and Programmatic Styling
For one-off overrides you can set an inline style directly on a node. Inline styles always beat external stylesheets in the cascade — use them only for truly dynamic values (colours computed at runtime, sizes derived from data).
setStyle() for values that are genuinely dynamic. For everything else, use style classes and swap them programmatically.
Custom Pseudo-Classes: Practical Example
Suppose you have a TextField that should show a red border when validation fails. Define a custom pseudo-class and wire it to your validation logic:
Now your controller calls emailField.setError(true) and the CSS engine does the rest — no inline style juggling, no style-class removal races.
Summary
JavaFX CSS gives you full control over the visual layer without touching Java code. Use external stylesheets loaded via getStylesheets(), target nodes with type, style-class, and ID selectors, leverage pseudo-classes for interactive states, and build themes around looked-up colour variables. Keep inline styles exceptional. This clean separation makes your UI maintainable, testable, and easy to hand off to a designer.