Bevy Flair brings CSS-like styling to Bevy UI, letting you define appearance and layout using familiar CSS syntax.
It enables you to style UI components, taking advantage of the power of CSS.
-
Apply CSS assets directly to Bevy UI elements.
-
Inherited stylesheets. Specify a
NodeStyleSheet
on a root node and all children inherit it automatically. -
Property inheritance support (e.g.
color
,font-family
). -
Font loading with
@font-face
. -
Animated property changes via
transition
. -
Custom animations with
@keyframes
. -
Hot-reloading: edit your
.css
file and see styles re-applied on the fly.- This is one of the main advantages over specifying the styles directly in code.
-
Broad support for existing Bevy UI components and properties:
- All
Node
properties are supported. - Components
BorderColor
,BackgroundColor
,BorderRadius
,Outline
,BoxShadow
,UiTransform
andZIndex
are supported, and inserted automatically when the corresponding property is used (e.g. usingbackground-color: red
will automatically insert theBackgroundColor
component ) - Support for parsing gradients, like
linear-gradient()
,radial-gradient()
orconic-gradient()
.
- All
-
Shorthand properties like
border
,grid
,margin
, etc.- Shorthand properties parse into individual properties, like
margin
becomesmargin-left
,margin-right
, etc. - Transitions and animations are supported for shorthand properties as well.
- Shorthand properties parse into individual properties, like
-
Non-standard CSS extensions for
ImageNode
- Example:
background-image: url("panel-border-030.png")
,-bevy-image-mode: sliced(20.0px)
.
- Example:
-
Color parsing. (e.g.
red
,#ff0000
,rgb(255 0 0)
,hsl(0 100% 50% / 50%)
,oklch(40.1% 0.123 21.57)
) -
Common CSS selectors and combinators (via selectors crate):
-
Attribute selectors (via
AttributeList
). -
Nested selectors: e.g.
&:hover { ... }
. -
Importing other stylesheets with
@import
. -
Custom properties with
var()
(Fallback is currently not supported). -
Basic
calc()
expressions (mainly useful with variables).- This is currently limited by Bevy support of mixing different
Val
types. This wouldn't work:calc(100% - 20px)
. - Is valuable only to do calculations using vars. For example:
calc(var(--spacing) * 2)
.
- This is currently limited by Bevy support of mixing different
-
@media
queries (prefers-color-scheme
,width
,height
,resolution
,aspect-ratio
). -
@layer
support. -
Inline CSS properties.
-
Pseudo-elements
::before
and::after
(enabled withPseudoElementsSupport
). -
Different stylesheets per subtree. With the use of a different
NodeStyleSheet
per subtree. It's even possible to not apply any style for a given subtree. -
Use of custom times for transitions and animations (See https://github.com/eckz/bevy_flair/blob/main/examples/animations.rs).
-
Supports for custom properties. (Example TBA).
-
Supports for custom parsing. (See https://github.com/eckz/bevy_flair/blob/main/examples/custom_parsing.rs)
- Only one stylesheet per entity (workaround: by using
@import
). - No global stylesheets.
- No real support for
!important
.- Currently,
!important
is detected but ignored with a warning.
- Currently,
- Limited font support: only single fonts via
@font-face
. No local or fallback fonts. - No advanced color functions like
color-mix()
or relative color syntax (e.g.lch(from blue calc(l + 20) c h)
). - No individual animation or transition properties like
animation-name
,transition-duration
, etc.
Example styled entirely with CSS:
game-menu.mov
-
Add
bevy_flair
to yourCargo.toml
. -
Create your UI structure and attach
NodeStyleSheet
the root:
main.rs
:
use bevy::prelude::*;
use bevy_flair::prelude::*;
fn main() {
App::new()
.add_plugins((DefaultPlugins, FlairPlugin))
.add_systems(Startup, setup)
.run();
}
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2d);
commands.spawn((
Node::default(),
NodeStyleSheet::new(asset_server.load("my_stylesheet.css")),
children![(Button, children![Text::new("Button")])],
));
}
Save your css file under assets/my_stylesheet.css
:
:root {
display: flex;
width: 100%;
height: 100%;
align-items: center;
justify-content: center;
/* font-size and color are inherited */
font-size: 35px;
color: rgb(30% 30% 30%);
}
button {
display: flex;
align-items: center;
justify-content: center;
width: 150px;
height: 65px;
background-color: rgb(15%, 15%, 15%);
border-radius: 10px;
transition: background-color 0.5s;
&:hover {
color: #ddd;
background-color: rgb(30%, 30%, 25%);
}
&:active {
color: #ddd;
background-color: rgb(35%, 65%, 35%);
}
text {
/* Color transitions need to happen in the text element */
transition: color 0.5s;
}
}
Another good place to start are the examples in the examples folder.
- Full CSS-based styling for Bevy UI.
- Efficient and reactive when applying styles.
- No unnecessary style re-application if the UI tree hasn’t changed.
- When modifications are detected in the UI tree, just the minimum affected nodes should get their style reapplied.
- Strict CSS validation and reporting:
- Invalid or unknown properties are reported, not ignored.
- Errors in one rule don’t block others.
- No panics from malformed CSS.
- Css that would make your application panic should be rejected and reported.
- If any correctly parsed css can cause a panics in bevy, it should be treated as a bug.
- Dictating how Bevy UI elements are spawned
- If you want to use any fancy macro to spawn your bevy UI elements, or if you want to do it in a manual way, it should not matter, it should work the same way.
- Once bsn! macro gets implemented, this crate should keep working as before.
- Define a default style.
- By default, if a property is not defined, such property will not be modified. This means that is up to the author to set up fallback styling if it's needed.
- There is support for
initial
values, which uses the component's default value.
- Supporting every CSS feature / property.
- CSS is a vast specification, so there are plenty of features that might not make sense to support.
- Strict CSS spec compliance (some deviations for practical reasons).
- CSS is a standard and such it defines certain behaviours very well, for example, current implementation of
animation
ortransition
is quite possible not 100% consistent with the standard.
- CSS is a standard and such it defines certain behaviours very well, for example, current implementation of
- Implementing missing Bevy UI features (e.g. unsupported units like
em
, or properties liketext-decoration
).
bevy | bevy_flair |
---|---|
0.17 | 0.5 |
0.16 | 0.2, 0.3, 0.4 |
0.15 | 0.1 |
Contributions are welcome! Feel free to fork the repository and submit a pull request.
This project is licensed under the MIT License. See the LICENSE file for more details.
The assets included in this repository (for our examples) fall under different open licenses.
- Poppins font. Designed by Indian Type Foundry, Jonny Pinhorn, Ninad Kale (https://fonts.google.com/specimen/Poppins) (SIL Open Font License, Version 1.1: assets/fonts/OFL.txt)
- Kenney Space Font from Kenney Fonts (CC0 1.0 Universal)
- UI borders from Kenny's Fantasy UI Borders Kit (CC0 1.0 Universal)