Rust GUI frameworks
2020 Framework 2026: Most downloaded native-rendering toolkit
12

egui: immediate mode wins hearts

Immediate mode made Rust GUIs feel easy.

egui is immediate mode: each frame you call functions that both describe and handle the UI. There is no widget tree to keep in sync with your state. ui.button("Click me") draws the button and, in the same call, tells you whether it was clicked. For tools, debuggers and game overlays that is hard to beat.

egui-app/src/bin/one.rs ✔ compiled · eframe 0.36 · rustc 1.95.0
use book_error::Result;
use eframe::egui;

#[derive(Default)]
struct MyApp {
    name: String,
    clicks: u32,
}

impl eframe::App for MyApp {
    // Immediate mode: this runs every frame and *describes* the UI.
    // There is no widget tree to keep in sync with your state.
    fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
        ui.text_edit_singleline(&mut self.name);
        if ui.button("Click me").clicked() {
            self.clicks += 1;
        }
        ui.label(format!("{} clicked {} times", self.name, self.clicks));
    }
}

fn main() -> Result<()> {
    eframe::run_native(
        "egui demo",
        eframe::NativeOptions::default(),
        Box::new(|_cc| Ok(Box::<MyApp>::default())),
    )?;
    Ok(())
}

What makes egui portable is that it knows nothing about windows or GPUs. It turns your UI into shapes, and a separate integration renders them. The snippet below runs one frame with no window at all and hands back triangle meshes plus texture updates.

egui-app/src/bin/two.rs ✔ compiled · eframe 0.36 · rustc 1.95.0
use eframe::egui;

// egui itself knows nothing about windows or GPUs. It turns your UI into
// shapes and hands them to whatever integration is driving it.
fn main() {
    let ctx = egui::Context::default();
    let mut output = ctx.run_ui(egui::RawInput::default(), |ui| {
        ui.label("hello, headless egui");
    });

    let meshes = ctx.tessellate(std::mem::take(&mut output.shapes), output.pixels_per_point);
    println!("{} meshes, {} texture updates", meshes.len(), output.textures_delta.set.len());

    // A real backend (egui-wgpu, glow) uploads these font/image textures to the GPU.
    output.textures_delta.clear();
}
output
1 meshes, 1 texture updates

The integrations are separate crates, and the lockfile shows them: egui-winit for input, egui-wgpu for drawing (with glow as an OpenGL option) and accesskit_winit for screen readers. egui itself depends on AccessKit directly. That layering is why egui runs in a browser, in Bevy and inside game engines. It is the most downloaded toolkit that draws its own pixels (25 million total downloads, 1,236 dependents), and it is still 0.36, not 1.0.

crates.io first publish.