JavaFX Color Derivation

A very powerful and often underestimated feature of JavaFX is its CSS Color Derivation.
But let us start at the beginning by explaining two prerequisites:

  1. The Default JavaFX 8 Theme (Modena) only defines a few colors statically in its stylesheet. The rest is derived by JavaFX’s color functions (ladder and derive - see the CSS Reference) or referenced as color variables.
  2. If you start to apply a custom styles to a Node in the scenegraph, these styles will also be applied to all children of this Node (if applicable). So changing a color variable on a single node will change the corresponding colors, derived colors and referenced colors on all child nodes in the scenegraph, but not on any of its parent nodes.

If we combine both together we can create these three Buttons with ease (the first one is a regular one, just to show the default theme):
Java FX Color derivation example

But let’s start with the Java Code for our little example:

Test.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        Button red = new Button("red");
        red.getStyleClass().add("red");

        Button green = new Button("green");
        green.getStyleClass().add("green");

        Button regular = new Button("regular");

        BorderPane root = new BorderPane();
        root.setTop(new ToolBar(regular, red, green));
        Scene scene = new Scene(root, 400, 400);
        scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Essentially we create some buttons, stuff them into a ToolBar and it to the Scene. Additionally we assign some style classes in order to do the color magic later on.
Doing the old school way we would have ended up editing all of the buttons colors.

But if we take a closer look at the default button colors..

modena.css
1
2
3
4
.button {
    -fx-background-color: -fx-shadow-highlight-color, -fx-outer-border, -fx-inner-border, -fx-body-color;
    -fx-text-fill: -fx-text-base-color;
}

..you may see the colors are referenced, and as you may guess they are derived of the aforementioned base colors.
For example look at the border color, defined in the root of the modena theme:

modena.css
1
2
3
.root {
  -fx-outer-border: derive(-fx-color, -23%);
}

So to put all of this together, we only need these simple rules in our CSS file:

application.css
1
2
3
4
5
6
.red {
  -fx-base: red;
}
.green {
  -fx-base: green;
}

What happens is that we changed the base color on each of the buttons. Now JavaFX is clever enough to detect that with a different base color, the derived colors for each of the buttons (and its children) need an update.

Wait there’s more

Now this was a very basic example, but to give you another example we can switch the base color of the root container to create our own “dark theme”:

application.css
1
2
3
.root {
  -fx-base: darkgray;
}

This will result in this darker version of our sample application:
Java FX Color derivation example
Using derived colors throughout your application will make your life a lot easier!

Comments