HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-03-09
1 <p>Oct 25, 2025</p>
1 <p>Oct 25, 2025</p>
2 <p>We’re standing at the edge of a new, curious world - a world where you can define display logic<em>right inside CSS</em>. What used to require JavaScript yesterday now works natively, at the level of CSS itself.</p>
2 <p>We’re standing at the edge of a new, curious world - a world where you can define display logic<em>right inside CSS</em>. What used to require JavaScript yesterday now works natively, at the level of CSS itself.</p>
3 <h2>Why it matters</h2>
3 <h2>Why it matters</h2>
4 <p>Modern interfaces are becoming increasingly reactive. A weather card might change its background depending on temperature. A chart could highlight segments based on live data. A form component might visually warn you when a limit is exceeded.</p>
4 <p>Modern interfaces are becoming increasingly reactive. A weather card might change its background depending on temperature. A chart could highlight segments based on live data. A form component might visually warn you when a limit is exceeded.</p>
5 <p>And all of this is logic we usually push to JavaScript:</p>
5 <p>And all of this is logic we usually push to JavaScript:</p>
6 if (temp &lt; 10) { element.classList.add('cold'); } else if (temp &lt; 25) { element.classList.add('mild'); } else { element.classList.add('warm'); }<p>But if you think about it - this is just a condition that affects<strong>visual appearance</strong>. So why not let CSS itself handle it?</p>
6 if (temp &lt; 10) { element.classList.add('cold'); } else if (temp &lt; 25) { element.classList.add('mild'); } else { element.classList.add('warm'); }<p>But if you think about it - this is just a condition that affects<strong>visual appearance</strong>. So why not let CSS itself handle it?</p>
7 <p>Imagine a component that receives variables like --temp, --limit, or --progress, and decides how to look - all on its own, without a single line of JS.</p>
7 <p>Imagine a component that receives variables like --temp, --limit, or --progress, and decides how to look - all on its own, without a single line of JS.</p>
8 <h2>Can CSS variables be compared? Yes, they can!</h2>
8 <h2>Can CSS variables be compared? Yes, they can!</h2>
9 <p>Surprisingly -<strong>yes</strong>. And not just compared statically, but<em>dynamically</em>, in response to user interaction. Here’s a small example.</p>
9 <p>Surprisingly -<strong>yes</strong>. And not just compared statically, but<em>dynamically</em>, in response to user interaction. Here’s a small example.</p>
10 <p><strong>Important:</strong>right now it works only in Chrome.</p>
10 <p><strong>Important:</strong>right now it works only in Chrome.</p>
11 <p>In this snippet, the block reacts to two CSS variables, --x and --y. When you hover over it, the values change - and so does its appearance.</p>
11 <p>In this snippet, the block reacts to two CSS variables, --x and --y. When you hover over it, the values change - and so does its appearance.</p>
12 .comparison { --x: 100px; --y: 120px; } .comparison:hover { --x: 140px; --y: 120px; }<p>On hover, the background updates instantly - with no JavaScript involved. This isn’t a trick. It’s<strong>real value comparison</strong>happening directly in CSS.</p>
12 .comparison { --x: 100px; --y: 120px; } .comparison:hover { --x: 140px; --y: 120px; }<p>On hover, the background updates instantly - with no JavaScript involved. This isn’t a trick. It’s<strong>real value comparison</strong>happening directly in CSS.</p>
13 <p>A full walkthrough of the technique is available in the step-by-step<a>interactive demo</a>- make sure to check it out after reading the article.</p>
13 <p>A full walkthrough of the technique is available in the step-by-step<a>interactive demo</a>- make sure to check it out after reading the article.</p>
14 <h2>Why a special trick is needed</h2>
14 <h2>Why a special trick is needed</h2>
15 <p>So, why don’t developers use CSS comparisons everywhere? It’s not even about browser support - it’s about the limitations of the core technology.</p>
15 <p>So, why don’t developers use CSS comparisons everywhere? It’s not even about browser support - it’s about the limitations of the core technology.</p>
16 <p>The key player here is <strong>container style queries</strong>. They let you write things like:</p>
16 <p>The key player here is <strong>container style queries</strong>. They let you write things like:</p>
17 @container style(--theme: dark) { ... }<p>But here’s the catch - these queries can only check<strong>for exact matches</strong>. They can tell if a variable equals a certain value, but that’s it. No &gt;, &lt;, or expressions like --temp &gt; --max-temp - not yet.</p>
17 @container style(--theme: dark) { ... }<p>But here’s the catch - these queries can only check<strong>for exact matches</strong>. They can tell if a variable equals a certain value, but that’s it. No &gt;, &lt;, or expressions like --temp &gt; --max-temp - not yet.</p>
18 <p>So if you want<em>true comparisons</em>, you need a little creativity.</p>
18 <p>So if you want<em>true comparisons</em>, you need a little creativity.</p>
19 <h2>How the trick works: three possible outcomes</h2>
19 <h2>How the trick works: three possible outcomes</h2>
20 <p>If you look closer, the limitation isn’t fatal. Style queries can only check equality, but a numerical comparison always has just<strong>three possible results</strong>:</p>
20 <p>If you look closer, the limitation isn’t fatal. Style queries can only check equality, but a numerical comparison always has just<strong>three possible results</strong>:</p>
21 <ol><li>less than,</li>
21 <ol><li>less than,</li>
22 <li>equal,</li>
22 <li>equal,</li>
23 <li>greater than.</li>
23 <li>greater than.</li>
24 </ol><p>Can we map all possible outcomes to just these three? Absolutely!</p>
24 </ol><p>Can we map all possible outcomes to just these three? Absolutely!</p>
25 <p>The key operation is ridiculously simple -<strong>subtraction</strong>. If you subtract one value from another, the result will always be:</p>
25 <p>The key operation is ridiculously simple -<strong>subtraction</strong>. If you subtract one value from another, the result will always be:</p>
26 <ul><li>negative - if the first value is smaller,</li>
26 <ul><li>negative - if the first value is smaller,</li>
27 <li>zero - if they’re equal,</li>
27 <li>zero - if they’re equal,</li>
28 <li>positive - if the first value is larger.</li>
28 <li>positive - if the first value is larger.</li>
29 </ul><p>We don’t really care about the exact number - only its<strong>sign</strong>. That sign tells us which side is bigger.</p>
29 </ul><p>We don’t really care about the exact number - only its<strong>sign</strong>. That sign tells us which side is bigger.</p>
30 <p>And this is exactly what the new sign() function does. It returns -1, 0, or 1.</p>
30 <p>And this is exactly what the new sign() function does. It returns -1, 0, or 1.</p>
31 <p>So we end up with a neat, universal expression:</p>
31 <p>So we end up with a neat, universal expression:</p>
32 --sign: sign(var(--x) - var(--y));<p>Now the variable --sign holds everything CSS needs to know about the comparison:</p>
32 --sign: sign(var(--x) - var(--y));<p>Now the variable --sign holds everything CSS needs to know about the comparison:</p>
33 <ul><li>-1 if --x is less than --y,</li>
33 <ul><li>-1 if --x is less than --y,</li>
34 <li>0 if they’re equal,</li>
34 <li>0 if they’re equal,</li>
35 <li>1 if --x is greater than --y.</li>
35 <li>1 if --x is greater than --y.</li>
36 </ul><p>Three outcomes - three states. That’s all we need to build conditional logic right in CSS.</p>
36 </ul><p>Three outcomes - three states. That’s all we need to build conditional logic right in CSS.</p>
37 <p>From here on, we can use this value anywhere - inside an if() function or an @container query.</p>
37 <p>From here on, we can use this value anywhere - inside an if() function or an @container query.</p>
38 <h2>Step-by-step implementation</h2>
38 <h2>Step-by-step implementation</h2>
39 <h3>Step 1. Define the variables</h3>
39 <h3>Step 1. Define the variables</h3>
40 .comparison:nth-child(1) { --x: 100px; --y: 120px; } .comparison:nth-child(2) { --x: 100px; --y: 100px; } .comparison:nth-child(3) { --x: 200px; --y: 100px; }<h3>Step 2. Register the variable --sign</h3>
40 .comparison:nth-child(1) { --x: 100px; --y: 120px; } .comparison:nth-child(2) { --x: 100px; --y: 100px; } .comparison:nth-child(3) { --x: 200px; --y: 100px; }<h3>Step 2. Register the variable --sign</h3>
41 <p>Registration ensures the browser treats --sign as a number and evaluates it right away.</p>
41 <p>Registration ensures the browser treats --sign as a number and evaluates it right away.</p>
42 @property --sign { inherits: true; initial-value: 0; syntax: ""; }<h3>Step 3. Compute the sign</h3>
42 @property --sign { inherits: true; initial-value: 0; syntax: ""; }<h3>Step 3. Compute the sign</h3>
43 .comparison { --sign: sign(var(--x) - var(--y)); }<h3>Step 4. React to the result</h3>
43 .comparison { --sign: sign(var(--x) - var(--y)); }<h3>Step 4. React to the result</h3>
44 <p>Using the new if() function:</p>
44 <p>Using the new if() function:</p>
45 .comparison { --sign: sign(var(--x) - var(--y)); background-color: if( style(--sign: -1): coral; style(--sign: 1): lightgreen; else: lightgray; ); }<p>Or via container queries:</p>
45 .comparison { --sign: sign(var(--x) - var(--y)); background-color: if( style(--sign: -1): coral; style(--sign: 1): lightgreen; else: lightgray; ); }<p>Or via container queries:</p>
46 @container style(--sign: -1) { .comparison-result { background-color: coral; } } @container style(--sign: 0) { .comparison-result { background-color: lightgray; } } @container style(--sign: 1) { .comparison-result { background-color: lightgreen; } }<p>With container queries, the comparison is computed on the parent, and the styles are applied to a nested element.</p>
46 @container style(--sign: -1) { .comparison-result { background-color: coral; } } @container style(--sign: 0) { .comparison-result { background-color: lightgray; } } @container style(--sign: 1) { .comparison-result { background-color: lightgreen; } }<p>With container queries, the comparison is computed on the parent, and the styles are applied to a nested element.</p>
47 <p>Either way,<strong>pure CSS</strong>decides what styles to apply based on variable values.</p>
47 <p>Either way,<strong>pure CSS</strong>decides what styles to apply based on variable values.</p>
48 <h2>Wrapping up</h2>
48 <h2>Wrapping up</h2>
49 <p>The tiny expression sign(var(--x) - var(--y)) turns the impossible into possible.</p>
49 <p>The tiny expression sign(var(--x) - var(--y)) turns the impossible into possible.</p>
50 <p>We’ve got a universal way to encode a comparison result into a single variable - and then use it anywhere: inside @container or if().</p>
50 <p>We’ve got a universal way to encode a comparison result into a single variable - and then use it anywhere: inside @container or if().</p>
51 <p>CSS is no longer a passive styling language. It can now<em>make decisions</em>based on its own variables and conditional logic, dynamically adjusting the appearance of elements.</p>
51 <p>CSS is no longer a passive styling language. It can now<em>make decisions</em>based on its own variables and conditional logic, dynamically adjusting the appearance of elements.</p>
52 <p>And while this currently works only in Chrome, the Pandora’s box is already open - CSS has started to think.</p>
52 <p>And while this currently works only in Chrome, the Pandora’s box is already open - CSS has started to think.</p>