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.
Styled] on a root node and all children inherit it automatically.color, font-family).@font-face].transition].@keyframes]..css file and see styles re-applied on the fly. Node] properties are supported.BorderColor], [BackgroundColor], [BorderRadius], [Outline], [BoxShadow], [UiTransform] and [ZIndex]
are supported, and inserted automatically when the corresponding property is used (e.g. using background-color: red will automatically insert the [BackgroundColor] component )linear-gradient()], [radial-gradient()] or [conic-gradient()].border], [grid], margin, etc.margin becomes margin-left, margin-right, etc.ImageNode] background-image: url("panel-border-030.png"), -bevy-image-mode: sliced(20.0px), -bevy-image-rect: 0 0 64 64.red,#ff0000,rgb(255 0 0),hsl(0 100% 50% / 50%),oklch(40.1% 0.123 21.57)):root, #id (using [Name]), .class (using [ClassList]), type selectors (via [TypeName]), :hover, :active, :focus, :nth-child, :first-child.ul li), child (ul > li), sibling (img + p, img ~ p).:not(), :has(), :is(), :where().
Attribute selectors (via [AttributeList]).
&:hover { ... }.@import.var()] (Fallback is currently not supported).calc()] expressions (mainly useful with variables).Val types. This wouldn't work: calc(100% - 20px).calc(var(--spacing) * 2).@media] queries (prefers-color-scheme, width, height, resolution, aspect-ratio).@layer] support.::before and ::after (enabled with [PseudoElementsSupport]).Styled] per subtree. It's even possible to not apply any style for a given subtree.Time for transitions and animations (See https://github.com/eckz/bevy_flair/blob/main/examples/custom_time.rs).GhostNode] in the hierarchy. Ghost nodes are simply ignored.ghost_nodes feature for better support of Ghost nodes.@import).!important.!important is detected but ignored with a warning.@font-face. No local or fallback fonts.color-mix() or relative color syntax (e.g. lch(from blue calc(l + 20) c h)).Example styled entirely with CSS:
https://github.com/user-attachments/assets/792b9cfa-42fb-4e50-a85f-8d21aafeb1e5
Add bevy_flair to your Cargo.toml.
Create your UI structure and attach Styled the root:
main.rs:
```rust, no_run 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) { commands.spawn(Camera2d); commands.spawn(( Node::default(), Styled::new(asset_server.load("my_stylesheet.css")), children![(Button, children![Text::new("Button")])], )); }
Save your css file under `assets/my_stylesheet.css`:
```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.
initial values, which uses the component's default value.animation or transition is quite possible not 100% consistent with the standard.em, or properties like [text-decoration]).| bevy | bevy_flair |
|---|---|
| 0.19 | 0.8 |
| 0.18 | 0.7 |
| 0.17 | 0.5, 0.6 |
| 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.
$ claude mcp add bevy_flair \
-- python -m otcore.mcp_server <graph>