Skip to content
CMO & CTO
CMO & CTO

Closing the Bridge Between Marketing and Technology, By Luis Fernandez

  • Digital Experience
    • Experience Strategy
    • Experience-Driven Commerce
    • Multi-Channel Experience
    • Personalization & Targeting
    • SEO & Performance
    • User Journey & Behavior
  • Marketing Technologies
    • Analytics & Measurement
    • Content Management Systems
    • Customer Data Platforms
    • Digital Asset Management
    • Marketing Automation
    • MarTech Stack & Strategy
    • Technology Buying & ROI
  • Software Engineering
    • Software Engineering
    • Software Architecture
    • General Software
    • Development Practices
    • Productivity & Workflow
    • Code
    • Engineering Management
    • Business of Software
    • Code
    • Digital Transformation
    • Systems Thinking
    • Technical Implementation
  • About
CMO & CTO

Closing the Bridge Between Marketing and Technology, By Luis Fernandez

Styling JavaFX: A Practical Look at CSS on the JVM

Posted on August 20, 2009 By Luis Fernandez

“Good design is as little design as possible. The same goes for code style. Put style where style belongs.”

Why JavaFX CSS on the JVM matters right now

Java folks have wanted painless styling for years. Swing gets the job done but dressing it up often means more code than color. With JavaFX CSS we finally get a way to style UI on the JVM without wiring every pixel by hand. It is not a clone of browser CSS and that is fine. The scene graph is a different beast. But we get selectors, classes, and a tidy bucket for fonts, colors, and borders. Which is a big win for teams that want code on one side and design on the other.

There is a lot of chatter right now about Sun Microsystems and the Oracle deal. People wonder what this means for JavaFX. I am still shipping apps and I like what I see in the current bits. The plugin is smooth on modern browsers, the runtime does not feel heavy, and CSS support is already useful for real apps. That is where I am placing my bets today. Ship small, keep style outside of logic, and let the JVM carry the load.

A small story from a tiny app

I built a compact media browser last week to test out JavaFX controls. The first draft had colors sprinkled inside event handlers and constructors. Classic mess. I moved those bits into a stylesheet and the code breathed. Designers could tweak shades and fonts without touching a single timeline or listener. I stopped bouncing between editor tabs just to change a highlight.

It also made theming painless. I made a dark sheet and a light sheet. Swapping one line in the scene switched the mood of the whole thing. No hunt for magic numbers. No fear of repaint oddities. The scene graph just picked up the new rules.

Deep dive 1: Selectors, classes, and attaching stylesheets

JavaFX CSS is about mapping rules to nodes in the scene. You get type selectors like Button, classes with a dot, and ids with a hash. Properties line up with node features. The names are JavaFX style, not browser style. Think fontSize and textFill, not web names. Here is a tiny set you can paste into a file named app.css.

/* app.css */
Button {
    fontSize: 14;
    fontWeight: bold;
    textFill: white;
    backgroundColor: #3a6ea5;
    borderColor: #274b72;
    borderWidth: 1;
    padding: 6 10 6 10;
}

.primary {
    backgroundColor: #2e8b57;
}

.warn {
    backgroundColor: #c44536;
}

#saveButton {
    borderColor: #1e5a3d;
}

Then wire it in your stage. The code below keeps style where it belongs and lets you tag nodes with styleClass and id.

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;

var saveBtn = Button {
    text: "Save"
    id: "saveButton"
    styleClass: "primary"
}

var deleteBtn = Button {
    text: "Delete"
    styleClass: "warn"
}

Stage {
    title: "Styling JavaFX"
    scene: Scene {
        stylesheets: ["app.css"]
        content: HBox {
            spacing: 10
            content: [ saveBtn, deleteBtn ]
        }
    }
}

Type selectors give you a base look for all controls of that type. Classes let you theme roles like primary or warn. Ids let you tweak that one button your product manager keeps pointing at in screenshots. Keep the number of ids small. Classes scale better.

Deep dive 2: Skinning controls without fights

Controls ship with skins. You can go far just with CSS, yet some states still need a touch of script. The trick is to use classes for states you care about, then toggle them from events. This keeps rule sets in the sheet and leaves behavior in code.

/* in app.css */
.over {
    backgroundColor: #3f7ab8;
}

.pressed {
    backgroundColor: #305e8c;
}
// toggle state classes from code
saveBtn.onMouseEntered = function(e) {
    saveBtn.styleClass = "primary over";
}

saveBtn.onMouseExited = function(e) {
    saveBtn.styleClass = "primary";
}

saveBtn.onMousePressed = function(e) {
    saveBtn.styleClass = "primary pressed";
}

saveBtn.onMouseReleased = function(e) {
    saveBtn.styleClass = "primary";
}

For text and icons, CSS can set fontSize and textFill. If you want a glow or a drop shadow, wire an Effect in code and keep the colors in the sheet. This keeps the heavy work in the runtime and the tweaks in one file.

/* app.css */
.glowText {
    textFill: #f0f6ff;
    fontSize: 18;
}

/* code */
import javafx.scene.effect.DropShadow;

var title = javafx.scene.text.Text {
    text: "JavaFX CSS"
    styleClass: "glowText"
    effect: DropShadow {
        radius: 6
        color: javafx.scene.paint.Color.web("#274b72")
    }
}

One more tip. Separate role classes from layout. Let layout containers handle spacing and alignment. Use CSS for paint and type. Mixing both in the sheet turns small apps into guesswork mode.

Deep dive 3: Performance and gotchas on the scene graph

Style recalculates when you add nodes, change classes, or swap sheets. Keep selectors simple. Type and class selectors are fast and clear. Deep chains with many ancestors slow you down and are hard to read. The JVM is fast, yet you still pay for work you do not need.

Batch changes. If you switch a bunch of classes during a transition, group them between layout passes. Do not flip styleClass back and forth inside tight loops. Keep your sheets small. Two sheets are fine. Ten sheets that all overlap will confuse future you.

Pick your battles with effects. Blurs and shadows look great and cost real time. Use them on titles or focus hints. Skip them on every cell in a big list. For icons, prefer images or vector shapes rather than painting everything by hand on each pulse.

Mobile is part of the JavaFX story. Smaller screens, smaller batteries. On those targets, plain colors and simple borders beat heavy gradients and thick shadows. CSS makes that easy. Keep a lean sheet for handheld and a richer sheet for desktop or browser apps.

What makes this stick

The big idea is simple. Put the style of your app in a stylesheet. Put the behavior in code. Use JavaFX CSS for paint, type, spacing, and state looks. Use the scene graph for structure and flow. Make classes for roles, not for pixels. Name them like you name code. primary, warn, muted, toolbar. That language lives longer than a hex value.

This is not about chasing a trend. It is about maintainable apps that ship. With JavaFX you get a friendly sheet format on top of a fast runtime and a mature JVM. Sun set the stage and the community is already trading tips and snippets. No one knows every twist of the Oracle story yet. What we do have is a clear path for styling apps today. That is enough to build with confidence.

So open a small project. Pull colors and fonts into a sheet. Tag your nodes with classes that mean something. Keep selectors tidy. When the next feature arrives and you need a new theme for that client demo, you will thank past you. Your code will read clean. Your UI will look sharp. And your users will never know how easy it was to get there.

Software Architecture Software Engineering

Post navigation

Previous post
Next post
  • Digital Experience (94)
    • Experience Strategy (19)
    • Experience-Driven Commerce (5)
    • Multi-Channel Experience (9)
    • Personalization & Targeting (21)
    • SEO & Performance (10)
  • Marketing Technologies (92)
    • Analytics & Measurement (14)
    • Content Management Systems (45)
    • Customer Data Platforms (4)
    • Digital Asset Management (8)
    • Marketing Automation (6)
    • MarTech Stack & Strategy (10)
    • Technology Buying & ROI (3)
  • Software Engineering (310)
    • Business of Software (20)
    • Code (30)
    • Development Practices (52)
    • Digital Transformation (21)
    • Engineering Management (25)
    • General Software (82)
    • Productivity & Workflow (30)
    • Software Architecture (85)
    • Technical Implementation (23)
  • 2025 (12)
  • 2024 (8)
  • 2023 (18)
  • 2022 (13)
  • 2021 (3)
  • 2020 (8)
  • 2019 (8)
  • 2018 (23)
  • 2017 (17)
  • 2016 (40)
  • 2015 (37)
  • 2014 (25)
  • 2013 (28)
  • 2012 (24)
  • 2011 (30)
  • 2010 (42)
  • 2009 (25)
  • 2008 (13)
  • 2007 (33)
  • 2006 (26)

Ab Testing Adobe Adobe Analytics Adobe Target AEM agile-methodologies Analytics architecture-patterns CDP CMS coding-practices content-marketing Content Supply Chain Conversion Optimization Core Web Vitals customer-education Customer Data Platform Customer Experience Customer Journey DAM Data Layer Data Unification documentation DXP Individualization java Martech metrics mobile-development Mobile First Multichannel Omnichannel Personalization product-strategy project-management Responsive Design Search Engine Optimization Segmentation seo spring Targeting Tracking user-experience User Journey web-development

©2025 CMO & CTO | WordPress Theme by SuperbThemes