In this tutorial, you’ll learn how to use CSS (Cascading Style Sheets) to customize the look and feel of your JavaFX application.
You can use CSS in JavaFX applications similar to how you use CSS in HTML. You should have a basic understanding of CSS to get the most out of this tutorial.
Following is the screen shot of the application that we’ll build in this tutorial -
Default CSS for JavaFX applications
The default css for all JavaFX applications is written in a file called modena.css
, which can be found in the JavaFX runtime jar file, jfxt.jar
, located in your Java installation folder. This css file defines the styles for the root node and the UI controls.
To view the contents of the default css, go to your JDK installation directory, then go to jre/lib/ext
folder, and extract the stylesheet from jfxt.jar
.
The file modena.css
is located under com/sun/javafx/scene/control/skin/modena
directory -
$ cd $JAVA_HOME/jre/lib/ext
$ sudo jar xf jfxrt.jar com/sun/javafx/scene/control/skin/modena/modena.css
$ vi com/sun/javafx/scene/control/skin/modena/modena.css
The default css is always applied to every JavaFX application. However, you can create one or more custom stylesheets of your own and add them to your application to override the default styles defined by JavaFX.
Creating the Project
Let’s create a demo project to learn how to style JavaFX applications. Fire up your favourite IDE and create a new Java project. Now, create the following files in src
folder under a package named javafx.example
-
- CSSDemoApplication.java - This is the main class of your JavaFX application.
- css_demo.fxml - This is the FXML source file where you define the user interface.
- demo.css - This is the CSS file in which you define the styles for ui elements.
The project’s directory structure looks like this -
javafx-css-demo-app
└── src
└── javafx
└── example
└── CSSDemoApplication.java
└── css_demo.fxml
└── demo.css
Creating the Main Application Class
For creating a new JavaFX application, you need to create a class, extend it from javafx.application.Application
and override it’s start()
method.
Checkout my JavaFX Beginners tutorial for learning more about a typical JavaFX application and it’s life cycle.
Let’s create the Main class for our JavaFX application. Open CSSDemoApplication.java
file and add the following code to it -
package javafx.example
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class CSSDemoApplication extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("css_demo.fxml"));
Scene scene = new Scene(root, 800, 500);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
In the start()
method, we load the FXML document, create a scene with the root node found from FXML and set the scene in primary stage.
Creating the layout of the application
Next step is to create the layout of your application in the FXML source file, css_demo.fxml
.
I’ll not go into the details of the FXML layout. Checkout my tutorial on How to design JavaFX layouts using FXML for learning more about FXML.
In this article we’ll be focusing on CSS. Just add the following XML to your css_demo.fxml
file -
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.image.Image?>
<BorderPane>
<top>
<BorderPane styleClass="header-section">
<left>
<Label id="header-text" text="Application Header"></Label>
</left>
<right>
<Button id="account" text="Account">
<graphic>
<ImageView fitHeight="24" fitWidth="24"
pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@javafx_account_example.png" />
</image>
</ImageView>
</graphic>
</Button>
</right>
</BorderPane>
</top>
<left>
<VBox styleClass="sidebar-section">
<children>
<Label text="Sidebar Item1"></Label>
<Label text="Sidebar Item2"></Label>
<Label text="Sidebar Item3"></Label>
<Label text="Sidebar Item4"></Label>
</children>
</VBox>
</left>
<center>
<VBox styleClass="content-section">
<children>
<Label id="content-header" text="Content header"></Label>
<Label id="content">
<text>
Lorem Ipsum is simply dummy text of the printing and
typesetting industry. Lorem Ipsum has been the industry's
standard dummy text ever since the 1500s, when an unknown
printer took a galley of type and scrambled it to make a
type specimen book. It has survived not only five centuries,
but also the leap into electronic typesetting, remaining
essentially unchanged. It was popularised in the 1960s with
the release of Letraset sheets containing Lorem Ipsum
passages, and more recently with desktop publishing software
like Aldus PageMaker including versions of Lorem Ipsum.
</text>
</Label>
</children>
</VBox>
</center>
<bottom>
<HBox id="footer-section">
<children>
<Label text="Copyright 2017 CalliCoder"></Label>
</children>
</HBox>
</bottom>
</BorderPane>
Note that, the above FXML also contains an image. Click here to download the image and save it in the same folder where your FXML file resides.
Creating and Adding stylesheets to the Application
If you run the application right now, it’ll look ugly! No, Seriously It’ll look ugly!
Let’s style the application by adding css. We’ll first add the CSS and run the application, and then learn how the styles specified in the css file relate to the UI elements.
Open demo.css
file and add the following css -
.root {
-fx-font-size: 14px;
-fx-font-family: sans-serif;
-fx-background-color: #ffffff;
}
.header-section {
-fx-padding: 10px;
-fx-font-size: 20px;
-fx-background-color: teal;
}
.header-section Label {
-fx-text-fill: #ffffff;
-fx-padding: 10px;
}
#account {
-fx-background-color: transparent;
-fx-text-fill: #ffffff;
-fx-font-size: 16px;
-fx-cursor: hand;
}
.sidebar-section {
-fx-min-width: 200px;
-fx-pref-width: 200px;
-fx-max-width: 200px;
-fx-border-width: 1;
-fx-border-color: transparent #E8E8E8 transparent transparent;
}
.sidebar-section Label {
-fx-font-size: 18px;
-fx-padding: 10 15 10 15;
-fx-border-width: 1;
-fx-border-color: transparent transparent #E8E8E8 transparent;
-fx-min-width: 200px;
-fx-pref-width: 200px;
-fx-max-width: 200px;
}
.content-section {
-fx-padding: 10 20 10 20;
-fx-wrap-text: true;
}
#content-header {
-fx-font-size: 18px;
-fx-padding: 0 0 10 0;
-fx-font-weight: 700;
}
#content {
-fx-wrap-text: true;
-fx-font-size: 16px;
}
#footer-section {
-fx-alignment: center;
-fx-padding: 10 10 10 10;
-fx-border-width: 1;
-fx-border-color: #E8E8E8 transparent transparent transparent;
}
Now that we have created the CSS file, let’s add the css to our application. There are two ways in which you can add a stylesheet to your JavaFX application -
1. Adding stylesheet through Java code
Use the code shown below to add the stylesheet, demo.css
to the JavaFX Scene
. Note that it looks for demo.css
file in the same directory in which the main application class resides.
scene.getStylesheets().add(getClass().getResource("demo.css").toExternalForm());
2. Adding stylesheet through FXML
Add a stylesheets
element before the end of the root layout element in your FXML. In our case, the root layout element is BorderPane
. Just add the following snippet before the closing </BorderPane>
element
<stylesheets>
<URL value="@demo.css" />
</stylesheets>
The @ symbol before the name of the css file in the URL indicates that the style sheet is in the same directory as the FXML file.
That’s it! You can now run the application, it’ll pick the styles from the css file and style the ui elements.
Understanding CSS concepts related to JavaFX
All the JavaFX CSS definitions contain a Selector and one or more JavaFX properties and their values. JavaFX property names are prefixed by -fx-. Property names and values are separated by colons (:), and multiple style declarations are separated by a semicolon.
Selectors
Selectors are used to identify the ui elements to which the style has to be applied. Each CSS style definition specifies a Selector and one or more styles separated by a semicolon. -
/* CSS selector and styles */
.header-section {
-fx-padding: 10px;
-fx-font-size: 20px;
-fx-background-color: teal;
}
Selectors “find” the JavaFX elements based on their element name, id or styleClass. Following are different types of Selectors -
Element Name Selectors -
Element Name Selectors select all elements in FXML with that name. For example, the selector,
Label
will select all labels in the FXML document.Label Button GridPane
Style Class Selectors -
Style class selectors are preceded by a dot (.). You can add one style class to multiple JavaFX elements. The styles defined for a class will be applied to all the elements that has the specified class.
You can add a styleClass to an element in FXML by using
styleClass
attribute.<!-- Adding style class in FXML --> <BorderPane styleClass="header-section">
Also, if you’ve created the ui element thorough java code, you can add the style class using -
node.getStyleClass().add("header-section")
Following are some examples of style class selectors -
.header-section
.sidebar-section
.content-section
*All the Element Name Selectors have an equivalent Style Class Selector. For Example - "Label" can also be selected as ".label", "Button" can also be selected as ".button" etc.*
ID Selectors -
You can also define styles by using a node’s id. ID selectors are preceded by # symbol. Unlike style classes, id is unique to an element.
A node’s id can be set using
id
attribute in FXML, and usingsetId()
method in java.Following are some examples of ID selectors -
#account #footer-section #content
Compound Selectors
You can also use compound selectors in your style definitions like the one below -
.header-section Label
The example above selects all the Label
elements that are descendant of elements with header-section
class.
Pseudo Selectors
JavaFX also supports selectors for pseudo-classes. For example -
.button:focused
.button:hover
Root Style class
The .root
style class is applied to the root node of the Scene instance. It’s similar to the body
element in html. Since all nodes in a scene are descendant of the root node, styles in the .root
class are applied to all the nodes. .root
class can be used to define default values for font-size, font-family etc. to provide consistency in the UI.
Conclusion
In this blog post, We learned how to create and add css to JavaFX applications and explored different css concepts through simple examples. You can find the code for the demo application that we built in this tutorial on my github repository.
For more information on this subject, see the Oracle JavaFX CSS Reference Guide. Thank you for reading. I hope you liked the post. Please ask any questions in the comment section below.