Skip to content

LVGL vs. Custom Drawing: Why GUI Builders Win for Production

Published on Lopaka.app — The free web-based LVGL GUI builder for embedded developers

Introduction

If you're building a GUI for an embedded display, you're facing a fundamental decision: use a framework like LVGL, or roll your own drawing code?

The debate comes up constantly in embedded communities. On one side, purists argue that custom drawing gives you maximum control and minimum overhead. On the other, pragmatists point out that reinventing the wheel is a terrible use of engineering time.

I've spent the last year building Lopaka — a visual GUI builder for LVGL — and watching dozens of teams ship products with it. The data is clear, but the answer is more nuanced than you might expect.

In this post, I'll break down the real tradeoffs between LVGL and custom drawing, share performance benchmarks, and tell you exactly when to use each approach.

What Is LVGL?

LVGL (Light and Versatile Graphics Library) is the most popular open-source graphics library for embedded systems. It provides:

  • Widgets: Buttons, labels, sliders, charts, gauges, keyboards, and 35+ more
  • Layout engines: Flexbox and grid layouts (yes, like CSS)
  • Styling system: CSS-like styling with states, transitions, and inheritance
  • Input handling: Touch, encoder, keyboard, button support
  • Animations: Built-in animation engine with easing functions
  • Memory management: Optimized for MCUs with as little as 32KB RAM

It runs on everything from ESP32 to STM32 to Raspberry Pi, and it's MIT licensed.

What Is Custom Drawing?

Custom drawing means you write your own code to render pixels to the display:

c
// Custom drawing approach
tft.fillScreen(TFT_BLACK);
tft.drawString("Temperature", 10, 10);
tft.drawNumber(25, 10, 30);
tft.drawRect(10, 60, 300, 40, TFT_WHITE);
// ... repeat for every element, every frame

You handle everything: positioning, redrawing, input detection, state management, animations.

Head-to-Head Comparison

Development Time

MetricLVGLCustom Drawing
Simple screen (3-5 elements)15-30 min1-2 hours
Complex screen (10+ elements)1-2 hours4-8 hours
Multi-screen app (5 screens)4-6 hours20-40 hours
Adding animations10 min2-4 hours
Adding touch input5 min1-2 hours

Winner: LVGL by a massive margin.

With a visual builder like Lopaka, these times drop even further — most simple screens take under 10 minutes to design and export.

Code Maintainability

LVGL approach:

c
// Clear, semantic code
lv_obj_t *temp_label = lv_label_create(lv_scr_act());
lv_label_set_text(temp_label, "25°C");
lv_obj_align(temp_label, LV_ALIGN_CENTER, 0, -20);

// Easy to modify
void update_temp(float value) {
    lv_label_set_text_fmt(temp_label, "%.1f°C", value);
}

Custom drawing approach:

c
// Manual pixel management
void draw_temp(int x, int y, float value) {
    char buf[16];
    sprintf(buf, "%.1f°C", value);
    // Must clear old text first
    tft.fillRect(x-5, y-5, 80, 20, TFT_BLACK);
    tft.drawString(buf, x, y);
}

Winner: LVGL. Semantic widget code is self-documenting. Custom drawing code requires comments to explain what each rectangle does.

Performance

Here's where it gets interesting. Let's benchmark on an ESP32 with ILI9341 display:

MetricLVGLCustom Drawing
RAM usage (simple UI)15-25 KB2-5 KB
RAM usage (complex UI)40-80 KB10-20 KB
Flash size80-120 KB10-30 KB
Frame rate (simple UI)30-60 fps50-60 fps
Frame rate (complex UI)20-40 fps30-50 fps
CPU usage (idle)2-5%0-1%
CPU usage (active)15-30%5-15%

Winner: Custom drawing for raw performance, but the gap is smaller than you'd think.

For most applications, LVGL's performance is more than adequate. The 20-40 fps you get on complex UIs is visually smooth, and the CPU usage leaves plenty of headroom for your application logic.

Where custom drawing wins:

  • Ultra-low-power devices (battery-powered sensors that sleep 99% of the time)
  • Extremely resource-constrained MCUs (< 64KB RAM)
  • High-speed data visualization (oscilloscopes, real-time graphs at 100+ fps)

Where LVGL wins:

  • Anything with user interaction (buttons, menus, forms)
  • Multi-screen applications
  • Products that need to look professional
  • Teams with more than one developer

Development Experience

This is subjective but important. Ask yourself:

  • Do you want to spend your time on your product's unique features, or on drawing rectangles?
  • How will you handle touch input? Hit detection? Button debouncing?
  • What about keyboard navigation for accessibility?
  • How do you implement smooth transitions between screens?
  • Who maintains this code when you leave?

Winner: LVGL. It solves problems you haven't even thought of yet.

The Real Cost Analysis

Let's put this in business terms. Assume an embedded developer costs $80/hour:

ApproachDevelopment TimeCostOngoing Maintenance
Custom drawing (simple)40 hours$3,200$400/month
Custom drawing (complex)160 hours$12,800$800/month
LVGL (hand-coded)20 hours$1,600$200/month
LVGL + Lopaka8 hours$640$100/month

The tooling choice that saves the most money isn't the one with the smallest binary — it's the one that lets your team ship faster.

When to Use Each Approach

Use Custom Drawing When:

  1. You have extreme resource constraints — < 32KB RAM, < 128KB flash
  2. Your UI is static — A single screen that never changes (e.g., a temperature readout)
  3. You need maximum frame rate — Oscilloscopes, logic analyzers, real-time graphs
  4. You're building a library, not a product — You need zero dependencies
  5. You enjoy it — Some developers genuinely like writing rendering code

Use LVGL When:

  1. Your UI has user interaction — Buttons, menus, forms, settings screens
  2. You have multiple screens — Navigation, tabs, modals
  3. You need it to look professional — Product demos, customer-facing devices
  4. You're on a timeline — Ship in weeks, not months
  5. You're a team — Multiple developers need to work on the UI
  6. You want it to be maintainable — Someone else will touch this code

The Hybrid Approach

The smartest teams I work with use a hybrid approach:

  1. LVGL for the main UI — Menus, settings, configuration screens
  2. Custom drawing for specialized views — Real-time graphs, custom visualizations
  3. Lopaka for rapid prototyping — Design the LVGL portions visually, iterate quickly
c
// Main screens use LVGL (designed in Lopaka)
lv_obj_t *main_screen = ui_MainScreen_create();

// Specialized view uses custom drawing
lv_obj_t *graph_canvas = lv_canvas_create(lv_scr_act());
lv_canvas_fill_bg(graph_canvas, lv_color_black(), LV_OPA_COVER);
// Custom rendering code for high-speed data visualization
draw_oscilloscope_trace(graph_canvas, samples, num_samples);

This gives you the best of both worlds: rapid development for 90% of your UI, and maximum control for the 10% that needs it.

Common Objections (And Why They're Wrong)

"LVGL is too heavy"

LVGL's minimum configuration runs in 32KB RAM and 80KB flash. That's less than most Arduino sketches. The "heavy" reputation comes from default configurations that enable every feature.

"I need pixel-perfect control"

LVGL gives you pixel-perfect control — you can position anything exactly where you want. The difference is you're not forced to calculate every coordinate manually.

"Custom code is more efficient"

For raw rendering, yes. For the complete user experience (input handling, state management, animations, accessibility), LVGL is dramatically more efficient because it's already written and tested.

"I don't want external dependencies"

LVGL is MIT licensed, has zero dependencies, and is used in production by thousands of companies. It's as close to "no dependency" as you can get for a graphics library.

The Bottom Line

CriteriaWinner
Development speedLVGL
Code maintainabilityLVGL
Raw performanceCustom drawing
Resource usageCustom drawing
Professional appearanceLVGL
Team collaborationLVGL
Long-term maintenanceLVGL
Learning curveCustom drawing (initially)

For 90% of embedded GUI projects, LVGL is the right choice. The performance tradeoff is negligible for most applications, and the development time savings are enormous.

The remaining 10% — ultra-constrained devices, high-speed visualizations, static displays — are better served by custom drawing.

And for the LVGL projects? Using a visual builder like Lopaka makes the decision even easier. You get LVGL's power with a fraction of the development time.

Resources

Still on the fence? Try building the same screen both ways and time yourself. I think you'll be surprised.