Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How do I correctly use variables in JavaFX CSS Stylesheets?

I am building a small password manager using JavaFX and currently working on make it easy to change the color theme. For that, I declared variables containing the hexcodes of different colors and saved’em in a stylesheet called "utility.css". This stylesheet is imported in two different stylesheets and the variables are called as described here.

Somehow I get this error while parsing:

Feb. 21, 2023 5:32:48 PM javafx.css.CssParser parse
WARNING: CSS Error parsing file:/G:/.../Coding/.../target/classes/css/utility.css: Expected RBRACE at [3,4]
Feb. 21, 2023 5:32:48 PM javafx.css.CssParser term
WARNING: CSS Error parsing file:/G:/.../Coding/.../target/classes/css/login-menu.css: Unexpected token '-' at [4,30]
Feb. 21, 2023 5:32:48 PM javafx.css.CssParser term
WARNING: CSS Error parsing file:/G:/.../Coding/.../target/classes/css/login-menu.css: Unexpected token '-' at [4,30]
Feb. 21, 2023 5:32:48 PM javafx.css.CssParser reportException
WARNING: Please report java.lang.NullPointerException at:
    javafx.graphics@19/javafx.css.CssParser.term(CssParser.java:4689)
    javafx.graphics@19/javafx.css.CssParser.expr(CssParser.java:4583)
    javafx.graphics@19/javafx.css.CssParser.declaration(CssParser.java:4554)
    javafx.graphics@19/javafx.css.CssParser.declarations(CssParser.java:4472)
    javafx.graphics@19/javafx.css.CssParser.parse(CssParser.java:3981)
    javafx.graphics@19/javafx.css.CssParser.parse(CssParser.java:253)
    javafx.graphics@19/javafx.css.CssParser.parse(CssParser.java:241)

I already asked chatGPT but seems there are things, AI can’t help us with (yet) 😀

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

This is the code of the "utility.css"-file, where I declared the variables

:root {
    --maincolor: #2b284d;
    --backgrounddark: #2b284d;
    --backgroundlight: #5a4f7d;
    --panel: #3c325c;
    --panelhighlighted: #503d6b;
    --panelselected: #503d6f;
    --casualbutton: #2b284d;
    --casualbuttonhighlighted: #5d5478;
    --crucialbuttonhightled: #eb5b0e;
    --textfield: #2b288d;
    --textfill: #b5b5b5;
}

and this of the two stylesheets:

@import "utility.css";

.combo-box .list-cell:filled:selected {
    -fx-background-color: var(--panelhighlighted);
    -fx-text-fill: #b5b5b5 ;
    -fx-font-family: "Calibri Light" ;
    -fx-font-size: 17;
    -fx-background-radius: 20px;
}

.combo-box .combo-box-popup .list-view, .combo-box .combo-box-popup .list-cell {
    -fx-background-color: var(--panel);
    -fx-text-fill: var(--textfill) ;
    -fx-font-family: "Calibri Light" ;
    -fx-font-size: 17;
    -fx-background-radius: 20px;
}

.combo-box .combo-box-popup .list-cell:hover {
    -fx-text-fill:  var(--textfill);
    -fx-background-color: var(--panelhighlighted);
}

.password-field {
    -fx-text-fill: #b5b5b5 ;
    -fx-prompt-text-fill: #b5b5b5 ;
}

.anchor-pane {
    overflow:hidden;
    -fx-background-color: #2b284d;
}

and

@import "utility.css";

.list-cell:filled:selected:focused, .list-cell:filled:selected {
    -fx-background-color: var(--panelselected);
}

.list-cell:filled:hover {
    -fx-background-color: var(--panelhighlighted);
}

.list-cell {
    -fx-background-color: var(--panel);
    -fx-pref-height: 60;
    -fx-background-radius: 20px;
    -fx-background-insets: 0;
    -fx-text-fill: var(--textfill) ;
    -fx-font-family: "Calibri Light" ;
    -fx-font-size: 20;
    -fx-alignment: center-left;
}

.list-view {
    -fx-background-color: var(--backgrounddark);
    -fx-border-color: var(--backgrounddark);
    -fx-background-insets: 0;
    -fx-padding: 0px;
}

.password-field {
    -fx-text-fill: var(--textfill) ;
    -fx-prompt-text-fill: var(--textfill) ;
    -fx-background-radius: 20px;
    -fx-background-color: var(--textfield);
}

.label {
    -fx-text-fill: var(--textfill);
    -fx-background-color: var(--textfield);
}

So I tried to eliminate ‘-‘ in the variable names, because these are used in css as the start of a command or sth but this didn’t work out.
I also tried an online css debugging tool, which only said I should switch the import statement with something called link to improve performance, which is not important for me atm.

I have absolutely no idea, what’s the problem here. I am using IntelliJ 2022.3.1 (Ultimate Edition).
The error happens at runtime, before that, IntelliJ doesn’t complain at all and even auto-completes my variable names in the stylesheets, so they are definitely there and definitely correct.

The error appears to happen, when the css parser reaches the firtst ‘-‘ in the first stylesheet that calls a variable, as if this may not happen there.

>Solution :

Glancing quickly at the CSS Specification, it looks like a valid identifier can only have a single hyphen at the start:

Macro     Definition
ident     [-]?{nmstart}{nmchar}*
name      {nmchar}+
nmstart   [_a-z]|{nonascii}|{escape}

The : in a selector signifies a pseudoclass, which I don’t think is what you want here. If you want the looked-up colors to be applied to the root pane and inherited by everything in the application, use the class selector for the root (.root).

I did a quick test with all the looked-up color names renamed to a start with a single hyphen, and changed the selector to select the root:

.root {
    -maincolor: #2b284d;
    -backgrounddark: #2b284d;
    -backgroundlight: #5a4f7d;
    -panel: #3c325c;
    -panelhighlighted: #503d6b;
    -panelselected: #503d6f;
    -casualbutton: #2b284d;
    -casualbuttonhighlighted: #5d5478;
    -crucialbuttonhightled: #eb5b0e;
    -textfield: #2b288d;
    -textfill: #b5b5b5;
}

Note that CSS naming conventions recommend separating words with hyphens, so your looked-up color names should probably be something like -main-color, etc. You might also consider putting a vendor prefix on them to avoid name collisions.

There is no need for var(...) in the CSS referencing a looked-up color. Just reference these directly. See the JavaFX CSS documentation.

I tested this with a CSS stylesheet style.css as follows:

@import "utility.css";
.label {
    -fx-background-color: -backgrounddark;
}

and ran it with IntelliJ’s "default" JavaFX template (which I included below), and it worked as expected with no errors.

HelloApplication.java:

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class HelloApplication extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
        Scene scene = new Scene(fxmlLoader.load(), 320, 240);
        scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm());
        stage.setTitle("Hello!");
        stage.setScene(scene);
        stage.show();
    }

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

HelloController.java:

import javafx.fxml.FXML;
import javafx.scene.control.Label;

public class HelloController {
    @FXML
    private Label welcomeText;

    @FXML
    protected void onHelloButtonClick() {
        welcomeText.setText("Welcome to JavaFX Application!");
    }
}

and hello-view.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>

<?import javafx.scene.control.Button?>
<VBox alignment="CENTER" spacing="20.0" xmlns:fx="http://javafx.com/fxml"
      fx:controller="org.jamesd.examples.csstest.HelloController">
    <padding>
        <Insets bottom="20.0" left="20.0" right="20.0" top="20.0"/>
    </padding>

    <Label fx:id="welcomeText"/>
    <Button text="Hello!" onAction="#onHelloButtonClick"/>
</VBox>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading