Skip to content

Theming

Kevin edited this page Jun 16, 2026 · 3 revisions

CSS Basics

Since the widget toolkit is Gtk+ theming is done with CSS.

Warning

GTK is not the web
While most features are implemented in GTK, you can't assume anything that works on the web will work with GTK.
Refer to the GTK docs to see what is available.

So far every widget you made used your default GTK theme. To make them more custom, you can apply stylesheets to them.

From file at startup

You can pass a path to a file or css as a string in App:start

init.lua
local inline_css = [[
    window {
        background-color: transparent;
    }
]]

App:start {
    css = inline_css,
    css = '/path/to/style.css',
    css = './style.css',
}

Warning

When using relative paths, for example ./style.css keep in mind that they will be relative to the current working directory.

Css Property on Widgets

Widget.Label {
    label = 'hello',
    css = 'color: blue; padding: 1em; background-color: red;',
    css = {
        color = 'blue',
        padding = '1em',
        background_color = 'red',
    },
}

Note

The css property of a widget will not cascade to its children.

Apply Stylesheets at Runtime

You can apply additional styles at runtime.

App:apply_css('/path/to/file.css')
App:apply_css([[
    window {
        background-color: transparent;
    }
]])
App:reset_css() -- reset if need

Warning

App:apply_css will apply on top of other stylesheets applied before.
You can reset stylesheets with App:reset_css or by passing true as a second parameter to App:apply_css.

Inspector

If you are not sure about the widget hierarchy or any CSS selector, you can use the GTK inspector

You can also open it by pressing Ctrl + Shift + I.

# to bring up the inspector run
astal-lua request --inspector
# or set the environment variable
GTK_DEBUG=interactive lua app.lua

Using SCSS

Gtk's CSS only supports a subset of what the web offers. Most notably nested selectors are unsupported by Gtk, but this can be workaround by using preprocessors like SCSS.

init.lua
local scss = './style.scss'
local css = '/tmp/style.css'

astal.exec(string.format('sass %s %s', scss, css))

App:start {
    css = css,
}

This snippet compiles your SCSS to CSS and automatically applies it to the Gtk app, using the async api

local astal = require('astal')
local App = require('astal.gtk4.app')
local async_exec, monitor_file = require('astal.process').async_exec, require('astal.file').monitor_file

local HOME = os.getenv('HOME')
local CONFIG = HOME .. '/.config/astal'
local CACHE = HOME .. '/.cache/astal'

local styles = CONFIG .. '/styles.scss'
local styles_dir = CONFIG .. '/scss'
local styles_cache = CACHE .. '/styles.css'

return async(function()
    local compile = function()
        local _, stderr = async_exec { 'sass', styles, styles_cache }
        if stderr then
            io.stdout:write(stderr .. '\n')
            return false
        end
        io.stdout:write(string.format('%s -> %s\n', styles, styles_cache))
        return true
    end

    local apply = function()
        if compile() then App:apply_css(styles_cache, true) end
    end

    local watch = function(path, recursive)
        monitor_file(path, recursive, function(_, event)
            if event == 'CHANGES_DONE_HINT' then apply() end
        end)
    end

    watch(styles)
    watch(styles_dir, true)
    apply()
end)

Clone this wiki locally