# How the LibWeb Library Renders Web Content in Ladybird: A Technical Deep Dive

> Discover how LibWeb renders web content in Ladybird. This technical deep dive details its role in parsing HTML CSS layout and display list recording.

- Repository: [Ladybird/ladybird](https://github.com/LadybirdBrowser/ladybird)
- Tags: deep-dive
- Published: 2026-03-05

---

**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`](https://github.com/LadybirdBrowser/ladybird/blob/main/Libraries/LibWeb/HTML/HTMLTokenizer.h) and [`Libraries/LibWeb/HTML/HTMLParser.cpp`](https://github.com/LadybirdBrowser/ladybird/blob/main/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`](https://github.com/LadybirdBrowser/ladybird/blob/main/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`](https://github.com/LadybirdBrowser/ladybird/blob/main/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`](https://github.com/LadybirdBrowser/ladybird/blob/main/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`](https://github.com/LadybirdBrowser/ladybird/blob/main/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`](https://github.com/LadybirdBrowser/ladybird/blob/main/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`](https://github.com/LadybirdBrowser/ladybird/blob/main/Libraries/LibWeb/Painting/ViewportPaintable.h)) serves as the root paintable owning the entire page canvas.
- **`TextPaintable`** ([`Libraries/LibWeb/Painting/TextPaintable.h`](https://github.com/LadybirdBrowser/ladybird/blob/main/Libraries/LibWeb/Painting/TextPaintable.h)) records glyph runs and text decorations.
- **`PaintableBox`** handles backgrounds, borders, and shadows.
- **`Painting::StackingContext`** ([`Libraries/LibWeb/Painting/StackingContext.h`](https://github.com/LadybirdBrowser/ladybird/blob/main/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`](https://github.com/LadybirdBrowser/ladybird/blob/main/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`](https://github.com/LadybirdBrowser/ladybird/blob/main/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:

```cpp
// 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`](https://github.com/LadybirdBrowser/ladybird/blob/main/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:

```cpp
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`](https://github.com/LadybirdBrowser/ladybird/blob/main/HTMLTokenizer.h)), **CSS style computation** ([`StyleComputer.h`](https://github.com/LadybirdBrowser/ladybird/blob/main/StyleComputer.h)), **box layout** ([`TreeBuilder.h`](https://github.com/LadybirdBrowser/ladybird/blob/main/TreeBuilder.h)), **display list recording** ([`DisplayListRecorder.h`](https://github.com/LadybirdBrowser/ladybird/blob/main/DisplayListRecorder.h)), and **bitmap rasterization** (`BackingStoreManager`).
- **Paintable objects** like `ViewportPaintable` and `TextPaintable` encapsulate rendering logic, while `StackingContext` manages 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`](https://github.com/LadybirdBrowser/ladybird/blob/main/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.