Google Chrome performance issues with CSS Grid

Wednesday, 5 May 2021

Summary

There is a "bug" in Google Chrome where interactive controls (such as buttons, inputs, text areas, etc.) can encounter severe lag if they are nested in too many CSS grids.

Example

Check out this Codepen in Chrome and another browser of your choice - I was comparing it to Safari on macOS. Type quickly (or smoosh your keyboard) in the top input box, compare the experience to when you do the same in the bottom input box.

Discovery

When I stumbled across display: grid I felt as though I found the holy grail. It was the solution to any interface I was building. display: flex suddenly felt so old. I started using it everywhere, for the simplest layouts like separating two elements where a margin-left would have been more than enough.

The project I was actively working on when this love for display: grid started was the Pokko user interface. With my liberal use of the grid, the interface was looking nice, it was working nicely, everything was good.

Unfortunately, there was an issue that kept popping up now and again that users were sporadically reporting about performance, specifically lag when entering content into text fields.

Being a React application I assumed that it had something to do with that, perhaps some performance issue I coded where the controls were being re-rendered on each keystroke. I dove deeply into optimising that to ensure that it wasn't the case, I swapped out controlled for uncontrolled inputs so that there could be no re-render on each keystroke. The lag remained.

I thought perhaps it could be to do with how deeply nested my inputs were in the DOM tree, so I tried flattening out the structure. The issue persisted.

I let it slide and tried to ignore it and hoped it would go away. That also didn't help.

Fast-forward a few months and it had been reported a few more times, and I was noticing the issue more and more.

I decided to spin up the site in Safari to see how it was behaving there. Surprisingly there was no input lag at all. Up to this point, I had been developing and using the site in Chrome. I then tried a few other browsers and they were all fine.

At this point, I was convinced that it was an issue with Chrome itself. This meant that it was likely something to do with how the browser puts the page together. Since I had ruled out React interfering and had even removed all Javascript bindings from my inputs and still experienced the issue, I figured the only other thing was CSS.

I remembered seeing a tweet recently about resetting all CSS properties, so I dropped in the following.

1* {
2  all: unset !important;
3}

My input lag was gone.

After months of trying to figure out this problem, I had finally discovered the cause.

I needed CSS to make my interface pretty, so I took on the task of tracking down what specifically could be causing it.

When I looked at the Elements inspector in Chrome the first thing that jumped out at me was that all the hierarchy of elements above my input fields were all display: grid. One by one I went through and disabled that property et voila. Since I was only using the grid to separate elements, I swapped it out for margins and I had the same look and feel but no input lag.

Problem solved. Chapter finished.

It really was a great weight off my shoulders, it had me quite concerned about the viability of the product and my ability as a front-end developer.

Powered by Pokko