-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Description
Proposal
Introduce CSS like the following, which assigns colors to CSS variables:
.indigo {
--color-100: #e5edff;
--color-200: #cddbfe;
/* ... indigo 300-900 ... */
}
.red {
--color-100: #fde8e8;
--color-200: #fbd5d5;
/* ... red 300-900 ... */
}
/* ... more colors sets ...*/
.text-color-100 {
color: var(--color-100);
}
.text-color-200 {
color: var(--color-200);
}
/* ... */
.bg-color-100 {
background-color: var(--color-100);
}
.bg-color-200 {
background-color: var(--color-200);
}
The benefit is that it would be much easier to toggle the color theme of a widget.
For example, to change this button from red to indigo:
<button class="p-2 text-red-100 bg-red-700 hover:bg-red-600">click me</button>
You have to replace all three of the "red" classes with "indigo" classes:
<button class="p-2 text-indigo-100 bg-indigo-700 hover:bg-indigo-600">click me</button>
With the proposed CSS:
<button class="p-2 red text-color-100 bg-color-700 hover:bg-color-600">click me</button>
To make the button indigo, you change only one class:
<button class="p-2 indigo text-color-100 bg-color-700 hover:bg-color-600">click me</button>
Benefits
There are two savings with this approach. First, there is a savings in the effort of toggling colors. This savings is biggest if you need to theme widgets that subtly change their color with all of the hover/focus/active states, like the buttons from Tailwind UI. This is especially true if you are toggling colors with JS (e.g. a status indicator that changes from green to red).
Second, there is a potential savings in file size. Currently you need number-of-colors * utilties-with-color-theme * number-of-variants
classes. With this approach, you might get away with number-of-colors + utilties-with-color-theme * number-of-variants
classes. In extreme cases, that would be a 90x reduction in file size. Admittedly, actual savings would be much smaller, assuming the use of purge
, and considering that some widgets would still need to use multiple colors, or use different "lightness" values with different colors.
Drawbacks
This doesn't work if you need to mix colors on the same widget class="text-red-700 bg-blue-300"
. For that reason, some projects may still have a use for the per-color utilities.
If you intend to toggle colors on a single widget, you need the contrast to stay the same to maintain accessibility. That is, you need a palette where the visual intensity of each "lightness" is more consistent across colors, as in the palette from @tailwindcss/ui
. Otherwise text-color-600 bg-color-100
might be legible with red
, but illegible with yellow
.
This doesn't account for "dark mode". In that case, instead of toggling colors, you're swapping lightness. (Although that drastically over-simplifies the effort needed to create a dark mode website.) As a first pass, you could do something like this, I suppose:
.dark-mode .red {
--color-900: #fde8e8; /* usually assigned to --color-100 */
/* ... */
}
The proposal above loses all the Opacity utilities. To do things right, you'd need RGB values for the vars too:
.indigo {
--color-100: #e5edff;
--color-rgb-100: 229, 237, 255;
}
.text-color-100 {
--text-opacity: 1;
color: var(--color-100);
color: rgba(var(--color-rgb-100), var(--text-opacity));
}