CSS Tutorial
CSS Tutorial
Introduction
Cascading Style Sheets, or CSS, is a styling language for describing and setting the layout
for markup languages. Most commonly, it is used to set the styling and format of HTML and
XHTML in websites, but it can be used with any type of XML document, including FXML.
The above code is an example of the CSS layout style for setting the properties of an
object. This code will set the text colour, background colour and padding (inner spacing)
for all buttons. Additionally, for only the ‘ok’ button, the font is set to bold. As the name
implies, CSS properties are cascading, meaning that in the markup hierarchy, objects will
inherit the properties of their parent, unless it is otherwise stated.
This tutorial will introduce the basics of CSS, along with its use with JavaFX and
FXML/Scene Builder 2. Following this, a small example of styling the tutorial GUI is given.
It is important to remember that CSS cannot change the content or structure of your FXML
file, it can only affect the appearance – CSS is not a scripting language.
Selectors
There are two main types of identifiers when using CSS: classes and ids. The former is
used when you want to give a series of objects the same properties, such as giving all
buttons the same colouring style, or setting the font for a particular type of label. The ID
2 CSS Tutorial
is used to define the properties for a single object where you want to identify that specific
item in your FXML document.
The format for accessing classes in CSS is to precede its name with a full-stop “.”, e.g.
.button will be used to set the properties for all items with the class “button”. Similarly,
the properties of individual items can be changed using the “#” symbol, appending it to
the ID, e.g. #ok will allow you to change the properties of an object with id “ok”.
Note that there may be multiple objects of different classes with the same ID, such as a
label and a text-field both named “firstname”. You can distinguish between these by using
the class identifier, which forms a ‘parent’ of each object:
.label#firstname{
/* styling for label named firstname */
}
.text-field#firstname{
/* styling for text-field named firstname */
}
The above code shows the chaining of classes and ids to be more specific in your styling.
This is also the case with style cascading, where an element will inherit features of its
‘parents’ in the XML layout. The following snippet of code demonstrates an example FXML
layout. While this has been simplified greatly, it is similar in idea to the tutorial example:
a Pane containing a SplitPane, which contains a left and a right AnchorPane. These
contain labels and a text-field: the left contains two labels; the right contains one label
and one text-field.
<Pane>
<children>
<SplitPane>
<items>
<AnchorPane id=”left”>
<children>
<Label text=”First Label” id=”label-italics” \>
<Label text=”Second Label” id=”label-bold” \>
</children>
</AnchorPane>
<AnchorPane id=”right”>
<children>
<Label text=”Third Label” \>
<TextField \>
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</Pane>
3 CSS Tutorial
The above example can be styled using the following example stylesheet. For now we
won’t actually show the styling code, but identify which objects will be affected by each
selector block.
.root {
/* Sets the default style for all items */
}
.anchor-pane {
/* Sets the default style for all items contained in an AnchorPane */
/* Overrides any previous properties of parent tags or root */
}
.anchor-pane#right {
/* Sets the style for the AnchorPane with id “right” (only) */
}
.anchor-pane .label {
/* Sets the style for any Labels that are children of an AnchorPane */
}
.label,
.text-field {
/* Sets the common properties of all Labels and TextField */
}
#left .label {
/* Sets the style for all child Labels of a tag with id “left” */
}
.label#label-italic {
/* Sets the style for a Label with id “label-italic” */
/* Note the lack of spacing between the class and id */
}
.anchor-pane #label-bold {
/* Sets the style for tag with the id “label-bold” in an AnchorPane */
/* The space means the id belongs to a child, not an AnchorPane */
}
.anchor-pane.label#label-bold {
/* An unambiguous equivalent of the above block: specifies the style
of a Label with id “label-bold” that is a child of an AnchorPane */
}
The above code outlines a few different ways of using CSS. There is versatility in the
cascading of styles, but often it can cause unintended effects if not checked properly. An
4 CSS Tutorial
example of this is the use of spacing between classes and ids. In the last three cases, you
can see the distinction between the .class#id and .class #id in that the first will look
for an object of that class with that id, where as the second will look for an object with
that id that is a child of the class.
It is also possible to set common properties of multiple classes without using the
cascading, but simply using the comma-separation of classes as the block selector: see
.label, .text-field which will set the style properties for all labels and all text-fields
regardless of their hierarchy.
Note that the Pane is the parent tag for all objects, so the properties set for it will
cascade down to all its children unless they are overridden. This is the same, then, for the
AnchorPane, and indeed the styling for the right AnchorPane (.anchor-pane#right).
The .root class is the parent for all objects, so any properties set in the .root selector
will be the global values unless overridden for specific classes.
Psuedo-classes are one additional type of selector. These are classes with an appended
state, which is used to distinguish the style between certain actions. Pseudo-classes are
appended to a selector with the colon operator ‘:’, e.g. .class:state. These allow you
to override certain style of a class based on certain actions, although the types of
interactions are quite limited. The most common state is “hover”, which will trigger when
the mouse is moved over it. Having a pseudo-class does not override the properties of the
main class, unless specified explicitly in the CSS file. Other general pseudo-states include
“pressed” and “focused”.
Declarations
Aside from selectors, declarations are needed to actually set the properties of your style.
These describe the various properties, from fonts and colours to borders and padding. In
JavaFX, all property declarations begin with “-fx-”. These are added to the selector
blocks and will set the properties of the elements that match up to this.
Declarations are made up of two parts: the property name and its value, separated by a
colon:
Each separate declaration must end with a semi-colon ‘;’. If the same declaration is
called multiple times in the same selector block, the last call is the one that is used.
Property values typically come in 3 types: the numeric value, e.g. for setting the size of
something; text value, e.g. font types or urls; and colours. Numeric value properties can
often have the units specified, such as when setting the size of a border you can specify
centimetres (cm), pixels (px), or points (pt). Note when setting font-size, this is normally
in pt, e.g. 11pt.
String values vary more on the property, for example, you can specify a border type as
‘solid’ or ‘dashed’, or the font-family, ‘Arial’ or ‘sans-serif’.
5 CSS Tutorial
Colour types are slightly different in that you can set the using a named colour (e.g. red),
using hexadecimal values (#F0AAAA), or even by specifying the red-green-blue values
(rgb(240, 170, 170)). A colour picker tool for getting the rgb or hex values is available
here, and a list of pre-named colours in JavaFX can be found here.
Some declarations allow a chain of properties that sets multiple properties in one line. For
example, the –fx-font property:
Note that for font-family, the given value is a string of three fonts. This effectively means
that the font will be Arial, unless it is not found in the font library of the system it is
running on, in which case it will be Helvetica. If neither of those is present, it defaults to
the system’s base sans-serif font.
To set the font colour, the declaration parameter name is ‘text-fill’, e.g.
–fx-text-fill: blue;
The above code is the CSS to style your GUI. To add this project, create a new File in your
‘view’ package (right-click ‘view’ > New > Other… > General > File). Name it
‘MyTheme.css’, and copy the above code into it.
There a multiple ways to assign a stylesheet to a Scene. The first way, we will assign it
within Scene Builder. Open RootLayout.fxml in Scene Builder, and select the
BorderPane. On the right hand side, again in ‘Properties’, click the ‘+’ under
‘Stylesheets’. Navigate to your ‘src/view’ folder and select ‘MyTheme.css’. Save and
refresh your project. Running the project now should style both the RootLayout and the
embedded PersonView.fxml due to the nature of the FXML hierarchy.
However, if you click either the New… or Edit… buttons, the new window is NOT styled by
your CSS file. This is because it belongs to a separate Scene. The next step is an example
of how to assign a stylesheet programmatically to a window.
For the PersonEdit window, you can assign the stylesheet in Scene Builder, as with the
RootLayout, or add the following line of code to your showPersonEdit() method after
the new Scene is created:
Useful Links
Oracle JavaFX 8 CSS Reference:
http://docs.oracle.com/javase/8/javafx/api/javafx/scene/doc-files/cssref.html