Are Inline Styles Faster than CSS?
I recently migrated my website from CSS-in-JS to inline styles and discovered that inline styles improved the load performance of my website. Based on this discovery, I wrote a blog post suggesting that switching to inline styles could improve a website's performance.
When I shared my post on internet forums, people correctly pointed out that migrating from a specific CSS-in-JS library to inline styles was too ambiguous to suggest that inline styles could be faster than CSS.
Many people were convinced that CSS was faster than inline styles. In an effort to seek the truth, I decided to conduct a less ambiguous and more conclusive experiment.
To perform this experiment, I migrated my website to CSS. Yes, I migrated my entire website to CSS, and yes, it was incredibly tedious.
I used BEM for styling my components, and I used atomic CSS for styling elements that were not explicit components. I ended up with a little more than 2,000 lines of handwritten CSS.
I built three versions of my React app. The first version was the control using inline styles.
<div style="color: blue;" />
The second version used a CSS file.
<link rel="stylesheet" href="index-27557ee9.css" />
And for the third version, I inlined the CSS in a style tag in the head of the document. I will refer to this as inline CSS.
<style> /* CSS here */</style>
I deployed all three versions to a single preview environment for testing. I could switch between the different versions using a query parameter in the URL. I then took measurements of the following:
- Server render time
- HTML size
- JavaScript bundle size
- Browser render time
- Web vitals
This is an n-of-1 experiment, but my website is more complex than a todo app and more realistic than a synthetic benchmark. Here are the results.
Server Render Time
I render my React application on the server and send the pre-rendered HTML to the browser. I measured the time it took to render my application on the server for my home page and for my blog post about deploying a React app to Vercel.
I selected my home page because it is often the first page my users see. In addition, I selected my blog post about deploying a React app to Vercel because it is my longest blog post to date and, therefore, has the most HTML (over 6,000 nodes). For consistency, I conducted all my experiments using these two pages.
Here is some pseudocode for how I measured the time it took to render my application.
const start = performance.now();await render(<App />);const end = performance.now();const total = end - start;
I calculated the average render time for each page, and here are the results.
The time it took to render my React app was very inconsistent. However, when I took the average, the times were nearly identical.
The reason for the inconsistency is likely IO. I make some amount of API requests on each page, which is inherently variable in time.
However, there was no measurable correlation between inline styles and the time it took to render my application on the server. It would appear that the time it takes to stringify my inline styles is insignificant.
I'll admit that, since IO is happening, this test is not conclusive. It would be better to eliminate all variables. However, for static websites, the rendered HTML could be cached, and, in that case, the time it takes to render doesn't matter as much.
HTML Size
Here is a size comparison of the HTML generated by each version of my app.
As you might expect, inline styles produced the largest HTML documents. However, after compression, the difference wasn't very significant.
What's interesting is that after compression, inline styles produced smaller documents than inline CSS. I believe this is because there is more repetition of inline styles, making them ideal for compression.
JavaScript Bundle Size
Here is a size comparison of the JavaScript generated by each version of my app.
Inline styles did increase the size of my JavaScript bundle. But again, after compression, the difference was insignificant. Remarkably, styling my entire website using inline styles only increased my JavaScript bundle by 1 kB after compression!
I want to point out that the size of my CSS file, minified and brotli'd, is 8.9 kB. That means inline styles actually resulted in the fewest bytes over the wire! At least for the first page visit before anything is cached in the browser.
I do not currently code-split my JavaScript, but if I did, then inline styles would naturally get chunked up as well.
Browser Render Time
Now let's have a look at browser render performance for each version. For these tests, I allowed the browser to cache the CSS file.
Parse, style, layout, and paint are stages of the browser's rendering pipeline. It is how it turns HTML into pixels.
The chart shows how long it took the browser to render each page once it started parsing the HTML. It also shows the frequency and time spent in each stage of the rendering pipeline.
While inline styles wasn't always the fastest to render the entire page, it was consistently the fastest to put pixels on the screen. This can be seen by looking for the first paint indicator (FP) in the chart.
There are a couple interesting observations from this data. The first observation is that for small pages, like my home page, a fast computer may parse the HTML before it parses the CSS (even from the cache).
If you look closely at the CSS timeline for my home page you'll see a second blue bar. That is the browser parsing the CSS. It can't render anything until it parses the CSS because CSS is render blocking.
The other interesting observation is that the browser (at least Chrome) appears to parse HTML for roughly 10 milliseconds before attempting to ship a frame. For inline CSS, the browser may need to process multiple chunks of HTML before it finishes parsing the CSS.
Furthermore, both CSS and inline CSS appear to tax first paint. This is especially noticeable on low powered devices. This makes sense, if you give the browser a wall of CSS, it has to cut through all that CSS before it can render anything.
Web Vitals
To round things out let's compare web vitals for each version of my app. To measure web vitals on my own devices I used the web-vitals npm package maintained by Google Chrome.
For these tests, I was connected to my home wifi (360 Mbps) and I allowed the browser to cache the CSS file.
More often than not, inline styles outperformed CSS when it came to first contentful paint (FCP) and largest contentful paint (LCP). This is consistent with the data for render performance.
There wasn't a measurable correlation between inline styles and first input delay (FID) or interaction to next paint (INP). Both inline styles and CSS were well below the 200 millisecond threshold to feel instantaneous.
Now let's take a look at Lighthouse and PageSpeed Insights to see if the trend continues.
There appears to be a slight advantage to to inline styles and inline CSS compared to CSS on desktop. However, on mobile there is a significant advantage to inline styles and inline CSS compared to CSS.
Both Lighthouse and PageSpeed Insights show horrible performance for CSS on mobile. This is inconsistent with the data I collected from my own devices. I believe this is because, when they conduct their tests, the browser's cache is empty and the network speed is throttled.
If you think about it, the first time a user visits a website the browser's cache will be empty. This means the first experience a user has with a website will be the worst in terms of performance.
Conclusion
There was no measurable correlation between inline styles and the time it took to render my React application on the server.
In addition, while inline styles did increase the size of my HTML and JavaScript, the difference was insignificant after compression. In fact, inline styles resulted in the fewest bytes total for the browser to download, at least on first page visit.
Furthermore, using inline styles the browser is able to start painting pixels earlier in the rendering process. This is especially true on mobile or low powered devices.
Over time, CSS will increase in size as more features are added to a website. This will negatively impact performance of existing pages.
Based on the data, I believe there is evidence to suggest that inline styles are better for performance than CSS. However, this may not be true for every website. I encourage people to do their own experiments and seek their own truth. The more data we collect the more we will understand.
Written by Daniel Nagy
Daniel is a software engineer and full-stack web developer. He studied computer science at Ohio University and has been doing web development and hybrid mobile app development since 2014.
If you liked this post, then please consider donating or becoming a sponsor. Your support will help me produce more content that gives back to the community.
Comments
You will not receive notifications for new comments. If you are waiting for a reply, please check back periodically.