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 < 10) { element.classList.add('cold'); } else if (temp < 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 < 10) { element.classList.add('cold'); } else if (temp < 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 >, <, or expressions like --temp > --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 >, <, or expressions like --temp > --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>