← All articles

Fixing CDK Virtual Scroll Flicker in Angular Zoneless Mode with patch-package

When zoneless change detection is enabled, CDK Virtual Scroll can flicker during scrolling. This guide applies a patch-package workaround until the upstream fix lands.

Published
Fixing CDK Virtual Scroll Flicker in Angular Zoneless Mode with patch-package cover image

When you use Angular in zoneless mode, CDK Virtual Scroll can flicker. The issue is reported on GitHub and a PR exists, but it has not been merged yet.

This article shows how to fix the bug with patch-package.

Bug details

When you enable provideExperimentalZonelessChangeDetection in Angular zoneless mode, virtual-scroll-viewport flickers while scrolling.

The cause is that transform updates become visible. Specifically, when the viewport adjusts content position, applying the transform directly causes flicker.

Fixing it with patch-package

What is patch-package?

patch-package is a tool for patching packages inside node_modules directly. Typical use cases:

  1. You want to fix a package bug, but the PR is not merged yet
  2. You want to extend a package, but the PR is not merged yet
  3. You do not want to bump the package version, but you need a specific bug fix

How it works

patch-package provides a way to apply temporary fixes to packages. First, edit the package in node_modules, then save the diff under a patches directory. After that, running npm install applies the patch automatically through a postinstall script.

This lets you apply a temporary fix without forking the package source. Because patch files live in version control, you can share the same fix across a team.

Implementation steps

1. Install patch-package

First, install patch-package:

npm install --save-dev patch-package

2. Update package.json

Add the following script to the scripts section of package.json:

{
  "scripts": {
    "postinstall": "patch-package"
  }
}

This postinstall script runs automatically after npm install and applies patches from the patches directory.

3. Create the patch

Edit the @angular/cdk source. The change looks like this:

diff --git a/node_modules/@angular/cdk/__ivy_ngcc__/esm2020/scrolling/virtual-scroll-viewport.mjs b/node_modules/@angular/cdk/__ivy_ngcc__/esm2020/scrolling/virtual-scroll-viewport.mjs
index 1234567..89abcdef 100644
--- a/node_modules/@angular/cdk/__ivy_ngcc__/esm2020/scrolling/virtual-scroll-viewport.mjs
+++ b/node_modules/@angular/cdk/__ivy_ngcc__/esm2020/scrolling/virtual-scroll-viewport.mjs
@@ -123,456 +789,123 @@
-            this._contentWrapper.nativeElement.style.transform = this._renderedContentTransform;
+            afterNextRender(() => {
+                this._contentWrapper.nativeElement.style.transform = this._renderedContentTransform;
+                this._isChangeDetectionPending = false;
+                const runAfterChangeDetection = this._runAfterChangeDetection;
+                this._runAfterChangeDetection = [];
+            });

This moves the transform update into the afterNextRender phase and prevents flicker.

4. Apply the patch

After editing, run:

npx patch-package @angular/cdk

This creates a file such as patches/@angular+cdk+19.2.14.patch containing the diff.

5. Verify the patch

Check the generated patch file. It should look like this:

diff --git a/node_modules/@angular/cdk/__ivy_ngcc__/esm2020/scrolling/virtual-scroll-viewport.mjs b/node_modules/@angular/cdk/__ivy_ngcc__/esm2020/scrolling/virtual-scroll-viewport.mjs
index 1234567..89abcdef 100644
--- a/node_modules/@angular/cdk/__ivy_ngcc__/esm2020/scrolling/virtual-scroll-viewport.mjs
+++ b/node_modules/@angular/cdk/__ivy_ngcc__/esm2020/scrolling/virtual-scroll-viewport.mjs
@@ -123,456 +789,123 @@
-            this._contentWrapper.nativeElement.style.transform = this._renderedContentTransform;
+            afterNextRender(() => {
+                this._contentWrapper.nativeElement.style.transform = this._renderedContentTransform;
+                this._isChangeDetectionPending = false;
+                const runAfterChangeDetection = this._runAfterChangeDetection;
+                this._runAfterChangeDetection = [];
+            });

Managing patches

Commit patch files to your version control system (Git, etc.). Benefits:

  1. Share the same fix across the team
  2. Track patch history
  3. Avoid forgetting to apply patches

When you upgrade the package version, the patch may stop applying and you will need to update it.

Summary

This article showed how to fix CDK Virtual Scroll flicker in Angular zoneless mode with patch-package.

The fix removes Virtual Scroll flicker and makes scrolling smoother.

This is a temporary workaround. When an official Angular fix ships, remove the patch and use the upstream change instead.

See you next time.