Skip to content

Commit 5312616

Browse files
css-color-parser : blog post (#905)
* css-color-parser : blog post * color parser blog post * color-mix blog post * tweaks * add some text * add some text * Styles and Suggestions (#916) * Minor reactivity touches * More adjustments * Update sites/postcss-preset-env/blog/postcss-color-mix-function.md Co-authored-by: Romain Menke <[email protected]> * Code suggestions --------- Co-authored-by: Romain Menke <[email protected]> * set date --------- Co-authored-by: Antonio Laguna <[email protected]>
1 parent 6a66eaa commit 5312616

10 files changed

Lines changed: 584 additions & 1 deletion

sites/package-lock.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sites/postcss-preset-env/blog/css-calc-v1.0.0.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ It can not do everything a browser would be able to, but it can still do enough
2929

3030
This new tool will enable us to create better PostCSS plugins for [Relative Color Syntax], [Color Mix] and any other feature that interacts with `calc()`.
3131

32-
{% block scripts %}<script async defer src="{{ "/static/js/blog_calc_2023_02_21.js" | addHash }}"></script>{% endblock %}
32+
{% block scripts %}<script async defer src="{{ '/static/js/blog_calc_2023_02_21.js' | addHash }}"></script>{% endblock %}
3333

3434
[CSS Calc]: https://github.com/csstools/postcss-plugins/tree/main/packages/css-calc#readme
3535
[Relative Color Syntax]: https://css-tricks.com/new-css-color-features-preview/#aa-the-relative-color-syntax-is-super-useful
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
---
2+
title: CSS Color Parser
3+
description: A new package to parse CSS color notations.
4+
date: 2023-03-27
5+
---
6+
7+
## Try it out
8+
9+
<label id="color-input-label-1" for="color-input-1">A new parser for CSS color notations:</label>
10+
<textarea id="color-input-1" class="color-input" rows="2">
11+
oklch(calc(50% * 1.4) 0.268 134.568)
12+
</textarea>
13+
<output id="color-output-rgb-1" class="color-output-rgb" for="color-input-1" style="--color: rgb(88, 186, 0);">rgb(88, 186, 0)</output>
14+
<output id="color-output-p3-1" class="color-output-p3" for="color-input-1" style="--color: color(display-p3 0.41387 0.73323 0);">color(display-p3 0.41387 0.73323 0)</output>
15+
16+
## One more specialized parser
17+
18+
Plenty of plugins in `postcss-preset-env` interact with CSS color values.
19+
We provide fallbacks for modern notations like `rgb(255 0 255 / 50%)` and new color functions like `color(display-p3 0.5 0 0.5 / 0.5)`.
20+
21+
In the past, each package had its own implementation of the needed conversion logic.
22+
This was fine for a while, but as the number of plugins grew, so did the amount of duplicate code.
23+
This was harder to maintain and plugins were larger than they needed to be.
24+
25+
_We had initially hoped to use an existing package (e.g. [color.js](https://colorjs.io) or [culori](https://culorijs.org)), but no package was designed specifically to parse and convert CSS colors exactly as a browser would. We hope that our modular approach allows others to reuse bits even if their use case is different._
26+
27+
[`css-color-5`](https://drafts.csswg.org/css-color-5/) introduced recursive color functions which required a different class of tools.<br>
28+
Simple parsing algorithms or regular expressions were no longer sufficient.
29+
30+
_A recursive example :_<br>
31+
```css
32+
.example {
33+
color: color-mix(
34+
in lch,
35+
#d20 50%,
36+
color-mix(
37+
in srgb,
38+
purple,
39+
rgb(230 10 15) 10%
40+
)
41+
);
42+
}
43+
```
44+
45+
We started from our existing [tokenizer](https://github.com/csstools/postcss-plugins/tree/main/packages/css-tokenizer) and [parsing algorithms](https://github.com/csstools/postcss-plugins/tree/main/packages/css-parser-algorithms) and added [`@csstools/css-calc`](https://github.com/csstools/postcss-plugins/tree/main/packages/css-calc) on on top of that.
46+
47+
We also created and published the [`@csstools/color-helpers` npm package](https://github.com/csstools/postcss-plugins/tree/main/packages/color-helpers) with the color logic based on the sample code maintained by the CSS Working Group.
48+
We are not the creators of most of the algorithms in this package but our users require something distributed through npm.
49+
50+
`@csstools/color-helpers` contains all the parts needed to convert between color spaces and color notations, but it doesn't have any knowledge of CSS and isn't able to parse or serialize CSS color values.
51+
52+
We brought all these building blocks together in a new package [`@csstools/css-color-parser`](https://github.com/csstools/postcss-plugins/tree/main/packages/css-color-parser).
53+
54+
This package is able to parse CSS color values like a browser would and convert them to fallback notations.
55+
56+
Currently supported in the parser :
57+
- `color-mix` from [CSS Color Module Level 5](https://drafts.csswg.org/css-color-5/)
58+
- all color notations from [CSS Color Module Level 4](https://drafts.csswg.org/css-color-4/)
59+
- named colors
60+
- `transparent`
61+
- hex colors
62+
- `calc()` expressions in color notations
63+
- recursive color functions
64+
65+
Only two serialization formats are currently supported :
66+
- `rgb(...)`
67+
- `color(display-p3 ...)`
68+
69+
_If you require other formats, please [open an issue](https://github.com/csstools/postcss-plugins/issues/new/choose)_
70+
71+
<label id="color-input-label-2" for="color-input-2">Go nuts:</label>
72+
<textarea id="color-input-2" class="color-input" rows="15">
73+
color-mix(
74+
in lch,
75+
purple calc(100% * sin(0.1)),
76+
color-mix(
77+
in oklch,
78+
#4fe calc(100% / 3),
79+
color(
80+
display-p3
81+
calc(33% * 3)
82+
calc(1 / 2) -0.1)
83+
calc(100% / 3 * 2
84+
)
85+
) calc(20% + 4%)
86+
)
87+
</textarea>
88+
<output id="color-output-rgb-2" class="color-output-rgb" for="color-input-2" style="--color: rgba(255, 99, 0, 0.339833);">rgba(255, 99, 0, 0.339833)</output>
89+
<output id="color-output-p3-2" class="color-output-p3" for="color-input-2" style="--color: color(display-p3 0.9361 0.42808 0.14191 / 0.339833);">color(display-p3 0.9361 0.42808 0.14191 / 0.339833)</output>
90+
91+
{% block scripts %}<script async defer src="{{ '/static/js/blog_color_parser_2023_03_27.js' | addHash }}"></script>{% endblock %}
92+
93+
<style>
94+
.color-input, .color-output-rgb, .color-output-p3 {
95+
background-color: #263238;
96+
border-radius: 3px;
97+
border: 1px solid grey;
98+
color: white;
99+
display: block;
100+
font-size: 0.875em;
101+
line-height: 2;
102+
margin: 1rem 0 2rem;
103+
max-width: calc(100% - 3rem);
104+
padding: 2px 8px;
105+
position: relative;
106+
text-align: left;
107+
width: 650px;
108+
}
109+
110+
.color-output-rgb::after,
111+
.color-output-p3::after {
112+
background-color: var(--color);
113+
border-radius: 50%;
114+
content: "";
115+
display: inline-block;
116+
height: calc(0.875em * 2);
117+
position: absolute;
118+
right: calc(-1 * ((0.875em * 2) + 1rem));
119+
top: 2px;
120+
width: calc(0.875em * 2);
121+
}
122+
123+
#color-input-label {
124+
display: block;
125+
font-size: 0.875em;
126+
line-height: 2;
127+
margin: 1rem 0;
128+
max-width: 100%;
129+
padding: 2px 0;
130+
text-align: left;
131+
width: 450px;
132+
}
133+
</style>

0 commit comments

Comments
 (0)