Ladybird Newsletter

Subscribe
Archives
October 2, 2025

This Month in Ladybird: September 2025

September wrapped up with 207 merged PRs from 40 contributors. Let’s take a look at some highlights:

Welcoming new sponsors

Ladybird is entirely funded by the generous support of companies and individuals who believe in the open web. This month, we're excited to welcome the following new sponsors:

  • Cloudflare with $100,000 (their announcement)
  • K15t with $5,000
  • Unkey with $5,000

We're incredibly grateful for their support. If you're interested in sponsoring the project, please contact us.

Web Platform Tests (WPT)

Progress on WPT continues. This month we squeezed out 13,405 new passes for a total of 1,853,367.

For context, here are the current top 6 browser engines and their WPT scores today vs one month ago.

newsletter-sep-2025-wpt.gif

HTTP caching enabled by default

An HTTP cache has been in the works for a while, but until now it was hidden behind a flag. This month we enabled it by default, making repeated navigations much faster. (PR #6119)

CSS custom property handling

Ladybird has supported CSS custom properties (also known as "variables") for a while, but there were lots of little gaps. This month we fixed !important handling (PR #6329), exposed them in CSSStyleProperties (PR #5989), ensured the correct order is preserved (PR #6226), and added them to the properties list in dev tools (PR #6311).

DevTools improvements

We also fixed some issues where layout information would not be displayed (PR #6312), and where the style sheets list would sometimes not appear (PR #6315).

CSS Typed OM API

Carrying on from last month, we now implement the various CSSStyleValue classes for transform functions, which is finally enough for most of the WPT tests to run instead of crashing immediately. There's still a lot to do, but it's been nice to finally see some results! (PRs #6162, #6176, and #6227)

View transitions

View transitions are a way of animating between page states (for example, from a product list to the details for one product), or even between different pages. This month, a lot of the underlying machinery for this has been implemented (PR #5155). It's going to take a bit longer before it's usable, but it's a good start to an exciting new web feature.

Trusted Types

Carrying on the initial work from last month, we now support the following features of Trusted Types:

  • TrustedTypePolicyFactory#emptyHTML
  • TrustedTypePolicyFactory#emptyScript
  • require-trusted-types-for
  • Trusted Types support in HTMLScriptElement

There is still ongoing work to accommodate Trusted Types in other areas, such as the DOM APIs. (PRs #5828, #6057, #6058)

Global Privacy Control

Global Privacy Control (GPC) notifies websites that they are not permitted to sell or share information about your activity. Unlike the old Do Not Track header, GPC is backed by legislation requiring websites to respect it. This month, we've replaced our DNT implementation with GPC (PR #6175), and it can be enabled in the settings page.

Generating application menus

Ladybird currently has two UI frontends: AppKit on macOS, and Qt6 on other systems. The biggest remaining duplication between them was around menus. This month we introduced shared menu definitions in LibWebView, from which each frontend now generates its menus (PR #6062, PR #6221). This makes maintaining our UIs simpler, and developers can now define a menu item once and have it appear in both.

Improved selection handling

Copying selected text often gave the wrong result, due to how whitespace collapsing shifted offsets. This also caused our Range offsets to be wrong. We now better map the original text offsets to what you see on screen. (PR #6169)

::slotted() pseudo-element support

We added support for the ::slotted() pseudo-element, which allows styling of elements passed into shadow DOM slots.

newsletter-sep-2025-rt-slotted-selector-progress.png

Animation compositing

This month we added support for animation compositing via the animation-composition property (PR #6233) and the KeyframeEffect.composite API (PR #6213). These features let authors control how animations are combined when multiple animations affect the same property.

Stable setTimeout() firing order

When many setTimeout(..., 1) calls arrive in quick succession, several timers can share the same deadline. Previously, those ties were resolved arbitrarily. We now assign each timer a sequence ID and break ties by (deadline, sequence_id), ensuring equal-deadline timers fire in the order they were registered. (PR #6260)

HarfBuzz text shaping cache

One of the most common tasks in any browser engine is measuring text. We delegate this work to HarfBuzz, but shaping text is complex and can be slow. We now cache shaping results to avoid recalculating them, which drastically improves performance on text-heavy pages like Wikipedia and news sites. (PR #6254)

Credits

We'd like to thank everyone who contributed code this month:

Ali Mohammad Pur, Aliaksandr Kalenik, Andreas Kling, ayeteadoe, Callum Law, euro20179, Feng Yu, InvalidUsernameException, Jan Koudijs, Jelle Raaijmakers, Julian Dominguez-Schatz, Kemal Zebari, Kenneth Myhra, Lorenz A, Louis Dalibard, luizgfc, Luke Wilde, Marcos Del Sol Vives, me-it-is, MFMF-EGY, mikiubo, Niccolo Antonelli Dziri, Nico Weber, Pascal Pomper, Pavel Shliak, Pratyush Nair, Psychpsyo, R-Goc, Rocco Corsi, Sam Atkins, Shannon Booth, Shivendra Kumar, Tete17, Tim Ledbetter, Timothy Flynn, Veeti Paananen, zac, Zaggy1024

Don't miss what's next. Subscribe to Ladybird Newsletter:
Powered by Buttondown, the easiest way to start and grow your newsletter.