Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[blog] Introducing Pigment CSS blog post #42198

Merged
merged 36 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
e6b7ba7
starting over
samuelsycamore Apr 10, 2024
028eff7
reverting
samuelsycamore Apr 10, 2024
5909f0c
initializing
samuelsycamore May 10, 2024
a522128
outline
samuelsycamore May 10, 2024
cc8681f
dedupe and prettier
samuelsycamore May 10, 2024
accf09b
rever pnpm lockfile
samuelsycamore May 10, 2024
c145800
Merge remote-tracking branch 'upstream/next' into pigment-intro-post
LukasTy May 10, 2024
702d8ae
title
samuelsycamore May 10, 2024
e41dc62
straight quotes
samuelsycamore May 10, 2024
c25dfdb
intro first pass, nbsps
samuelsycamore May 13, 2024
db5806b
why pigment
samuelsycamore May 13, 2024
f4eb4f7
how pigment works
samuelsycamore May 13, 2024
4c01719
tailwind nbsp
samuelsycamore May 13, 2024
215673e
benefits
samuelsycamore May 13, 2024
f661b38
for material ui
samuelsycamore May 13, 2024
7c4699b
typo
samuelsycamore May 13, 2024
7396c50
state of css
samuelsycamore May 13, 2024
3712171
briefly clarify whys in intro
samuelsycamore May 13, 2024
89042b8
rephrasing a little
samuelsycamore May 13, 2024
0325259
perf, future
samuelsycamore May 13, 2024
a6a356d
first draft complete
samuelsycamore May 13, 2024
e86ebf9
run-time, build-time
samuelsycamore May 13, 2024
48a33f3
nbsps
samuelsycamore May 13, 2024
b8696f0
more vale fixes
samuelsycamore May 13, 2024
c865606
Apply suggestions from code review
samuelsycamore May 14, 2024
1271247
title
samuelsycamore May 14, 2024
d14d96d
review feedback
samuelsycamore May 14, 2024
55ab13e
perf test app callout
samuelsycamore May 14, 2024
56cf3c9
nbsp
samuelsycamore May 14, 2024
00c43f7
add Pigment as a tag
danilo-leal May 15, 2024
41674b8
change publication date
danilo-leal May 15, 2024
fb0abde
add custom OG image
danilo-leal May 15, 2024
cbcbe7f
add code blocks
danilo-leal May 15, 2024
11c2151
shorthand notation
danilo-leal May 15, 2024
4ba9aaf
theme-aware sx prop
danilo-leal May 15, 2024
9a9e884
use a table instead of bullet list
danilo-leal May 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/pages/blog/introducing-pigment-css.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as React from 'react';
import TopLayoutBlog from 'docs/src/modules/components/TopLayoutBlog';
import { docs } from './introducing-pigment-css.md?muiMarkdown';

export default function Page() {
return <TopLayoutBlog docs={docs} />;
}
114 changes: 114 additions & 0 deletions docs/pages/blog/introducing-pigment-css.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
title: 'Introducing Pigment CSS: the next generation of CSS-in-JS for Material UI'
samuelsycamore marked this conversation as resolved.
Show resolved Hide resolved
description: 'Pigment CSS offers significant performance gains along with RSC and App Router support.'
date: 2024-05-14T00:00:00.000Z
authors: ['samuelsycamore']
danilo-leal marked this conversation as resolved.
Show resolved Hide resolved
tags: ['Pigment CSS']
card: false
---

In the era of React Server Components and the Next.js App Router, component libraries like Material UI must make some paradigm-shifting changes to reap the potential performance gains by moving more of the work of rendering UIs from run time to build time.

Trouble is, the "traditional" CSS-in-JS solutions we rely on aren't able to come along with us because so much of what they do happens at run time.

Check warning on line 12 in docs/pages/blog/introducing-pigment-css.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Google.We] Try to avoid using first-person plural like 'we'. Raw Output: {"message": "[Google.We] Try to avoid using first-person plural like 'we'.", "location": {"path": "docs/pages/blog/introducing-pigment-css.md", "range": {"start": {"line": 12, "column": 51}}}, "severity": "WARNING"}

Check warning on line 12 in docs/pages/blog/introducing-pigment-css.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Google.We] Try to avoid using first-person plural like 'us'. Raw Output: {"message": "[Google.We] Try to avoid using first-person plural like 'us'.", "location": {"path": "docs/pages/blog/introducing-pigment-css.md", "range": {"start": {"line": 12, "column": 93}}}, "severity": "WARNING"}
And with nearly 50% of respondents in the [State of CSS 2023 survey](https://2023.stateofcss.com/en-US/css-in-js/) indicating they use styled-components, we're looking at a whole lot of React developers with no clear path forward from here.

Check warning on line 13 in docs/pages/blog/introducing-pigment-css.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Google.We] Try to avoid using first-person plural like 'we'. Raw Output: {"message": "[Google.We] Try to avoid using first-person plural like 'we'.", "location": {"path": "docs/pages/blog/introducing-pigment-css.md", "range": {"start": {"line": 13, "column": 155}}}, "severity": "WARNING"}
samuelsycamore marked this conversation as resolved.
Show resolved Hide resolved

For a library as widely used as Material UI, the biggest challenge is to stay up-to-date while introducing as few breaking changes as humanly possible, to maintain a consistent and reliable developer experience without asking users to completely change the way they build UI components.

That's where Pigment CSS comes in.

Pigment CSS is MUI's new in-house styling solution: a zero-runtime CSS-in-JS package that generates colocated styles to their own CSS files at build time.
With Pigment CSS you get the latest and greatest advancements in CSS along with RSC compatibility, _plus_ significant performance improvements when compared with Emotion in Material UI v5.
samuelsycamore marked this conversation as resolved.
Show resolved Hide resolved
And though it's specially tailored to meet the needs of Material UI users, Pigment CSS can be used with _any_ React component library you prefer.
samuelsycamore marked this conversation as resolved.
Show resolved Hide resolved

## Why Pigment CSS?

### Traditional CSS-in-JS is not enough

Emotion made a lot of sense for Material UI v5 in late 2021, but so much has changed in the React ecosystem since then.
In early 2023 React introduced Server Components, and Next.js offered the first implementation of the new spec with the App Router shortly thereafter.
samuelsycamore marked this conversation as resolved.
Show resolved Hide resolved

RSCs unlock a whole new realm of possibilities for React; for us as UI developers, it means we can create components that are fully rendered at build time so we don't have to pass that burden on to the client at run time.

Check warning on line 30 in docs/pages/blog/introducing-pigment-css.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Google.We] Try to avoid using first-person plural like 'us'. Raw Output: {"message": "[Google.We] Try to avoid using first-person plural like 'us'.", "location": {"path": "docs/pages/blog/introducing-pigment-css.md", "range": {"start": {"line": 30, "column": 63}}}, "severity": "WARNING"}

Check warning on line 30 in docs/pages/blog/introducing-pigment-css.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Google.We] Try to avoid using first-person plural like 'we'. Raw Output: {"message": "[Google.We] Try to avoid using first-person plural like 'we'.", "location": {"path": "docs/pages/blog/introducing-pigment-css.md", "range": {"start": {"line": 30, "column": 93}}}, "severity": "WARNING"}

Check warning on line 30 in docs/pages/blog/introducing-pigment-css.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Google.We] Try to avoid using first-person plural like 'we'. Raw Output: {"message": "[Google.We] Try to avoid using first-person plural like 'we'.", "location": {"path": "docs/pages/blog/introducing-pigment-css.md", "range": {"start": {"line": 30, "column": 159}}}, "severity": "WARNING"}
But working with RSCs requires us to let go of familiar APIs like `useContext`, which in turn becomes a major blocker for using the last generation's style engines like Emotion that rely heavily on this hook for theming.

Check warning on line 31 in docs/pages/blog/introducing-pigment-css.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Google.We] Try to avoid using first-person plural like 'us'. Raw Output: {"message": "[Google.We] Try to avoid using first-person plural like 'us'.", "location": {"path": "docs/pages/blog/introducing-pigment-css.md", "range": {"start": {"line": 31, "column": 32}}}, "severity": "WARNING"}
danilo-leal marked this conversation as resolved.
Show resolved Hide resolved

:::info
To learn more about RSCs, we highly recommend reading [Making Sense of React Server Components](https://www.joshwcomeau.com/react/server-components/) by Josh Comeau.

Check warning on line 34 in docs/pages/blog/introducing-pigment-css.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Google.We] Try to avoid using first-person plural like 'we'. Raw Output: {"message": "[Google.We] Try to avoid using first-person plural like 'we'.", "location": {"path": "docs/pages/blog/introducing-pigment-css.md", "range": {"start": {"line": 34, "column": 27}}}, "severity": "WARNING"}
:::

### Material UI is a unique use case

Material UI is downloaded millions of times per month and is one of the most rigorously battle-tested UI libraries on the internet, with a GitHub history spanning all the way back to 2014.
It's had to make some massive changes along the way to keep up with the times; most recently, moving from JSS to Emotion from v4 to v5.
While those breaking changes did bring many benefits overall, they unfortunately came with a notoriously painful migration experience.

We learned our lesson!

Check warning on line 43 in docs/pages/blog/introducing-pigment-css.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Google.We] Try to avoid using first-person plural like 'We'. Raw Output: {"message": "[Google.We] Try to avoid using first-person plural like 'We'.", "location": {"path": "docs/pages/blog/introducing-pigment-css.md", "range": {"start": {"line": 43, "column": 1}}}, "severity": "WARNING"}

Check warning on line 43 in docs/pages/blog/introducing-pigment-css.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Google.We] Try to avoid using first-person plural like 'our'. Raw Output: {"message": "[Google.We] Try to avoid using first-person plural like 'our'.", "location": {"path": "docs/pages/blog/introducing-pigment-css.md", "range": {"start": {"line": 43, "column": 12}}}, "severity": "WARNING"}
We can't do that to our users again.

So when it came time to seek out a new way to generate styles, we knew we needed to keep the syntax and authoring experience as similar as possible to Emotion and styled-components, to minimize friction when migrating.
samuelsycamore marked this conversation as resolved.
Show resolved Hide resolved

### Other options don't meet our needs

For those of us who are perfectly happy with the patterns we know and love from CSS-in-JS, it feels frustrating to consider abandoning all that muscle memory just to reinvent the wheel yet again.
danilo-leal marked this conversation as resolved.
Show resolved Hide resolved
We like the DX of colocated styles, and we'd rather not bloat the DOM with atomic class names—so Tailwind CSS, StyleX, Panda CSS, and other solutions that have cropped up in recent months just don't match up with our preferences.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't feel accurate. I have reworked this part in https://react-conf-2024-pigment-css.netlify.app/?presenterMode=true&slideIndex=29&stepIndex=0. The first point is that Atomic for production, sure, if it helps with performance, great. The issue with atomic classes is only in development mode IMHO. I have doubt that https://twitter.com/astahmer_dev/status/1776919737999425629 can truly help here.

My point is that "Other options don't meet our needs", yes, but a big part of this is that we also see an opportunity with a deeper bundle integration, that we don't see any other library trying. Mostly because it's a lot of work, but hopefully: 1. we have the resources to make it work, and 2. React Compiler is paving the way

Two examples of projects not trying/giving up on this direction:


## How Pigment CSS works

Pigment CSS is a zero-runtime CSS-in-JS library: This means it doesn't have access to the end user's browser runtime, which would be necessary to generate and insert authored CSS at run time.
Instead, it does all its processing at build time to pre-generate the CSS which then becomes part of the output bundle.

Pigment CSS is built on top of the [WyW-in-JS](https://wyw-in-js.dev/) library that also powers [Linaria](https://linaria.dev/).
danilo-leal marked this conversation as resolved.
Show resolved Hide resolved
It features a [processor](https://wyw-in-js.dev/how-to/custom-tagged-template#creating-a-processor) which makes it possible to create custom logic that's triggered by the presence of different imports from the library.
The processor looks through the source code for `styled()`, `css()`, and other function calls and extracts the arguments to be evaluated.
These values are then handed back to Pigment CSS for additional parsing and evaluation.

:::info
Check out [How Pigment CSS works](https://github.com/mui/pigment-css/blob/master/HOW_PIGMENT_CSS_WORKS.md) for complete details.
:::

## Benefits of using Pigment CSS

For Material UI users, the benefits of adopting Pigment CSS\* are clear: your end users get better performance, and you get RSC and App Router compatibility without having to significantly change how you author component styles.
samuelsycamore marked this conversation as resolved.
Show resolved Hide resolved

_\*These benefits extend to other component libraries beyond Material UI as well, but that's our focus for the sections that follow._
_We intend for Pigment CSS to be a viable solution for the React ecosystem as a whole, but you can understand why we're prioritizing Material UI during early development._

### Better performance

When comparing the same Material UI app built with Next.js and either Emotion or Pigment CSS, the latter led to:
samuelsycamore marked this conversation as resolved.
Show resolved Hide resolved

- 20% reduction in first load JS (104 kB vs. 131 kB)

Check failure on line 78 in docs/pages/blog/introducing-pigment-css.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [MUI.CorrectReferenceAllCases] Use 'JavaScript' instead of 'JS' Raw Output: {"message": "[MUI.CorrectReferenceAllCases] Use 'JavaScript' instead of 'JS'", "location": {"path": "docs/pages/blog/introducing-pigment-css.md", "range": {"start": {"line": 78, "column": 30}}}, "severity": "ERROR"}
- 9% decrease in First Contentful Paint (455 ms vs. 503 ms)
- 15% reduction in Time To First Byte
samuelsycamore marked this conversation as resolved.
Show resolved Hide resolved
- 7.5% reduction in page HTML (14.7 kB vs. 15.9 kB)

### Familiar developer experience

For developers migrating from Emotion or styled-components, you're probably already familiar with the most common patterns employed by Pigment CSS.
`styled()` and `css()` are the two main functions used to define styles, and they mostly work the same as you'd expect them to (with some notable differences due to the nature of build-time CSS-in-JS—see [Coming from Emotion or styled-components](https://github.com/mui/pigment-css/tree/master?tab=readme-ov-file#coming-from-emotion-or-styled-components) for details).

We've also ported over the `sx` prop from MUI System, so you can still define styles directly in a given component, but now it's much more performant than before.

Check failure on line 88 in docs/pages/blog/introducing-pigment-css.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [MUI.MuiBrandName] Use a non-breaking space (option+space on Mac, Alt+0160 on Windows or AltGr+Space on Linux, instead of space) for brand name ('MUI System' instead of 'MUI System') Raw Output: {"message": "[MUI.MuiBrandName] Use a non-breaking space (option+space on Mac, Alt+0160 on Windows or AltGr+Space on Linux, instead of space) for brand name ('MUI System' instead of 'MUI System')", "location": {"path": "docs/pages/blog/introducing-pigment-css.md", "range": {"start": {"line": 88, "column": 43}}}, "severity": "ERROR"}
And in Pigment CSS we've extended support for `sx` to include _all_ DOM nodes—not just Material UI components—so you don't need to wrap a simple `<div>` or `<span>` with a Box component to apply theme styles to it.

Check failure on line 89 in docs/pages/blog/introducing-pigment-css.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [MUI.MuiBrandName] Use a non-breaking space (option+space on Mac, Alt+0160 on Windows or AltGr+Space on Linux, instead of space) for brand name ('Material UI' instead of 'Material UI') Raw Output: {"message": "[MUI.MuiBrandName] Use a non-breaking space (option+space on Mac, Alt+0160 on Windows or AltGr+Space on Linux, instead of space) for brand name ('Material UI' instead of 'Material UI')", "location": {"path": "docs/pages/blog/introducing-pigment-css.md", "range": {"start": {"line": 89, "column": 88}}}, "severity": "ERROR"}

### Future-proof solution

Though we're still quite early in RSC era, it seems inevitable that the ecosystem as a whole will converge on this new paradigm for React over time.
Next.js gave us our first glimpse with the App Router; RedwoodJS [recently released their own implementation](https://redwoodjs.com/blog/rsc-now-in-redwoodjs); and many other frameworks and meta-frameworks are currently working out POCs and RFCs to catch up.
samuelsycamore marked this conversation as resolved.
Show resolved Hide resolved
Regardless of how quickly Server Components catch on among developers, it's clear that library maintainers now must support [the two Reacts](https://overreacted.io/the-two-reacts/) (client-side and server-side) to stay relevant into the future.

Pigment CSS, then, is yet another bet from MUI on the longevity and sustainability of the React ecosystem—and a promise that we'll continue to innovate in this space for years to come.

And perhaps most importantly: because Pigment CSS is maintained by the same folks behind Material UI, we'll have a lot more control over how the tool evolves over time to continue to meet our users' needs.
In a perfect world, this would be the last time you'd ever have to migrate your Material UI app to a new style engine.

Check failure on line 100 in docs/pages/blog/introducing-pigment-css.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [MUI.MuiBrandName] Use a non-breaking space (option+space on Mac, Alt+0160 on Windows or AltGr+Space on Linux, instead of space) for brand name ('Material UI' instead of 'Material UI') Raw Output: {"message": "[MUI.MuiBrandName] Use a non-breaking space (option+space on Mac, Alt+0160 on Windows or AltGr+Space on Linux, instead of space) for brand name ('Material UI' instead of 'Material UI')", "location": {"path": "docs/pages/blog/introducing-pigment-css.md", "range": {"start": {"line": 100, "column": 81}}}, "severity": "ERROR"}
We'll do our best to make that a reality. 🤞

## What's next

Pigment CSS is currently in the early alpha stage of development—the plan is to have a stable version ready to release alongside Material UI v6 later this year.
samuelsycamore marked this conversation as resolved.
Show resolved Hide resolved
When that happens, you'll have the choice to opt in to Pigment CSS incrementally after migrating to v6, giving you all the time you need to migrate on your own terms.

That said, Pigment CSS is available now for experimentation, and we'd love for you to give it a try and let us know what you think—your feedback at this stage could have a major impact on the final product.

## Get started with Pigment CSS

Check failure on line 110 in docs/pages/blog/introducing-pigment-css.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [MUI.MuiBrandName] Use a non-breaking space (option+space on Mac, Alt+0160 on Windows or AltGr+Space on Linux, instead of space) for brand name ('Pigment CSS' instead of 'Pigment CSS') Raw Output: {"message": "[MUI.MuiBrandName] Use a non-breaking space (option+space on Mac, Alt+0160 on Windows or AltGr+Space on Linux, instead of space) for brand name ('Pigment CSS' instead of 'Pigment CSS')", "location": {"path": "docs/pages/blog/introducing-pigment-css.md", "range": {"start": {"line": 110, "column": 21}}}, "severity": "ERROR"}

Head to the [Pigment CSS repo](https://github.com/mui/pigment-css/) to learn how to set it up and start tinkering.

Check failure on line 112 in docs/pages/blog/introducing-pigment-css.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [MUI.MuiBrandName] Use a non-breaking space (option+space on Mac, Alt+0160 on Windows or AltGr+Space on Linux, instead of space) for brand name ('Pigment CSS' instead of 'Pigment CSS') Raw Output: {"message": "[MUI.MuiBrandName] Use a non-breaking space (option+space on Mac, Alt+0160 on Windows or AltGr+Space on Linux, instead of space) for brand name ('Pigment CSS' instead of 'Pigment CSS')", "location": {"path": "docs/pages/blog/introducing-pigment-css.md", "range": {"start": {"line": 112, "column": 14}}}, "severity": "ERROR"}
Please feel free to [open a new issue](https://github.com/mui/pigment-css/issues) if you encounter any bugs or frustrations along the way.
And while you're there, why not ⭐️ star the repo ⭐️ to let us know you're excited and help spread the word to others? 😁
danilo-leal marked this conversation as resolved.
Show resolved Hide resolved