UI (User Interface) / Generic Font Families

Back to examples View in GitHub

This example demonstrates generic font families, which allow font faces to be selected using broadly defined categories (such as serif or monospace) without selecting a specific font family.

Each generic font family is first resolved to a concrete family name, which is then matched to a font in the internal font database. This example loads system installed fonts to populate the database.

This feature is most useful for non-game applications; most games instead choose to simply bundle their required fonts to ensure a unified visual look.

use bevy::{
    color::palettes::{
        css::{WHEAT, YELLOW},
        tailwind::ZINC_600,
    },
    prelude::*,
    text::FontCx,
};

fn main() {
    let mut app = App::new();
    app.add_plugins(DefaultPlugins).add_systems(Startup, setup);

    app.run();
}

const FONT_SIZE: FontSize = FontSize::Px(25.);

fn setup(mut commands: Commands, mut font_system: ResMut<FontCx>) {
    // UI camera
    commands.spawn(Camera2d);

    commands
        .spawn((Node {
            display: Display::Grid,
            grid_template_columns: vec![RepeatedGridTrack::fr(3, 1.)],
            margin: UiRect::AUTO,
            row_gap: px(25),
            column_gap: px(15),
            ..Default::default()
        },))
        .with_children(|builder| {
            builder.spawn((
                Node {
                    justify_self: JustifySelf::Center,
                    grid_column: GridPlacement::span(3),
                    margin: UiRect::bottom(px(15)),
                    ..default()
                },
                Text::new("Generic Font Families"),
                TextFont::from_font_size(FONT_SIZE),
                Underline,
            ));

            let outline = Outline {
                color: ZINC_600.into(),
                width: px(2.),
                offset: px(4.),
            };

            for (source, description) in [
                (FontSource::SansSerif, "generic sans serif font"),
                (FontSource::Serif, "generic serif font"),
                (FontSource::Fantasy, "generic fantasy font"),
                (FontSource::Cursive, "generic cursive font"),
                (FontSource::Monospace, "generic monospace font"),
            ] {
                builder.spawn((
                    Text::new(description),
                    TextFont::from(source.clone()).with_font_size(FONT_SIZE),
                    TextColor(WHEAT.into()),
                    TextLayout::justify(Justify::Center),
                    outline,
                ));

                builder.spawn((
                    Text::new(format!("FontSource::{source:?}")),
                    TextFont::from_font_size(FONT_SIZE),
                    TextColor(YELLOW.into()),
                    TextLayout::justify(Justify::Center),
                    outline,
                ));

                // Get the family name for the `FontSource` from `FontCx`.
                // `get_family` only returns `None` for `FontSource::Handle`.
                let family_name = font_system.get_family(&source).unwrap();
                builder.spawn((
                    Text::new(family_name),
                    TextFont::from_font_size(FONT_SIZE),
                    TextLayout::justify(Justify::Center),
                    outline,
                ));
            }
        });
}