javajavafxjavafx-css

Does JavaFX CSS support variables for numeric values?


I thought that JavaFX CSS didn't support variables for numeric values. But then I found this answer with 16 upvotes, so I created a simple test:

public class NewMain extends Application {

    @Override
    public void start(Stage primaryStage) {
        var button = new Button("Button");
        VBox root = new VBox(button);
        root.getStylesheets().add(NewMain.class.getResource("test.css").toExternalForm());
        Scene scene = new Scene(root, 100, 100);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

and CSS:

.root {
    LABEL_PADDING_TOP: 0;
    LABEL_PADDING_RIGHT: 0;
    LABEL_PADDING_BOTTOM: 0;
    LABEL_PADDING_LEFT: 5;
}

.button {
    -fx-padding: LABEL_PADDING_TOP LABEL_PADDING_RIGHT LABEL_PADDING_BOTTOM LABEL_PADDING_LEFT;
    -fx-background-color: green;
}

And this is what I have:

Feb 08, 2025 1:39:41 PM javafx.scene.CssStyleHelper calculateValue WARNING: Caught 'java.lang.ClassCastException: class java.lang.Double cannot be cast to class javafx.css.Size (java.lang.Double is in module java.base of loader 'bootstrap'; javafx.css.Size is in module javafx.graphics@19 of loader 'app')' while converting value for '-fx-padding' from rule '*.button' in stylesheet file:home/user/temp/test.css

As this feature is very important for me I would like to make it work, if it is possible.


Solution

  • Does JavaFX CSS support variables for numeric values?

    No.

    FAQ

    I found this answer with 16 upvotes

    That would indicate that variable substitution for numeric values used to work in the past for older JavaFX versions. However, such a feature was never publicly documented so it would have been unsupported and I guess unmaintained, as your tests with recent JavaFX versions show that it does not work.

    References

    The current references for JavaFX CSS are:

    Neither of those mention or use variables for numeric values.

    How to use variables with JavaFX CSS

    Pre-process the CSS in Java or using an external tool.

    You could use a SASS pre-processor to generate the CSS to be used. SASS supports variables.

    Or you could generate the CSS dynamically using Java code. That is best done with a templating library (e.g. you could use something like freemarker or named placeholders). Templating was due to be added to the JDK in JEP465: String Templates, but the proposal was withdrawn as the previews had issues that needed to be resolved using a different approach. It will likely be added to some future Java release. Given that future string templating could be added to the Java language itself and that can process CSS, it doesn't seem worthwhile to me to add a generic variable type feature to the JavaFX CSS processor.

    Here is an example of generating CSS in code. The example is just for illustrative purposes, it is not meant to be performative (use a templating library if worried about performance).

    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.layout.VBox;
    import javafx.stage.Stage;
    
    public class VariableCssApp extends Application {
    
        private static final String CSS_DATA_URL_TYPE = "data:text/css,";
        private static final String CSS = CSS_DATA_URL_TYPE +
                """
                .button {
                    -fx-padding: LABEL_PADDING_TOP LABEL_PADDING_RIGHT LABEL_PADDING_BOTTOM LABEL_PADDING_LEFT;
                    -fx-background-color: palegreen;
                }
                """
                        .replace("LABEL_PADDING_TOP", "10")
                        .replace("LABEL_PADDING_RIGHT", "20")
                        .replace("LABEL_PADDING_BOTTOM", "30")
                        .replace("LABEL_PADDING_LEFT", "40");
    
        public static void main(String[] args) {
            launch(args);
        }
    
        @Override
        public void start(Stage stage) {
            VBox root = new VBox(new Button("Button"));
            root.getStylesheets().add(CSS);
            Scene scene = new Scene(root, 100, 100);
            stage.setScene(scene);
            stage.show();
    
            System.out.println("Applied CSS:\n" + CSS);
        }
    }
    

    Variable-like things

    There are some things in JavaFX CSS that act a bit like variables, but are not exactly variables.

    looked-up colors

    JavaFX has the concept of looked-up colors, which function as constant values for color values from which other colors can be derived. That is very useful for theming.

    em values

    JavaFX lengths can be em values which will vary based on the font-size.

    Modena, advises their use like this:

    To make UI controls scale and be the right proportions for each of these font sizes we base the padding (which controls size of control) on the font size. This is done using the CSS measurement unit of a "em" where (1em = font size).

    Examples of scaling UIs based on font size: