Skip to content
This repository has been archived by the owner on Sep 28, 2024. It is now read-only.

Type Safe CSS

Edvin Syse edited this page Apr 22, 2016 · 49 revisions

WikiDocumentationType Safe CSS

Type Safe CSS

TornadoFX has a type safe DSL for generating CSS, including type safe selector declarations. Using it is optional, you can always write your stylesheets manually, but you'll find there are many advantages to using the DSL. A couple of them are discoverability and getting the syntax right the first time. Others are support for mixins and the ability to generate CSS with code, even based on for example state or configuration in your app.

Defining a style sheet

class MyStyles : Stylesheet() {
    companion object {
        // Define our styles
        val box by cssclass()
        val bob by cssclass()
        val alice by cssclass()

        // Define our colors
        val dangerColor = c("#a94442")
        val hoverColor = c("#d49942")
    }

    init {
        s(box) {
            padding = box(10.px)
            spacing = 10.px
        }

        s(label) {
            fontSize = 56.px
            padding = box(5.px, 10.px)
            maxWidth = infinity

            +s(bob, alice) {
                borderColor = box(dangerColor)
                borderStyle = BorderStrokeStyle(StrokeType.INSIDE, StrokeLineJoin.MITER, StrokeLineCap.BUTT, 10.0, 0.0, listOf(25.0, 5.0))
                borderWidth = box(5.px)

                +s(hover) {
                    backgroundColor = hoverColor
                }
            }
        }
    }
}

Importing the stylesheet

To use a particular stylesheet, import it in the init block of your app class:

class MyApp : App() {
    override val primaryView = MyView::class

    init {
        importStylesheet(MyStyles::class)
    }
}

Applying style classes to components

You can choose to use the type safe selectors shown above, or use strings, both for defining selectors and adding classes to nodes. It is a best pratice to use type safe selectors everywhere, so that you can track where/if your css is defined and applied.

Describe addClass, hasClass, toggleClass both with strings and CSSClasses.

Default style classes

The Stylesheet class defines constants for all pseudo classes and node classes used in all the default JavaFX components, to there is no need to define classes like hover, label, button and listView.

You can also define #id with the cssid delegate and ':pseudoclasseswith thecsspseudoclass` delegate.

Defining colors

Remember to explain that colors should be defined in the companion object of your stylesheet, so you can change them in one place instead of littering color declarations in the stylesheet itself. Eg. val dangerColor = c("#a94442").

Dimensions

Some sort of explanation that all measurements are type safe as well using units. (There is support for linear units (px, %, mm, pt, em, infinity, etc.), angular units (deg, rad, grad, and turn), and temporal units (s, ms)).

Box

Mixins

Modifier selections (+s)

Special support for SingleViewApp

For small/demo applications, you can define and apply a stylesheet directly inside the app class:

class CssDemo : SingleViewApp("CSS Demo") {
    override val root = VBox()

    companion object {
        val box by cssclass()
        val alice by cssclass()
        val bob by cssclass()
    }

    init {
        with(root) {
            addClass(box)

            label("Alice") {
                addClass(alice)
            }
            label("Bob") {
                addClass(bob)
            }
        }
        css {
            s(box) {
                padding = box(10.px)
                spacing = 10.px
            }

            s(label) {
                fontSize = 56.px
                padding = box(5.px, 10.px)
                maxWidth = infinity

                +s(bob, alice) {
                    borderColor = box(Color.ORANGE)
                    borderStyle = BorderStrokeStyle(StrokeType.INSIDE, StrokeLineJoin.MITER, StrokeLineCap.BUTT, 10.0, 0.0, listOf(25.0, 5.0))
                    borderWidth = box(5.px)
                }
            }
        }
    }
}

The application will look like this:

The CSS can be printed using println(stylesheet) and looks like this:

.box {
    -fx-padding: 10px 10px 10px 10px;
    -fx-spacing: 10px;
}
.label {
    -fx-font-size: 56px;
    -fx-padding: 5px 10px 5px 10px;
    -fx-max-width: infinity;
}
.label.bob, .label.alice {
    -fx-border-color: rgba(255, 165, 0, 1) rgba(255, 165, 0, 1) rgba(255, 165, 0, 1) rgba(255, 165, 0, 1);
    -fx-border-style: segments(25.0 5.0) inside line-join miter 10.0 line-cap butt;
    -fx-border-width: 5px 5px 5px 5px;
}

Next: Async Task Execution

Clone this wiki locally