How the LibWeb Library Renders Web Content in Ladybird: A Technical Deep Dive
LibWeb is the self-contained web engine at the heart of Ladybird that transforms raw HTML and CSS into a rasterized bitmap through parsing, style computation, layout tree generation, and display list recording.
The Ladybird browser relies entirely on LibWeb to handle the complete lifecycle of web content rendering. This native C++ library—originally developed for SerenityOS—implements the full stack of web standards, including HTML tokenization, CSS cascading, box model layout, and GPU-accelerated painting, without dependencies on external engines like Blink or WebKit.
The LibWeb Rendering Pipeline
LibWeb orchestrates six distinct phases to convert network data into visible pixels. Each phase is implemented in specific subdirectories of Libraries/LibWeb/ and operates on immutable data structures that flow from parsing to rasterization.
HTML Parsing and DOM Construction
The rendering process begins with the HTML tokenizer and parser defined in Libraries/LibWeb/HTML/HTMLTokenizer.h and Libraries/LibWeb/HTML/HTMLParser.cpp. These components consume raw HTTP response bytes and construct a DOM::Document tree.
The tokenizer converts character streams into HTML tokens (start tags, end tags, text, comments), while the parser applies the HTML5 insertion rules to build the DOM hierarchy. This tree represents the structural elements—html, body, div, text nodes—that will later carry computed styles and layout geometry.
CSS Processing and Style Computation
Once the DOM exists, LibWeb parses associated stylesheets using CSS::CSSParser (defined in Libraries/LibWeb/CSS/CSSParser.h). The parser produces a cascade of style rules that are matched against DOM nodes.
The CSS::StyleComputer (located in Libraries/LibWeb/CSS/StyleComputer.h) resolves these cascaded values into computed styles for each element. This includes resolving inherit, initial, and !important declarations, as well as calculating absolute lengths and color values. The resulting style map is attached directly to DOM nodes, providing the layout engine with definitive geometry instructions (width, height, margins, positioning schemes).
Layout Engine and Box Generation
With a fully styled DOM, the layout engine constructs a parallel layout tree hierarchy of Layout::Node objects. The entry point is Layout::TreeBuilder (in Libraries/LibWeb/Layout/TreeBuilder.h), which traverses the DOM and instantiates concrete box types such as Layout::BlockBox and Layout::InlineBox (defined in Libraries/LibWeb/Layout/Box.h).
During this phase, LibWeb resolves the CSS box model for every element. The engine calculates containing block widths, collapses vertical margins, establishes formatting contexts, and determines the exact position of every fragment. The output is a complete layout tree where each node knows its precise coordinates and dimensions in the viewport coordinate space.
Painting and Display List Generation
After layout stabilization, LibWeb generates a display list—a serialized sequence of drawing commands that describe the page contents without immediate rasterization. The Painting::DisplayListRecorder (in Libraries/LibWeb/Painting/DisplayListRecorder.h) traverses the layout tree and records paint commands into a Painting::DisplayList buffer.
Concrete paintable objects handle specific rendering primitives:
ViewportPaintable(Libraries/LibWeb/Painting/ViewportPaintable.h) serves as the root paintable owning the entire page canvas.TextPaintable(Libraries/LibWeb/Painting/TextPaintable.h) records glyph runs and text decorations.PaintableBoxhandles backgrounds, borders, and shadows.Painting::StackingContext(Libraries/LibWeb/Painting/StackingContext.h) assembles the final draw order, managing z-index layering, opacity groups, CSS transforms, and filter effects.
Rasterization and UI Integration
The display list is ultimately converted into a bitmap that the UI process can blit to the screen. Services/WebContent/PageClient.h creates a LibWeb::Painting::BackingStoreManager, which selects between Skia (for GPU-accelerated rasterization) or a software fallback rasterizer based on platform capabilities.
The resulting image is stored in a BackingStore and transmitted over IPC to the frontend. In the Qt-based master branch, UI/Qt/WebContentView.h implements QWidget::paintEvent to receive this bitmap and render it via QPainter. Input events flow in the reverse direction: WebContentView::enqueue_native_event translates Qt mouse and keyboard events into Web::MouseEvent and Web::KeyEvent objects that LibWeb processes for hit-testing and JavaScript event dispatch.
Practical Code Examples
Integrating LibWeb with the Qt UI
The following snippet demonstrates how Ladybird’s browser window initializes LibWeb and triggers the rendering pipeline:
// In UI/Qt/BrowserWindow.cpp (simplified)
auto* view = new Ladybird::WebContentView(this);
view->load(QUrl::fromUserInput("https://example.com"));
view->show();
When WebContentView::load executes (implemented in UI/Qt/WebContentView.cpp), it instantiates a WebView::WebContentClient and requests navigation. LibWeb then executes the full pipeline—parsing, layout, painting—to produce a bitmap that the widget’s paintEvent draws inside the Qt window.
Headless Rendering with LibWeb
LibWeb can render web content without any UI dependencies, enabling server-side rendering or automated testing:
RefPtr<Web::HTML::HTMLDocument> document = Web::HTML::Parser::parse(R"(
<html><body><h1>Hello, LibWeb!</h1></body></html>
)"_sv);
auto layout_root = Web::Layout::TreeBuilder::build(*document);
auto viewport = Web::Painting::ViewportPaintable::create(layout_root->viewport());
Web::Painting::DisplayListRecorder recorder;
viewport->paint(recorder, Web::Painting::PaintPhase::Foreground);
auto bitmap = recorder.finish(); // Gfx::Bitmap with the rendered page
This example executes the core LibWeb steps in isolation: HTML parsing via HTML::Parser::parse, layout tree construction via TreeBuilder::build, paintable object creation via ViewportPaintable::create, and final bitmap generation through the DisplayListRecorder.
Summary
- LibWeb is a monolithic, dependency-free implementation of web standards within the Ladybird repository, covering HTML, CSS, DOM, and graphics.
- The rendering pipeline flows through distinct phases: HTML tokenization (
HTMLTokenizer.h), CSS style computation (StyleComputer.h), box layout (TreeBuilder.h), display list recording (DisplayListRecorder.h), and bitmap rasterization (BackingStoreManager). - Paintable objects like
ViewportPaintableandTextPaintableencapsulate rendering logic, whileStackingContextmanages compositing and z-ordering. - The architecture cleanly separates the engine from the UI: LibWeb runs in a sandboxed process and delivers finished bitmaps to
WebContentView, which handles platform-specific display and input.
Frequently Asked Questions
What is LibWeb in the Ladybird browser?
LibWeb is Ladybird’s native web engine library that implements HTML parsing, CSS styling, layout calculation, and graphics rendering. Originally derived from SerenityOS, it provides a complete alternative to WebKit or Chromium’s Blink, allowing Ladybird to render modern web content using entirely independent code.
How does LibWeb handle CSS layout compared to other engines?
LibWeb implements the CSS box model and formatting contexts according to the W3C specifications, using a dedicated layout tree separate from the DOM. The Layout::TreeBuilder constructs boxes (BlockBox, InlineBox, etc.) and resolves geometry through the CSS::StyleComputer, similar in concept to Blink’s LayoutNG or Gecko’s Servo, but written in idiomatic C++ without legacy compatibility constraints.
Can LibWeb be used independently of the Ladybird UI?
Yes. LibWeb is designed as a reusable library within Libraries/LibWeb/ and can be linked into any C++ application. The headless rendering example demonstrates producing a Gfx::Bitmap without Qt or any UI framework, making LibWeb suitable for server-side rendering, automated testing, or embedding into custom browser interfaces.
Does LibWeb support GPU acceleration for web content?
Yes. According to the source in Services/WebContent/PageClient.h, LibWeb’s BackingStoreManager can utilize Skia for GPU-accelerated rasterization when available, falling back to a software rasterizer on unsupported platforms. This allows the painting phase to leverage hardware acceleration for complex CSS transforms, opacity layers, and large viewport bitmaps.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →