<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: FSCSS tutorial</title>
    <description>The latest articles on DEV Community by FSCSS tutorial (fscss).</description>
    <link>https://dev.to/fscss</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F10079%2F03f5d662-652b-4b9a-be33-c148848119c2.jpg</url>
      <title>DEV Community: FSCSS tutorial</title>
      <link>https://dev.to/fscss</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fscss"/>
    <language>en</language>
    <item>
      <title>Building Circular UI with circle-progress.fscss (No JavaScript)</title>
      <dc:creator>FSCSS tutorial</dc:creator>
      <pubDate>Sun, 13 Sep 2026 22:07:52 +0000</pubDate>
      <link>https://dev.to/fscss/building-circular-ui-with-circle-progressfscss-no-javascript-1mp2</link>
      <guid>https://dev.to/fscss/building-circular-ui-with-circle-progressfscss-no-javascript-1mp2</guid>
      <description>&lt;p&gt;Circular progress, pie charts, and step rings usually mean SVG path math or a chart library.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;circle-progress.fscss&lt;/strong&gt; does it with pure CSS — &lt;code&gt;conic-gradient&lt;/code&gt;, masks, and FSCSS &lt;code&gt;@define&lt;/code&gt; helpers.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/Figsh/Circle-progress.fscss" rel="noopener noreferrer"&gt;Figsh/Circle-progress.fscss&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frz3lsz9rf7jgowpv39yi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frz3lsz9rf7jgowpv39yi.jpg" alt="Showcase grid — ring, pie, steps, nested" width="720" height="414"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  What you get
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Define&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Progress ring&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@circle-progress&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Solid pie&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@circle-pie&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-slice pie&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@circle-pie-multi&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Steps ring&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@circle-steps&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nested rings&lt;/td&gt;
&lt;td&gt;Compose by nesting elements&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All driven by CSS variables. Change &lt;code&gt;--progress-value&lt;/code&gt; and the arc follows.&lt;/p&gt;


&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Option A — runtime (quick / prototyping)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/fscss@1.2.1/runtime.min.js"&lt;/span&gt; &lt;span class="na"&gt;defer&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Option B — CLI compile (production)&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;It works well with &lt;a href="https://marketplace.visualstudio.com/items?itemName=Figsh.fscss" rel="noopener noreferrer"&gt;FSCSS vscode extention&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; fscss
fscss styles.fscss styles.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Import the module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;circle-progress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;progress-root&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;circle-progress&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;progress-circle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full sample page:&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/Figsh/Circle-progress.fscss/blob/main/samples/example.html" rel="noopener noreferrer"&gt;samples/example.html&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  1. Progress ring
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F43dc5bwja5ldbt7yis05.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F43dc5bwja5ldbt7yis05.jpg" alt="Green 72% progress ring" width="720" height="637"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"progress-circle p72"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;72%&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.p72&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="err"&gt;@progress-range(72)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under the hood: a &lt;code&gt;conic-gradient&lt;/code&gt; draws the arc, a radial mask cuts the hole, and a small tip marker rotates with the value.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Color override
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9e5xbpbcarjtrjn0h0br.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9e5xbpbcarjtrjn0h0br.jpg" alt="Blue 41% ring" width="719" height="639"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.p41&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@progress-range(41)&lt;/span&gt;
  &lt;span class="py"&gt;--progress-color-arc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#4d9fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--progress-color-glow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;77&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;159&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.45&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same component — only tokens change.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft6eces17fgkyzl7id426.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft6eces17fgkyzl7id426.jpg" alt="Amber 88% ring" width="720" height="655"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.p88&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@progress-range(88)&lt;/span&gt;
  &lt;span class="py"&gt;--progress-color-arc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffb830&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--progress-color-glow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;184&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;48&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Pie slice
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi9mt9em98gd229stqrxd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi9mt9em98gd229stqrxd.jpg" alt="Solid 30% pie" width="720" height="625"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"circle-pie p30"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;30%&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@circle-pie&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;circle-pie&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;p30&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;@progress-range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;--progress-color-arc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ff5070&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No mask — the conic fill is the whole disk.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Multi pie
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0ibfr399ht6371e5q17k.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0ibfr399ht6371e5q17k.jpg" alt="4-slice multi pie" width="720" height="654"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"circle-pie-multi pie-a"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@circle-pie-multi&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;circle-pie-multi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pie-a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--pie-a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--pie-b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;25&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--pie-c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--pie-d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Four slices from four percentage tokens.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Steps ring
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fveytg7weyg71c4odptab.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fveytg7weyg71c4odptab.jpg" alt="Steps 5/8" width="720" height="628"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"circle-steps steps-5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;5/8&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@circle-steps&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;circle-steps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;steps-5&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;@steps-done&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;steps-total&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqq3gueu5ktt2ok5jhipf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqq3gueu5ktt2ok5jhipf.jpg" alt="Steps 3/6 violet" width="720" height="668"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.steps-3&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@steps-done(3)&lt;/span&gt;
  &lt;span class="err"&gt;@steps-total(6)&lt;/span&gt;
  &lt;span class="py"&gt;--progress-color-arc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#9d7eff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6. Nested rings
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F78r9inutlh8frrhsw3rt.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F78r9inutlh8frrhsw3rt.jpg" alt="Nested green outer + blue inner" width="720" height="694"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"progress-circle p72"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"--progress-size:200px"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"progress-circle p41"&lt;/span&gt;
       &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"--progress-size:120px;--progress-stroke:10px"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    41
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same define, different size/stroke on the child — composition without new APIs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Mental model
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Tokens&lt;/strong&gt; — &lt;code&gt;@progress-root()&lt;/code&gt; sets size, stroke, colors, value.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shape&lt;/strong&gt; — one &lt;code&gt;@define&lt;/code&gt; per pattern (ring, pie, steps).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Value&lt;/strong&gt; — &lt;code&gt;@progress-range(n)&lt;/code&gt; or &lt;code&gt;--progress-value&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Theme&lt;/strong&gt; — override &lt;code&gt;--progress-color-arc&lt;/code&gt; / &lt;code&gt;--progress-color-glow&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No SVG paths. No chart library. Change a variable, the circle updates.&lt;/p&gt;




&lt;h2&gt;
  
  
  When to use runtime vs CLI
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use case&lt;/th&gt;
&lt;th&gt;Prefer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Demos, CodePen, quick tests&lt;/td&gt;
&lt;td&gt;CDN &lt;strong&gt;runtime&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Production, static deploy&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;CLI&lt;/strong&gt; compile to plain CSS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Runtime keeps FSCSS syntax in the page. CLI ships zero-runtime CSS.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Clone or copy from the repo and open the sample:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/Figsh/Circle-progress.fscss" rel="noopener noreferrer"&gt;github.com/Figsh/Circle-progress.fscss&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Sample: &lt;code&gt;samples/example.html&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Swap values, nest rings, add a pie — same module, different tokens.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built with FSCSS &lt;code&gt;@define&lt;/code&gt; · pure CSS circular UI&lt;/em&gt;&lt;/p&gt;

</description>
      <category>fscss</category>
      <category>tutorial</category>
      <category>showdev</category>
      <category>sharepoint</category>
    </item>
    <item>
      <title>Styling Deeply Nested divs with One FSCSS Array Loop (No More Hand-Writing Selectors)</title>
      <dc:creator>FSCSS tutorial</dc:creator>
      <pubDate>Fri, 11 Sep 2026 17:08:54 +0000</pubDate>
      <link>https://dev.to/fscss/styling-deeply-nested-divs-with-one-fscss-array-loop-no-more-hand-writing-selectors-3i08</link>
      <guid>https://dev.to/fscss/styling-deeply-nested-divs-with-one-fscss-array-loop-no-more-hand-writing-selectors-3i08</guid>
      <description>&lt;p&gt;Writing nested selectors by hand is painful.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;orange&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;purple&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;indigo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;/* …and it gets worse the deeper you go */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;FSCSS gives us a clean way to generate the entire chain in a single loop using &lt;code&gt;@arr&lt;/code&gt; + &lt;code&gt;rpt()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;You have a simple nested structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;1
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;2
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;3&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You want each level to have a different background color (and maybe padding, border-radius, etc.) without writing the selectors manually.&lt;/p&gt;

&lt;h3&gt;
  
  
  The One-Loop Solution
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/fscss@1.2.0/runtime.min.js"&lt;/span&gt; &lt;span class="na"&gt;async&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;@arr&lt;/span&gt; &lt;span class="n"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;orange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;purple&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;indigo&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;          &lt;span class="c"&gt;/* → 1, 2, 3 */&lt;/span&gt;

&lt;span class="n"&gt;rpt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="s1"&gt;"div "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;      &lt;span class="c"&gt;/* builds "div ", "div div ", "div div div " */&lt;/span&gt;
  &lt;span class="nt"&gt;background&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;@arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;[]];&lt;/span&gt;
  &lt;span class="nt"&gt;padding&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;10&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="nt"&gt;border-radius&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;10&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="nt"&gt;color&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;#fff&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="nt"&gt;margin&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;8&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Gets Generated
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;orange&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;purple&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c"&gt;/* same properties */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;indigo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c"&gt;/* same properties */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;@arr levels[count(3, 1)]&lt;/code&gt; creates the numbers &lt;code&gt;1, 2, 3&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rpt(@arr.levels[], "div ")&lt;/code&gt; repeats the string &lt;code&gt;"div "&lt;/code&gt; according to the current level.&lt;/li&gt;
&lt;li&gt;Inside the rule, &lt;code&gt;@arr.colors[@arr.levels[]]&lt;/code&gt; picks the matching color (arrays are 1-indexed).&lt;/li&gt;
&lt;li&gt;FSCSS expands the whole block once for every item in the array — one clean loop.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Easy Variations
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Change depth&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Just update the &lt;code&gt;count()&lt;/code&gt; and the colors array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@arr colors[tomato, coral, salmon, crimson]
@arr levels[count(4, 1)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use child combinator instead of descendant&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rpt(@arr.levels[], "div &amp;gt; ") {
  /* now generates div &amp;gt;, div &amp;gt; div &amp;gt;, etc. */
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Add more properties or even different values per level&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
You can reference the level index for anything — font-size, opacity, animation-delay, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why This Feels Good
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Zero repetitive typing
&lt;/li&gt;
&lt;li&gt;Depth and colors stay in sync
&lt;/li&gt;
&lt;li&gt;Still pure CSS after compilation
&lt;/li&gt;
&lt;li&gt;Works with the browser runtime or the CLI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hand-writing nested selectors used to be a small but annoying chore. With FSCSS arrays + &lt;code&gt;rpt()&lt;/code&gt;, it becomes a one-liner pattern you can reuse anytime.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Full:&lt;/em&gt; &lt;a href="https://fscss.devtem.org/nested-loop" rel="noopener noreferrer"&gt;https://fscss.devtem.org/nested-loop&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Building an FSCSS Module: How Easy Is It, Really?</title>
      <dc:creator>FSCSS </dc:creator>
      <pubDate>Tue, 08 Sep 2026 23:05:31 +0000</pubDate>
      <link>https://dev.to/fscss/building-an-fscss-module-how-easy-is-it-really-2a5c</link>
      <guid>https://dev.to/fscss/building-an-fscss-module-how-easy-is-it-really-2a5c</guid>
      <description>&lt;p&gt;Building a basic FSCSS module is relatively easy, especially if you already know CSS and the core FSCSS syntax (&lt;code&gt;@define&lt;/code&gt;, arrays/&lt;code&gt;@arr&lt;/code&gt;, &lt;code&gt;@use&lt;/code&gt;, imports). Getting to a polished, reusable visual component takes a bit more care to avoid a few silent pitfalls, but the ecosystem provides clear patterns and a checklist that make the whole process approachable.&lt;/p&gt;

&lt;h3&gt;
  
  
  What an FSCSS Module Is
&lt;/h3&gt;

&lt;p&gt;FSCSS (Figured Shorthand Cascading Style Sheets) is a lightweight CSS preprocessor. A module is essentially a &lt;code&gt;.fscss&lt;/code&gt; file containing reusable style generators defined with &lt;code&gt;@define&lt;/code&gt;, think of them as mixins, macros, or functions. Nothing runs automatically on import. You explicitly call the definitions you want. This keeps output small and gives you full control over what actually compiles.&lt;/p&gt;

&lt;p&gt;Here's a simple utility module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@define&lt;/span&gt; &lt;span class="n"&gt;radius-util&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;
  &lt;span class="nc"&gt;.radius-0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;@arr&lt;/span&gt; &lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;radius-&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="nb"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Import and use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;radius-util&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;"./spacing-utils.fscss"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;radius-util&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's enough to generate hundreds of utility classes with very little code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recommended Structure for Solid Modules
&lt;/h3&gt;

&lt;p&gt;Existing modules, along with the official write-up on converting raw CSS components into modules, converge on the same shape:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Root tokens mixin.&lt;/strong&gt; One &lt;code&gt;@define&lt;/code&gt; that writes the needed CSS custom properties, usually onto &lt;code&gt;:root&lt;/code&gt; or a scoped selector. Call it once, first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scoped base/reset.&lt;/strong&gt; Tied to the component's own selector, never a bare global &lt;code&gt;*&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structural mixins.&lt;/strong&gt; One per visual piece, each taking a selector parameter so it stays reusable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One-call preset/composite.&lt;/strong&gt; Wires the pieces together for the common case while leaving the individual mixins available on their own.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  How Easy Is It in Practice?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Basic utilities and generators:&lt;/strong&gt; very easy. Arrays plus &lt;code&gt;@define&lt;/code&gt; let you produce large sets of classes in a few lines.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Component-style modules&lt;/strong&gt; (charts, forms, animated waves, and similar): still straightforward once you follow the patterns, but the compiler is often silent on mistakes. The common gotchas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accidentally nesting selectors so styles compile but never match anything.&lt;/li&gt;
&lt;li&gt;Declaring a parameter that's never referenced with &lt;code&gt;@use(...)&lt;/code&gt;, which quietly becomes a no-op.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;count()&lt;/code&gt; needing a literal number at compile time, not an expression.&lt;/li&gt;
&lt;li&gt;Missing module-specific prefixes on keyframes or custom properties, which causes collisions later when multiple modules share a page.&lt;/li&gt;
&lt;li&gt;Loops needing the array reference in selector position, followed by a block, to actually trigger.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A useful debugging habit here: drop &lt;code&gt;exec(_log, "message")&lt;/code&gt; around expansions to see exactly what the compiler produced.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where This Comes From
&lt;/h3&gt;

&lt;p&gt;There's an official experience write-up and checklist covering exactly these points, rooted in the process of turning real CSS components into &lt;code&gt;siri-wave.fscss&lt;/code&gt; and &lt;code&gt;flux-wave.fscss&lt;/code&gt;. Following existing modules alongside that checklist makes the process repeatable and low-friction, instead of re-debugging the same issues from scratch each time.&lt;/p&gt;




&lt;p&gt;If you're comfortable writing CSS and willing to study one or two existing modules plus the modular system docs, building a useful FSCSS module is easy for simple cases and only moderately more involved for polished, shareable ones. The design deliberately favors small, composable, on-demand generators over heavy monolithic stylesheets, and the import system makes sharing and reusing modules simple.&lt;/p&gt;

&lt;p&gt;write-up: &lt;a href="https://fscss.devtem.org/building-fscss-modules" rel="noopener noreferrer"&gt;fscss.devtem.org/building-fscss-modules&lt;/a&gt;&lt;/p&gt;

</description>
      <category>fscss</category>
      <category>opensource</category>
      <category>modules</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>FSCSS Array Loops: Generating Repeated CSS Rules with @arr</title>
      <dc:creator>FSCSS tutorial</dc:creator>
      <pubDate>Tue, 08 Sep 2026 15:00:09 +0000</pubDate>
      <link>https://dev.to/fscss/fscss-array-loops-generating-repeated-css-rules-with-arr-3c32</link>
      <guid>https://dev.to/fscss/fscss-array-loops-generating-repeated-css-rules-with-arr-3c32</guid>
      <description>&lt;p&gt;One of the most useful tools in FSCSS for cutting down repetitive CSS is the array system. Arrays let you store ordered lists of values and expand them into repeated rules automatically, instead of writing five or six nearly identical blocks by hand.&lt;/p&gt;

&lt;p&gt;This post walks through how &lt;code&gt;@arr&lt;/code&gt; works, how the loop trigger behaves, and the pattern used in real FSCSS modules like &lt;code&gt;siri-wave.fscss&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Declaring Arrays
&lt;/h3&gt;

&lt;p&gt;Arrays in FSCSS are 1-indexed and string-native. The first item is &lt;code&gt;[1]&lt;/code&gt;, not &lt;code&gt;[0]&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@arr colors[magenta, cyan, green, purple, orange, blue]
@arr delays[0.1s, 0.25s, 0.45s, 0.15s, 0.35s, 0.55s]
@arr indexes[count(6,1)]   /* generates 1,2,3,4,5,6 */
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;count(n, start)&lt;/code&gt; is the standard way to generate a numeric index array. You can also declare literal lists of any CSS value type: colors, sizes, times, strings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accessing Individual Items
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;background: @arr.colors[1];      /* magenta */
animation-delay: @arr.delays[3]; /* 0.45s */
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Loop Trigger: Empty Brackets
&lt;/h3&gt;

&lt;p&gt;The core feature is the empty bracket syntax, &lt;code&gt;@arr.name[]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When FSCSS sees &lt;code&gt;@arr.name[]&lt;/code&gt; inside a selector that's followed by a block, it expands the rule once for every item in the array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@arr delays[0.1s, 0.3s, 0.5s]
@arr colors[#ef4444, #f59e0b, #10b981]
@arr indexes[count(3,1)]

.loading-dot:nth-child(@arr.indexes[]) {
  animation-delay: @arr.delays[@arr.indexes[]];
  background: @arr.colors[@arr.indexes[]];
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This compiles to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.loading-dot&lt;/span&gt;&lt;span class="nd"&gt;:nth-child&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;animation-delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.1s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ef4444&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.loading-dot&lt;/span&gt;&lt;span class="nd"&gt;:nth-child&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;animation-delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.3s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#f59e0b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.loading-dot&lt;/span&gt;&lt;span class="nd"&gt;:nth-child&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;animation-delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#10b981&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  A Real Example: siri-wave.fscss
&lt;/h3&gt;

&lt;p&gt;Here's the pattern as it's actually used in &lt;a href="https://github.com/Koolkidkonrad/siri-wave.fscss" rel="noopener noreferrer"&gt;siri-wave.fscss&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@define siri-blob-colors(st:.blob){`
  @arr siri-colors[magenta, cyan, green, purple, orange, blue]
  @arr siri-colors-i[count(6,1)] 

  @siri-blob-variant(@use(st).@arr.siri-colors[@arr.siri-colors-i[]], @arr.siri-colors[@arr.siri-colors-i[]])

  @use(st){
    /* Need a block to trigger the loop */
    --siri-loop-index: @arr.siri-colors-i[];
  }
`}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Breaking down what happens:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Two parallel arrays are declared: one for values, one for indexes.&lt;/li&gt;
&lt;li&gt;The empty &lt;code&gt;[]&lt;/code&gt; sits inside a selector/argument that's followed by a block.&lt;/li&gt;
&lt;li&gt;FSCSS expands the whole statement six times, once per index.&lt;/li&gt;
&lt;li&gt;Each expansion calls &lt;code&gt;@siri-blob-variant&lt;/code&gt; with the matching color name, producing &lt;code&gt;.blob.magenta&lt;/code&gt;, &lt;code&gt;.blob.cyan&lt;/code&gt;, and so on.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This index-array-plus-parallel-values pattern is the recommended way to generate multiple variants cleanly, without writing each variant out by hand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rules for Reliable Looping
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@arr.name[]&lt;/code&gt; must appear in a &lt;strong&gt;selector position followed by a &lt;code&gt;{ }&lt;/code&gt; block&lt;/strong&gt;. A bare reference inside a mixin argument alone won't trigger the loop reliably.&lt;/li&gt;
&lt;li&gt;Prefer an explicit index array (&lt;code&gt;count(n,1)&lt;/code&gt;) whenever you need to index into other arrays.&lt;/li&gt;
&lt;li&gt;Arrays are expanded entirely at compile time. The output is plain CSS, with no runtime array logic left behind.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Array Methods
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.length&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Number of items&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@arr.colors!.length&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;.first&lt;/code&gt; / &lt;code&gt;.last&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;First / last item&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@arr.colors!.first&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.list&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Comma-separated list&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@arr.colors!.list&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.join(sep)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Join with custom separator&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@arr.colors!.join(+)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.reverse&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Reversed list&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@arr.colors!.reverse&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.shuffle&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Random order&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@arr.colors!.shuffle&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.indices&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1-based index list&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@arr.colors!.indices&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.randint&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;One random value for the compile&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@arr.colors!.randint&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Short list&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The Mental Model
&lt;/h3&gt;

&lt;p&gt;Think of &lt;code&gt;@arr.name[]&lt;/code&gt; as "for each item in this array, generate a rule." That's the entire mechanism behind the six colored blobs in siri-wave, generated without writing six almost-identical blocks by hand.&lt;/p&gt;




&lt;p&gt;FSCSS isn't just a different syntax for writing CSS. It's growing into an ecosystem of reusable libraries, tools, and resources meant to make modern web development faster and less repetitive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The siri-wave repo: &lt;a href="https://github.com/Koolkidkonrad/siri-wave.fscss" rel="noopener noreferrer"&gt;siri-wave.fscss on GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>fscss</category>
      <category>css</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>st-core.fscss: a chart and dashboard UI kit built entirely in CSS mixins</title>
      <dc:creator>FSCSS tutorial</dc:creator>
      <pubDate>Sat, 05 Sep 2026 23:19:55 +0000</pubDate>
      <link>https://dev.to/fscss/st-corefscss-a-chart-and-dashboard-ui-kit-built-entirely-in-css-mixins-2mb3</link>
      <guid>https://dev.to/fscss/st-corefscss-a-chart-and-dashboard-ui-kit-built-entirely-in-css-mixins-2mb3</guid>
      <description>&lt;p&gt;Most chart libraries hand you a JavaScript API and a bundle size to worry about. st-core.fscss takes a different route: it's a set of FSCSS mixins that compile straight to CSS, no JavaScript required to render a chart, a stat card, or a progress bar.&lt;/p&gt;

&lt;p&gt;It's open source, and the whole thing lives in one readable source file.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it can do right now
&lt;/h2&gt;

&lt;p&gt;st-core.fscss covers the pieces you'd actually reach for on a dashboard or analytics screen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Line and area charts&lt;/strong&gt;, drawn with &lt;code&gt;clip-path: polygon()&lt;/code&gt; against eight data points&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data dots&lt;/strong&gt; placed along the line, generated automatically from an array so you don't write eight separate rules by hand&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A background grid and axis labels&lt;/strong&gt;, sized to match your data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stat cards&lt;/strong&gt;, with label, value, and an up/down delta built in&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Progress bars&lt;/strong&gt;, driven by a single custom property so the fill can be updated later without touching the markup&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A device-frame container&lt;/strong&gt;, if you want the whole thing to look like it's sitting inside a phone mockup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything reads from one shared design-token set, colors, radii, spacing, chart defaults, so a single &lt;code&gt;st-root()&lt;/code&gt; call at the top of your stylesheet themes the whole kit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it's built this way
&lt;/h2&gt;

&lt;p&gt;Every piece is a plain &lt;code&gt;@define&lt;/code&gt; mixin. Call &lt;code&gt;st-chart-points(68, 59, 70, 35, 58, 22, 42, 55)&lt;/code&gt; with your real numbers, call &lt;code&gt;st-chart-line()&lt;/code&gt; and &lt;code&gt;st-chart-fill()&lt;/code&gt;, and you have a working chart, no chart.js, no canvas, no re-render logic. Update the data later by calling &lt;code&gt;st-chart-points()&lt;/code&gt; again with new numbers, and every dot, line, and fill shifts to match.&lt;/p&gt;

&lt;p&gt;That's the appeal for a dev workflow: you're writing CSS-shaped code the whole time. Nothing to import beyond FSCSS itself, nothing to configure beyond the parameters you pass.&lt;/p&gt;

&lt;h2&gt;
  
  
  Syntax highlighting
&lt;/h2&gt;

&lt;p&gt;If &lt;code&gt;@define&lt;/code&gt;, &lt;code&gt;@use()&lt;/code&gt;, and &lt;code&gt;@arr&lt;/code&gt; look unfamiliar in an editor with no idea what FSCSS is, the FSCSS &lt;a href="https://marketplace.visualstudio.com/items?itemName=Figsh.fscss" rel="noopener noreferrer"&gt;VS Code extension&lt;/a&gt; fixes that. It adds proper syntax highlighting and snippets for FSCSS files, so reading or writing st-core.fscss mixins looks like reading CSS, not a wall of unhighlighted text. Worth installing before you open the source for the first time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to start
&lt;/h2&gt;

&lt;p&gt;The repo itself is short enough to read start to finish in one sitting, and there's a companion explainer walking through what every mixin does and why, mixin by mixin, if you'd rather understand the mechanics before you start calling them. Both beginners picking up FSCSS for the first time and developers who already know the compiler should be able to get a chart on screen within a few minutes either way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Repo: &lt;a href="https://github.com/fscss-ttr/st-core.fscss" rel="noopener noreferrer"&gt;github.com/fscss-ttr/st-core.fscss&lt;/a&gt;
&lt;/h3&gt;

</description>
      <category>css</category>
      <category>fscss</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>FSCSS v1.2.0 is out: two clean entry points, full backward compatibility, and inline styles that actually compile</title>
      <dc:creator>FSCSS tutorial</dc:creator>
      <pubDate>Fri, 04 Sep 2026 23:55:28 +0000</pubDate>
      <link>https://dev.to/fscss/fscss-v120-is-out-two-clean-entry-points-full-backward-compatibility-and-inline-styles-that-34ff</link>
      <guid>https://dev.to/fscss/fscss-v120-is-out-two-clean-entry-points-full-backward-compatibility-and-inline-styles-that-34ff</guid>
      <description>&lt;p&gt;FSCSS is open source, built in the open, and free for anyone to use, extend, or pick apart. That's the whole point of it. Every release is meant to make it easier for other developers to build with, not harder. v1.2.0 is the clearest example of that yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  What shipped
&lt;/h2&gt;

&lt;p&gt;Previous versions of FSCSS scattered their browser-facing files across the package: &lt;code&gt;/e/exec.js&lt;/code&gt;, &lt;code&gt;/exec.js&lt;/code&gt;, &lt;code&gt;/xfscss.js&lt;/code&gt;, &lt;code&gt;/xfscss.min.js&lt;/code&gt;, and more. Depending on what you needed, you'd end up guessing which file was the right one to load.&lt;/p&gt;

&lt;p&gt;v1.2.0 consolidates all of that into two public entry points:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Auto-run, for plain HTML pages --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/fscss@1.2.0/runtime.min.js"&lt;/span&gt; &lt;span class="na"&gt;async&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Manual control, for tooling and modules&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;xfscss&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://cdn.jsdelivr.net/npm/fscss@1.2.0/esm.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;runtime.js&lt;/code&gt; auto-scans the page and compiles everything on load, &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; blocks, &lt;code&gt;&amp;lt;link type="fscss"&amp;gt;&lt;/code&gt; sources, and now inline &lt;code&gt;style&lt;/code&gt; attributes too. &lt;code&gt;esm.js&lt;/code&gt; never auto-runs and never touches page loading, since it's meant for using FSCSS as a tool: an FSCSS-to-CSS converter, a build step, or any pipeline where you decide what gets processed and when.&lt;/p&gt;

&lt;p&gt;Use one or the other. Never both.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nothing breaks
&lt;/h2&gt;

&lt;p&gt;This is the part worth repeating: the npm package and CLI are completely unchanged, and every method that worked in the 1.1.x line still works exactly the same way in 1.2.0. &lt;code&gt;@define&lt;/code&gt;, &lt;code&gt;@fun&lt;/code&gt;, &lt;code&gt;@event&lt;/code&gt;, &lt;code&gt;@arr&lt;/code&gt;, &lt;code&gt;pattern()&lt;/code&gt;, all of it. The consolidation only touches the browser entry-point files. If you're compiling ahead of time with the CLI, this release changes nothing for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inline styles now go through the full pipeline
&lt;/h2&gt;

&lt;p&gt;This is the headline feature. From v1.2.0, &lt;code&gt;style="..."&lt;/code&gt; attributes are compiled on boot the same way &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; blocks are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;@define&lt;/span&gt; &lt;span class="n"&gt;btn-style&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#636EE7&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;color-mix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;#dddddd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;25px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;700&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"@btn-style(#1a2a4f)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Search&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"@btn-style(#f00f00)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Search&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1ce8h199ai90jatcs9u4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1ce8h199ai90jatcs9u4.jpg" alt="FSCSS output" width="399" height="186"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Combined with &lt;code&gt;xfscss.process()&lt;/code&gt;, that means an inline mixin call can be recompiled at runtime and swapped straight back into the element, no rewritten CSS, no framework state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;update&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;btn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;xfscss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@btn-style(@arr.colors!.randint)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;btn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;style&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newStyle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full walkthrough of this: including a detail (method declared inline stay resolvable even after their declaration is cleaned out of the attribute), if you want to go deeper: &lt;a href="https://dev.to/figsh/fscss-v120-lets-you-write-mixins-directly-in-style-heres-why-thats-a-bigger-deal-than-2a31"&gt;FSCSS v1.2.0 lets you write mixins directly in style="..."&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters for an open-source tool
&lt;/h2&gt;

&lt;p&gt;None of this is about adding complexity for its own sake. FSCSS exists to cut down on repetitive CSS and give developers capabilities plain CSS doesn't have natively, and every release should make that easier to reach for, not harder to keep up with. Two entry points instead of a pile of internal files. Full compatibility instead of a migration guide. A feature that makes the JS API and the language work together instead of sitting side by side.&lt;/p&gt;

&lt;p&gt;Open source only stays useful if the people using it can trust an upgrade won't cost them a rewrite. That's the bar this release was held to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;fscss@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/fscss@1.2.0/runtime.min.js"&lt;/span&gt; &lt;span class="na"&gt;async&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Docs: &lt;a href="https://fscss.devtem.org/docs" rel="noopener noreferrer"&gt;fscss.devtem.org/docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;API reference: &lt;a href="https://fscss.devtem.org/api" rel="noopener noreferrer"&gt;fscss.devtem.org/api&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Inline styles: &lt;a href="https://fscss.devtem.org/inline" rel="noopener noreferrer"&gt;fscss.devtem.org/inline&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/Figsh/xfscss" rel="noopener noreferrer"&gt;github.com/Figsh/xfscss&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;NPM: &lt;a href="https://www.npmjs.com/package/fscss" rel="noopener noreferrer"&gt;npmjs.com/package/fscss&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bug reports, feature requests, and pull requests are all welcome on &lt;a href="https://github.com/Figsh/xfscss" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; &lt;/p&gt;

</description>
      <category>coding</category>
      <category>fscss</category>
      <category>css</category>
      <category>javascript</category>
    </item>
    <item>
      <title>FSCSS Component Architecture: A Modular, Composition-First Approach to CSS</title>
      <dc:creator>FSCSS tutorial</dc:creator>
      <pubDate>Thu, 03 Sep 2026 15:58:02 +0000</pubDate>
      <link>https://dev.to/fscss/fscss-component-architecture-a-modular-composition-first-approach-to-css-38n6</link>
      <guid>https://dev.to/fscss/fscss-component-architecture-a-modular-composition-first-approach-to-css-38n6</guid>
      <description>&lt;p&gt;FSCSS component architecture is built around a modular, composition-first model that compiles to plain CSS. It emphasizes reusable style units, design tokens, conditional logic, and selective imports—with almost no runtime JavaScript required for the final output. Components in FSCSS are treated as pure style definitions rather than framework-specific widgets, keeping stylesheets readable, highly reusable, and free of classic “mega-stylesheet” problems while still producing standard CSS that any browser understands.&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Building Blocks
&lt;/h3&gt;

&lt;p&gt;FSCSS provides a focused set of primitives for defining and composing styles:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Primitive&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;th&gt;Introduced / Key version&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;str(name, "…")&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Named blocks of CSS declarations&lt;/td&gt;
&lt;td&gt;Simple reusable style snippets&lt;/td&gt;
&lt;td&gt;Core&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;@fun(name){…}&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Key-value stores (design tokens)&lt;/td&gt;
&lt;td&gt;Spacing scales, color palettes, property groups&lt;/td&gt;
&lt;td&gt;Core&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;@define name(params)&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Parameterized mixins&lt;/td&gt;
&lt;td&gt;Themed components, variants, full structures&lt;/td&gt;
&lt;td&gt;1.1.15+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;pattern(threshold: "desc", "…")&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Semantic / fuzzy matching&lt;/td&gt;
&lt;td&gt;Natural-language style injection&lt;/td&gt;
&lt;td&gt;1.1.25+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;@event name(param)&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Conditional value functions&lt;/td&gt;
&lt;td&gt;Themes, states, calculations&lt;/td&gt;
&lt;td&gt;Core&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;@arr(name[…])&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Arrays + iteration&lt;/td&gt;
&lt;td&gt;Generated classes, loops, scales&lt;/td&gt;
&lt;td&gt;Core&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;@import&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Selective / wildcard module loading&lt;/td&gt;
&lt;td&gt;Modular architecture &amp;amp; ecosystem modules&lt;/td&gt;
&lt;td&gt;Core&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  How Components Are Structured
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Atomic / Token Layer (&lt;code&gt;@fun&lt;/code&gt; + variables)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Design tokens sit at the foundation so every component draws from a single source of truth:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@fun(tokens) {
  primary: #2563eb;
  radius-md: 8px;
  space-4: 1rem;
  shadow-sm: 0 1px 3px rgba(0,0,0,.1);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Base Style Blocks (&lt;code&gt;str()&lt;/code&gt; or &lt;code&gt;@fun&lt;/code&gt; full-block)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Related declarations are grouped into reusable blocks that can be dropped into any selector:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;str(card-base, "
  padding: @fun.tokens.space-4.value;
  border-radius: @fun.tokens.radius-md.value;
  box-shadow: @fun.tokens.shadow-sm.value;
  background: white;
")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Parameterized Components (&lt;code&gt;@define&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
True mixins accept arguments and can be composed freely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@define button(bg: #2563eb, fg: white, pad: 0.75rem 1.5rem) {
  background: @use(bg);
  color: @use(fg);
  padding: @use(pad);
  border: none;
  border-radius: @fun.tokens.radius-md.value;
  cursor: pointer;
}

@define button-hover(bg) {`
  &amp;amp;:hover { background: @use(bg); }
`}

.btn-primary {
  @button()
  @button-hover(#1d4ed8)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Semantic / Intent-based Styles (&lt;code&gt;pattern()&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Styles can be described in plain language; FSCSS matches by similarity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pattern(0.6: "elevated card with soft shadow", `
  border-radius: 12px;
  padding: 1.5rem;
  box-shadow: 0 10px 25px rgba(0,0,0,.08);
  background: white;
`)

.product-card {
  elevated card with soft shadow
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Conditional &amp;amp; Dynamic Behavior (&lt;code&gt;@event&lt;/code&gt; + &lt;code&gt;@arr&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Themes, states, and generated variants are handled at compile time without external logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@event theme(mode) {
  if mode: dark { return: #0f172a; }
  el { return: #f8fafc; }
}

body {
  background: @event.theme(dark);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Modular Architecture &amp;amp; Ecosystem
&lt;/h3&gt;

&lt;p&gt;FSCSS encourages splitting styles into focused modules and importing only what is needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@import((page-root, page-hero) from customizable)
@import((*) from form)
@import((st-chart-line, st-stat-card) from st-core)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modules that follow this pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/fscss-ttr/st-core.fscss" rel="noopener noreferrer"&gt;st-core&lt;/a&gt;&lt;/strong&gt; — pure-CSS charts &amp;amp; stat cards (data via CSS custom properties)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/fscss-ttr/form.fscss" rel="noopener noreferrer"&gt;form&lt;/a&gt;&lt;/strong&gt; — floating labels, checkboxes, switches, validation (checkbox-hack style)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/Figsh/Circle-progress.fscss" rel="noopener noreferrer"&gt;circle-progress&lt;/a&gt;&lt;/strong&gt; — progress rings with color logic driven by &lt;code&gt;@event&lt;/code&gt; + &lt;code&gt;@arr&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/fscss-ttr/customizable.fscss" rel="noopener noreferrer"&gt;customizable&lt;/a&gt;&lt;/strong&gt; — page shells (nav, hero, CTA, footer, typography)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/fscss-ttr/cube.fscss" rel="noopener noreferrer"&gt;cube&lt;/a&gt;&lt;/strong&gt; — pure CSS 3D cube faces with micro-effects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each module is self-contained, token-driven, and designed so multiple modules can coexist on one page without conflicts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recommended Project Layout
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;styles/
  tokens.fscss          ← @fun + $variables
  components/
    button.fscss        ← @define + str()
    card.fscss
    form.fscss
  layouts/
    page.fscss
  main.fscss            ← selective @imports + composition
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compile with the CLI for production (&lt;code&gt;fscss main.fscss dist/styles.css&lt;/code&gt;) so the shipped CSS has zero runtime dependency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Design Principles
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Composition over inheritance&lt;/strong&gt; — stack small &lt;code&gt;@define&lt;/code&gt;s and &lt;code&gt;str()&lt;/code&gt; blocks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tokens first&lt;/strong&gt; — everything reads from &lt;code&gt;@fun&lt;/code&gt; or &lt;code&gt;$variables&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Selective imports&lt;/strong&gt; — pull only the mixins a page needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compile-time resolution&lt;/strong&gt; — almost all logic runs at build time and disappears from the final CSS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Progressive enhancement&lt;/strong&gt; — start with simple &lt;code&gt;str()&lt;/code&gt; / &lt;code&gt;@fun&lt;/code&gt;, then graduate to &lt;code&gt;@define&lt;/code&gt; and &lt;code&gt;pattern()&lt;/code&gt; as complexity grows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This architecture keeps stylesheets readable, highly reusable, and free of the classic “mega-stylesheet” problems while still producing standard CSS that any browser understands.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>fscss</category>
      <category>sharepoint</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How pattern() Feels a Few Weeks In</title>
      <dc:creator>FSCSS tutorial</dc:creator>
      <pubDate>Tue, 01 Sep 2026 15:06:19 +0000</pubDate>
      <link>https://dev.to/fscss/how-pattern-feels-a-few-weeks-in-3fm5</link>
      <guid>https://dev.to/fscss/how-pattern-feels-a-few-weeks-in-3fm5</guid>
      <description>&lt;p&gt;I've written three posts now about &lt;code&gt;pattern()&lt;/code&gt;: what it is, why it might matter for beginners and AI-generated CSS, and a demo module built on top of it. This one is different. It's less a tutorial and more a check-in, and a reason to keep teaching this in the open rather than writing it once and moving on.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that surprised me
&lt;/h2&gt;

&lt;p&gt;I expected questions about syntax. I got questions about the matching itself instead. One reader asked directly how two patterns avoid matching the same phrase. Another pointed at the ambiguity tradeoff as the thing worth watching as the idea scales. Neither question was about how to write &lt;code&gt;pattern()&lt;/code&gt;. Both were about whether it holds up.&lt;/p&gt;

&lt;p&gt;That's the right question to be asking, and it's not fully answered yet. I know it holds up in a small module. I don't know yet how it holds up in a library with hundreds of patterns written by more than one person. That's genuinely still open, and I'd rather say that plainly than pretend the demo module settles it.&lt;/p&gt;

&lt;h2&gt;
  
  
  A short recap, for anyone catching up
&lt;/h2&gt;

&lt;p&gt;If this is the first post of the series you've landed on:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pattern()&lt;/code&gt; lets you describe a piece of CSS in plain English instead of calling it by an exact name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pattern(0.6: "rounded primary button", `
  border: none;
  border-radius: 8px;
  padding: 10px 20px;
  background: #764ba2;
  color: white;
`)

.btn {
  rounded primary button
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The phrase inside &lt;code&gt;.btn&lt;/code&gt; doesn't need to match the description exactly. It needs to score above the threshold, &lt;code&gt;0.6&lt;/code&gt; here, on word similarity. Write something close enough, and it resolves. Write something unrelated, and it falls through as harmless literal text instead of breaking your build.&lt;/p&gt;

&lt;p&gt;The earlier posts go deeper: &lt;a href="https://dev.to/fscss/fscss-define-pattern-and-import-explained-in-plain-english-5el0"&gt;the mechanics of &lt;code&gt;pattern()&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://dev.to/fscss/why-readable-css-matters-more-as-ai-writes-more-of-it-3jg0"&gt;why this matters for beginners and AI-generated CSS&lt;/a&gt;, and &lt;a href="https://dev.to/fscss/patternsfscss-a-demo-module-for-styling-css-in-plain-english-oc"&gt;patterns.fscss&lt;/a&gt;, a small open module you can fork.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd tell a beginner trying this for the first time
&lt;/h2&gt;

&lt;p&gt;Don't start by writing ten patterns. Start by writing one, for something you personally rewrite often, a card style, a button variant, whatever shows up in your own projects repeatedly. Give it a description in the words you'd actually use out loud. Then try triggering it with a slightly different phrase than the one you wrote, not the exact words, something close. If it matches, you've felt the whole idea in about two minutes. If it doesn't, lower the threshold slightly and try again. That's the entire learning curve.&lt;/p&gt;

&lt;p&gt;The mistake to avoid is writing two patterns that are almost the same idea in almost the same words. I made this mistake myself in the first draft of &lt;code&gt;patterns.fscss&lt;/code&gt;, two button patterns worded closely enough that matching between them was genuinely unclear. It's an easy trap, and the only real fix is noticing it and rewording, not a cleverer algorithm.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this goes next
&lt;/h2&gt;

&lt;p&gt;I don't have a roadmap to announce. What I have is an open module and an open question about how well description-based matching holds up at scale. If you try &lt;code&gt;pattern()&lt;/code&gt; on something real, whether it works cleanly or breaks in an interesting way, I'd rather hear about the break. That's more useful to the next person reading this series than another polished example would be.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/fscss-ttr/patterns.fscss" rel="noopener noreferrer"&gt;github.com/fscss-ttr/patterns.fscss&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Docs: &lt;a href="https://fscss.devtem.org/pattern" rel="noopener noreferrer"&gt;fscss.devtem.org/pattern&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Extension &lt;a href="https://marketplace.visualstudio.com/items?itemName=Figsh.fscss" rel="noopener noreferrer"&gt;visualstudio&lt;/a&gt; &lt;/p&gt;




</description>
      <category>fscss</category>
      <category>css</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>From st-core.fscss to ProvChart: Same CSS-Paint Idea, Built for Real Data</title>
      <dc:creator>FSCSS tutorial</dc:creator>
      <pubDate>Wed, 26 Aug 2026 15:56:32 +0000</pubDate>
      <link>https://dev.to/fscss/from-st-corefscss-to-provchart-same-css-paint-idea-built-for-real-data-2mp2</link>
      <guid>https://dev.to/fscss/from-st-corefscss-to-provchart-same-css-paint-idea-built-for-real-data-2mp2</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/fscss-ttr/st-core.fscss" rel="noopener noreferrer"&gt;st-core.fscss&lt;/a&gt; started as an FSCSS module with a clear bet: &lt;strong&gt;charts can be browser paint, not a JavaScript chart runtime.&lt;/strong&gt; No canvas. No SVG dependency for the line. Data lives in CSS custom properties; shapes are &lt;code&gt;clip-path: polygon()&lt;/code&gt;; optional JS only writes numbers. Compiled, it’s on the order of &lt;strong&gt;~0.5 kb&lt;/strong&gt; of CSS—not a 40–150 kb chart library.&lt;/p&gt;

&lt;p&gt;That idea spread—writeups, demos, dashboard experiments—because it matched what performance-minded frontends already wanted: &lt;strong&gt;first paint is the chart&lt;/strong&gt;, crawlers see markup, updates can be variable writes with free CSS transitions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ProvChart&lt;/strong&gt; is not a rejection of that model. It’s what you build when the same philosophy has to survive &lt;strong&gt;arbitrary series lengths, multi-series layouts, and a server-side compile step&lt;/strong&gt;—without asking every team to hand-author mixins per dataset.&lt;/p&gt;




&lt;h2&gt;
  
  
  What st-core actually nailed
&lt;/h2&gt;

&lt;p&gt;st-core’s contract is intentionally tight and easy to teach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Eight points: &lt;code&gt;--st-p1&lt;/code&gt; … &lt;code&gt;--st-p8&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Fixed X stops: &lt;code&gt;0% 14% 28% 42% 57% 71% 85% 100%&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Mixins like &lt;code&gt;@st-chart-points&lt;/code&gt;, &lt;code&gt;@st-chart-line&lt;/code&gt;, &lt;code&gt;@st-chart-fill&lt;/code&gt;, dots, stats&lt;/li&gt;
&lt;li&gt;Optional JS: &lt;code&gt;element.style.setProperty('--st-p3', '42%')&lt;/code&gt; → browser repaints the polygon
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.chart&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c"&gt;/* FSCSS: @st-chart-points(20, 35, 33, 30, 48, 35, 66, 37) */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That is still a &lt;strong&gt;strong starter library&lt;/strong&gt; for hand-built cards, marketing strips, and demos where eight samples are enough. It maximizes what the browser already does well. Nothing about ProvChart throws that away.&lt;/p&gt;


&lt;h2&gt;
  
  
  Where a fixed eight-point contract stops fitting
&lt;/h2&gt;

&lt;p&gt;Real product data rarely arrives as “exactly eight numbers”:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Days in a month, weeks in a year, irregular sensor samples
&lt;/li&gt;
&lt;li&gt;Several series on one frame (revenue vs cost, traffic vs signups)
&lt;/li&gt;
&lt;li&gt;Automation: JSON from an API, not a mixin edited in a stylesheet
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;st-core’s elegance &lt;strong&gt;is&lt;/strong&gt; that compile-time contract. ProvChart’s job is to keep &lt;strong&gt;data → variables → CSS geometry → paint&lt;/strong&gt; when the point count and series count are decided &lt;strong&gt;per request&lt;/strong&gt;, not per mixin signature.&lt;/p&gt;


&lt;h2&gt;
  
  
  What ProvChart changes (and what it doesn’t)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;st-core.fscss&lt;/th&gt;
&lt;th&gt;ProvChart&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Paint model&lt;/td&gt;
&lt;td&gt;CSS variables + &lt;code&gt;clip-path&lt;/code&gt; / native CSS&lt;/td&gt;
&lt;td&gt;Same family of ideas&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Point count&lt;/td&gt;
&lt;td&gt;Eight fixed slots&lt;/td&gt;
&lt;td&gt;Length of &lt;code&gt;series[].points&lt;/code&gt; (no eight-slot ceiling)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Series&lt;/td&gt;
&lt;td&gt;Hand composition / multi-line patterns in FSCSS&lt;/td&gt;
&lt;td&gt;First-class multi-series, combo, bar, hbar, gauge, …&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authoring&lt;/td&gt;
&lt;td&gt;Mixins in source / FSCSS compile&lt;/td&gt;
&lt;td&gt;JSON → builder or &lt;strong&gt;Developer API&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Client chart library&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;None for paint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Docs embeds&lt;/td&gt;
&lt;td&gt;Manual / CSS&lt;/td&gt;
&lt;td&gt;Optional &lt;code&gt;generate-svg&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Interaction&lt;/td&gt;
&lt;td&gt;Hand dots / &lt;code&gt;attr()&lt;/code&gt; patterns&lt;/td&gt;
&lt;td&gt;Optional &lt;strong&gt;provchart-runtime&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Unchanged belief:&lt;/strong&gt; the chart is CSS. JavaScript should not be required to &lt;em&gt;draw&lt;/em&gt; the shape.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Changed machinery:&lt;/strong&gt; compilation can run on a server; geometry is generated for the payload you sent; roots are instance-scoped (classes like &lt;code&gt;pc-…&lt;/code&gt; and variables such as &lt;code&gt;--pc-{id}-s{series}-p{index}&lt;/code&gt;) so many charts can share a page without colliding.&lt;/p&gt;

&lt;p&gt;There is &lt;strong&gt;no marketed “must be ≤ 200 points” product rule&lt;/strong&gt; in this writeup. Practical limits are the usual ones: payload size, CSS complexity, and what stays smooth in real browsers—not an eight-argument mixin.&lt;/p&gt;


&lt;h2&gt;
  
  
  Server compile instead of only a &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; mixin
&lt;/h2&gt;

&lt;p&gt;st-core path: FSCSS CLI or in-browser compile → you ship CSS you authored.&lt;/p&gt;

&lt;p&gt;ProvChart path: send JSON, get markup:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://provchart-api.devtem.org/api/v1/generate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X-API-Key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PROVCHART_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;line&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;series&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Revenue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#8b7bff&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;points&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;axisX&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jan&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Feb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Apr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;May&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// data.html + data.css → inject; first paint is the chart&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Five points or fifty—it’s the same call shape. For README and Markdown surfaces, &lt;code&gt;POST /api/v1/generate-svg&lt;/code&gt; returns SVG / data URI without requiring a chart runtime on the doc page.&lt;/p&gt;


&lt;h2&gt;
  
  
  provchart-runtime: interaction without owning paint
&lt;/h2&gt;

&lt;p&gt;st-core already showed the interaction seed: a dot, a tooltip, data on the element, CSS doing the rest.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/fscss-ttr/provchart-runtime" rel="noopener noreferrer"&gt;provchart-runtime&lt;/a&gt; (MIT, npm &lt;code&gt;provchart-runtime&lt;/code&gt;) generalizes that for &lt;strong&gt;generated&lt;/strong&gt; HTML charts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Finds &lt;code&gt;[data-provchart]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Skips pure SVG exports when configured
&lt;/li&gt;
&lt;li&gt;Scroll reveal, legend focus, per-point tooltips (reading generated custom properties where present)
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;MutationObserver&lt;/code&gt; for charts injected after load
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ProvChartRuntimeConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;tooltips&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;perPointTooltips&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;excludeSvg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script
  &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/provchart-runtime@1.0.0/dist/provchart-runtime.min.js"&lt;/span&gt;
  &lt;span class="na"&gt;defer&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Additive on purpose: generate output does not depend on the runtime; the runtime does not replace the engine.&lt;/p&gt;


&lt;h2&gt;
  
  
  The stack, honestly drawn
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;st-core.fscss (open source, viral pure-CSS chart idea)
  --st-p1…p8 · fixed X-stops · mixins · ~0.5kb compiled CSS
  JS optional: write variables, CSS transitions animate polygons
        │
        ▼
ProvChart (chart.devtem.org)
  Same paint philosophy · variable-length series · multi-series types
  Builder + Developer API → static HTML/CSS (and SVG for docs)
        │
        ▼
provchart-runtime (optional)
  Tooltips / motion / legend UX on HTML charts only
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Open core: &lt;a href="https://github.com/fscss-ttr/st-core.fscss" rel="noopener noreferrer"&gt;github.com/fscss-ttr/st-core.fscss&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Product: &lt;a href="https://chart.devtem.org" rel="noopener noreferrer"&gt;chart.devtem.org&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Runtime: &lt;a href="https://github.com/fscss-ttr/provchart-runtime" rel="noopener noreferrer"&gt;github.com/fscss-ttr/provchart-runtime&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  When to use which
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use st-core when…&lt;/th&gt;
&lt;th&gt;Use ProvChart when…&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;You want full control in FSCSS/CSS source&lt;/td&gt;
&lt;td&gt;Data is JSON from backends, CI, or agents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Eight points (or st-core’s patterns) fit the story&lt;/td&gt;
&lt;td&gt;Series length and count change per view&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You’re deep in the FSCSS module ecosystem&lt;/td&gt;
&lt;td&gt;You want API keys, quotas, SVG export, dashboard builder&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maximum clarity for teaching pure CSS charts&lt;/td&gt;
&lt;td&gt;Production multi-series, combo, gauge, automation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Many teams will use &lt;strong&gt;both&lt;/strong&gt;: st-core for crafted marketing cards; ProvChart when the dataset refuses to stay eight samples long.&lt;/p&gt;



&lt;p&gt;st-core.fscss proved a viral, high-performance idea—&lt;strong&gt;browser-native paint, minimal JS, no chart-library tax.&lt;/strong&gt; ProvChart keeps that idea and removes the fixed-slot ceiling so the same belief works when the numbers come from a database, not a mixin call.&lt;/p&gt;




&lt;div class="ltag__user ltag__user__id__14466"&gt;
  &lt;a href="/provchart" class="ltag__user__link profile-image-link"&gt;
    &lt;div class="ltag__user__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=150,height=150,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F14466%2Fb4fe5b40-3c9d-46ca-9537-1880fc4bea3c.png" alt="provchart image"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
      &lt;a href="/provchart" class="ltag__user__link"&gt;ProvChart&lt;/a&gt;
      Follow
    &lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a href="/provchart" class="ltag__user__link"&gt;
        Charts that load with the first paint and stay crawlable
ProvChart generates pure HTML + CSS charts from your data
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>product</category>
      <category>fscss</category>
      <category>css</category>
      <category>provchart</category>
    </item>
    <item>
      <title>Why Readable CSS Matters More as AI Writes More of It</title>
      <dc:creator>FSCSS tutorial</dc:creator>
      <pubDate>Tue, 25 Aug 2026 09:29:37 +0000</pubDate>
      <link>https://dev.to/fscss/why-readable-css-matters-more-as-ai-writes-more-of-it-3jg0</link>
      <guid>https://dev.to/fscss/why-readable-css-matters-more-as-ai-writes-more-of-it-3jg0</guid>
      <description>&lt;p&gt;Most CSS tooling is built around one assumption: the person writing the stylesheet remembers the exact name of the thing they want. A mixin, a utility class, a function signature. Get the name slightly wrong and nothing happens, or worse, something wrong happens silently.&lt;/p&gt;

&lt;p&gt;That assumption breaks down in two places at once right now: beginners, and AI-generated CSS. Neither is good at remembering exact names. Both are good at describing what they want.&lt;/p&gt;

&lt;h2&gt;
  
  
  The exact-name problem
&lt;/h2&gt;

&lt;p&gt;Say you want a rounded button with a purple background. In most systems you need to already know the answer is &lt;code&gt;.btn-primary&lt;/code&gt;, or &lt;code&gt;mixin button-primary()&lt;/code&gt;, or whatever your team decided six months ago. If you don't know it, you either guess, search the codebase, or write it from scratch again, adding one more near-duplicate button style to the pile.&lt;/p&gt;

&lt;p&gt;A beginner doesn't have that memorized name yet. An AI model generating CSS doesn't reliably have it either, it will confidently produce a plausible-looking class name that doesn't exist in your project, because plausible-looking is exactly what language models are good at, and existing in your specific codebase is not something they can check without help.&lt;/p&gt;

&lt;p&gt;Both groups are, in a real sense, working from intent rather than from an exact API surface. The tooling just hasn't caught up to that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Matching by description instead of by name
&lt;/h2&gt;

&lt;p&gt;FSCSS's &lt;code&gt;pattern()&lt;/code&gt; method takes the opposite approach. Instead of calling a style by its exact name, you describe it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;pattern&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;6&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"rounded primary button"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;
  &lt;span class="nt"&gt;border&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;none&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="nt"&gt;border-radius&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;8&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="nt"&gt;padding&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;10&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt; &lt;span class="err"&gt;20&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="nt"&gt;background&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;#764&lt;/span&gt;&lt;span class="nt"&gt;ba2&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="nt"&gt;color&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;white&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="nt"&gt;font-weight&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;600&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and later, anywhere in the stylesheet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.btn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;rounded&lt;/span&gt; &lt;span class="err"&gt;primary&lt;/span&gt; &lt;span class="err"&gt;button&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The phrase doesn't need to match the description exactly. It needs to be close enough, measured by a similarity score against a threshold you set. Someone who writes &lt;code&gt;rounded purple button&lt;/code&gt; instead of &lt;code&gt;rounded primary button&lt;/code&gt; still gets the right result, because the words overlap enough to clear the bar.&lt;/p&gt;

&lt;p&gt;This is a small syntax change with a real consequence: the thing being memorized shifts from an exact identifier to a rough description. Rough descriptions are the thing beginners already know how to produce, and the thing AI models are already extremely good at producing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this helps beginners specifically
&lt;/h2&gt;

&lt;p&gt;A new developer doesn't need to browse a component library, search for &lt;code&gt;card&lt;/code&gt;, &lt;code&gt;panel&lt;/code&gt;, &lt;code&gt;surface&lt;/code&gt;, and &lt;code&gt;box&lt;/code&gt; to guess which one your project picked, and read the source to confirm what it actually does. They write what they want in the words they'd use to ask a coworker for it. If a close-enough pattern exists, it resolves. If it doesn't, they get to write real CSS instead, which they were going to have to learn eventually anyway.&lt;/p&gt;

&lt;p&gt;This doesn't remove the need to learn CSS. It removes the need to memorize your project's specific naming conventions before you can be productive in it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this helps AI-generated CSS specifically
&lt;/h2&gt;

&lt;p&gt;When a model generates &lt;code&gt;@my-exact-mixin-name()&lt;/code&gt;, it is guessing at a name it has no way to verify against your actual codebase. When it generates &lt;code&gt;soft elevated card with subtle shadow&lt;/code&gt; inside a selector, it is describing an outcome, and the matching happens against patterns that actually exist in your project. A wrong guess at an exact name fails silently or breaks the build. A wrong guess at a description either matches something close enough to be useful, or matches nothing and falls through as literal, harmless text, which is a far safer failure mode.&lt;/p&gt;

&lt;p&gt;This is also why the earlier comment on the &lt;code&gt;pattern()&lt;/code&gt; announcement post, about this being especially useful for AI-generated CSS, is worth taking seriously. Fuzzy matching by description is closer to how models actually operate than exact-name lookup ever was.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tradeoff you have to manage
&lt;/h2&gt;

&lt;p&gt;None of this is free. A pattern library is only as reliable as the distinctness of its descriptions. If two patterns describe closely related things in overlapping words, for example &lt;code&gt;white button with purple label&lt;/code&gt; next to &lt;code&gt;solid purple primary button with white label&lt;/code&gt;, a given phrase can score close on both, and the result depends on small wording differences rather than clear intent. This came up directly while building &lt;a href="https://github.com/fscss-ttr/patterns.fscss" rel="noopener noreferrer"&gt;patterns.fscss&lt;/a&gt;: an early draft had two button patterns worded closely enough that matching between them was genuinely ambiguous.&lt;/p&gt;

&lt;p&gt;The fix isn't a smarter matching algorithm. It's writing descriptions the way you'd want a beginner, or a model, to actually phrase the request, and keeping related-but-different patterns lexically distinct from each other. That discipline matters more as a pattern library grows, not less.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to start
&lt;/h2&gt;

&lt;p&gt;If you want to see this in practice, &lt;a href="https://github.com/fscss-ttr/patterns.fscss" rel="noopener noreferrer"&gt;patterns.fscss&lt;/a&gt; is a small demo module of cards, buttons, hover effects, and animations, all callable by description. Fork it, read how the descriptions are worded, and use it as a template for your own project's pattern library.&lt;/p&gt;

&lt;p&gt;Pattern Feature: &lt;a href="https://fscss.devtem.org/pattern" rel="noopener noreferrer"&gt;fscss.devtem.org/pattern&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;NPM: &lt;a href="https://www.npmjs.com/package/fscss" rel="noopener noreferrer"&gt;npmjs.com/package/fscss&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vscode extention: &lt;a href="https://marketplace.visualstudio.com/items?itemName=Figsh.fscss" rel="noopener noreferrer"&gt;FSCSS support&lt;/a&gt;&lt;/p&gt;




</description>
      <category>ai</category>
      <category>fscss</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to build an FSCSS module like st-core.fscss</title>
      <dc:creator>FSCSS tutorial</dc:creator>
      <pubDate>Mon, 24 Aug 2026 14:21:20 +0000</pubDate>
      <link>https://dev.to/fscss/how-to-build-an-fscss-module-like-st-corefscss-1d6l</link>
      <guid>https://dev.to/fscss/how-to-build-an-fscss-module-like-st-corefscss-1d6l</guid>
      <description>&lt;p&gt;To build an FSCSS module like &lt;code&gt;st-core.fscss&lt;/code&gt;, create a stylesheet of reusable &lt;code&gt;@define&lt;/code&gt; mixins, expose a small public API, and compile/test it with the FSCSS CLI. &lt;code&gt;st-core&lt;/code&gt; follows this pattern for design tokens, layout helpers, charts, stat cards, and progress bars.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Learn the module structure
&lt;/h3&gt;

&lt;p&gt;An FSCSS module is a stylesheet of reusable style definitions that other FSCSS files can import.&lt;/p&gt;

&lt;p&gt;A practical module should contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Private design tokens and helper logic&lt;/li&gt;
&lt;li&gt;Public mixins with a consistent naming convention&lt;/li&gt;
&lt;li&gt;Parameter defaults&lt;/li&gt;
&lt;li&gt;Selector arguments so consumers can choose their own class names&lt;/li&gt;
&lt;li&gt;Documentation and examples&lt;/li&gt;
&lt;li&gt;A compiled CSS output for production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Typical project layout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-core.fscss
README.md
examples/
  demo.fscss
dist/
  my-core.css
package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Define a public API
&lt;/h3&gt;

&lt;p&gt;Use a namespace to avoid collisions. Parameters &lt;strong&gt;must&lt;/strong&gt; be read with &lt;code&gt;@use()&lt;/code&gt;. For full rules, wrap the body in a backtick string block and target the selector with &lt;code&gt;@use(selector){ ... }&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@define&lt;/span&gt; &lt;span class="n"&gt;mc-root&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;
&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="k"&gt;@use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="py"&gt;--mc-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#10131a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--mc-surface&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#191e28&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--mc-card&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#222938&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--mc-accent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#4f9cff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--mc-text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#eef4ff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--mc-muted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#8491a7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--mc-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--mc-space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--mc-chart-line-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify the exact syntax against the FSCSS version you ship against. &lt;code&gt;st-core.fscss&lt;/code&gt; requires FSCSS 1.1.24 or later.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Build reusable mixins
&lt;/h3&gt;

&lt;p&gt;A mixin should generate one coherent component or behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Container&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@define&lt;/span&gt; &lt;span class="n"&gt;mc-container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;
  &lt;span class="k"&gt;@use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;margin-inline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-space&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Card&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@define&lt;/span&gt; &lt;span class="n"&gt;mc-card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;:.&lt;/span&gt;&lt;span class="n"&gt;mc-card&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;
  &lt;span class="k"&gt;@use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-card&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="n"&gt;color-mix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;srgb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-accent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;18%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-radius&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-space&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Progress bar&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@define&lt;/span&gt; &lt;span class="n"&gt;mc-progress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;:.&lt;/span&gt;&lt;span class="n"&gt;mc-progress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;
  &lt;span class="k"&gt;@use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-progress-width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default-width&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;999px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;90deg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-accent&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="m"&gt;#9bc7ff&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="m"&gt;400ms&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The mixin establishes structure; CSS custom properties let individual instances override values.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Create a chart data mixin
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;st-core&lt;/code&gt; stores chart values in custom properties (&lt;code&gt;--st-p1&lt;/code&gt; … &lt;code&gt;--st-p8&lt;/code&gt;). The fill, line, and dots inherit them. Values are supplied on a natural 0–100 scale (100 = top); the mixin inverts them for CSS coordinates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@define&lt;/span&gt; &lt;span class="n"&gt;mc-chart-points&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;p5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p6&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="py"&gt;--mc-p1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="n"&gt;-&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--mc-p2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="n"&gt;-&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--mc-p3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="n"&gt;-&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--mc-p4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="n"&gt;-&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--mc-p5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="n"&gt;-&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--mc-p6&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="n"&gt;-&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p6&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--mc-p7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="n"&gt;-&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p7&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--mc-p8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="n"&gt;-&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p8&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Render the chart with CSS
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;clip-path: polygon()&lt;/code&gt;. This is pure CSS—no SVG, canvas, or JS charting library.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Area fill&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@define&lt;/span&gt; &lt;span class="n"&gt;mc-chart-fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;:.&lt;/span&gt;&lt;span class="n"&gt;mc-chart-fill&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;
  &lt;span class="k"&gt;@use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;inset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;color-mix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;srgb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-accent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;35%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;clip-path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;polygon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="m"&gt;0%&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="m"&gt;14%&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="m"&gt;28%&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="m"&gt;42%&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="m"&gt;57%&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="m"&gt;71%&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p6&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="m"&gt;85%&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p7&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="m"&gt;100%&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p8&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="m"&gt;100%&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="m"&gt;0%&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Line stroke&lt;/strong&gt; (thin polygon with return path)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@define&lt;/span&gt; &lt;span class="n"&gt;mc-chart-line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;:.&lt;/span&gt;&lt;span class="n"&gt;mc-chart-line&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;
  &lt;span class="k"&gt;@use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;inset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-accent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;drop-shadow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-accent&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nl"&gt;clip-path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;polygon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="m"&gt;0%&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="m"&gt;14%&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="m"&gt;28%&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="m"&gt;42%&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="m"&gt;57%&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="m"&gt;71%&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p6&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="m"&gt;85%&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p7&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="m"&gt;100%&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p8&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="m"&gt;100%&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-chart-line-width&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
      &lt;span class="m"&gt;85%&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-chart-line-width&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
      &lt;span class="m"&gt;71%&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-chart-line-width&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
      &lt;span class="m"&gt;57%&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-chart-line-width&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
      &lt;span class="m"&gt;42%&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-chart-line-width&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
      &lt;span class="m"&gt;28%&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-chart-line-width&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
      &lt;span class="m"&gt;14%&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-chart-line-width&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
      &lt;span class="m"&gt;0%&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-p1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-chart-line-width&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For production-quality curves you may prefer SVG or canvas; the CSS technique is ideal for small, fixed-point visualizations.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Import and use the module
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;my-core&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;mc-root&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;mc-card&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;stat-card&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;mc-chart-fill&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;chart-fill&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;mc-chart-line&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;chart-line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chart&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;220px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-surface&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--mc-radius&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="err"&gt;@mc-chart-points(20,&lt;/span&gt; &lt;span class="err"&gt;35,&lt;/span&gt; &lt;span class="err"&gt;33,&lt;/span&gt; &lt;span class="err"&gt;30,&lt;/span&gt; &lt;span class="err"&gt;48,&lt;/span&gt; &lt;span class="err"&gt;35,&lt;/span&gt; &lt;span class="err"&gt;66,&lt;/span&gt; &lt;span class="err"&gt;37)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.chart-line&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--mc-accent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#55d6be&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Corresponding HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"stat-card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;Revenue&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;$84,201&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"chart"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"chart-fill"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"chart-line"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;st-core&lt;/code&gt; uses the same consumer pattern: import the module, call the component mixins, then place the generated classes in HTML.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Support runtime updates
&lt;/h3&gt;

&lt;p&gt;Because data lives in custom properties, JavaScript only needs to write variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateChart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chart&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;chart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s2"&gt;`--mc-p&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%`&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;updateChart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.chart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JavaScript supplies data; CSS remains responsible for rendering.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Compile and test
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; fscss
fscss examples/demo.fscss dist/demo.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test at least:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mixins with default arguments&lt;/li&gt;
&lt;li&gt;Mixins with custom selectors&lt;/li&gt;
&lt;li&gt;Multiple component instances&lt;/li&gt;
&lt;li&gt;Missing or invalid values&lt;/li&gt;
&lt;li&gt;Responsive widths&lt;/li&gt;
&lt;li&gt;CSS custom-property overrides&lt;/li&gt;
&lt;li&gt;Compiled output in browsers (no FSCSS runtime)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For production, compile the module into CSS. &lt;code&gt;st-core&lt;/code&gt; documents CDN/runtime mode for prototypes and compiled mode for deployment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recommended API design
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@mc-root()
@mc-container(selector)
@mc-card(selector)
@mc-chart-points(values...)
@mc-chart-fill(selector)
@mc-chart-line(selector)
@mc-chart-grid(selector, rows, columns)
@mc-progress(selector, default-width)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep implementation details private, prefix every generated variable and class, document every parameter, and provide one minimal example per mixin. That combination is what makes a module like &lt;code&gt;st-core.fscss&lt;/code&gt; reusable rather than merely a collection of CSS snippets.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Sources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real source: &lt;a href="https://github.com/fscss-ttr/st-core.fscss/blob/main/st-core.fscss" rel="noopener noreferrer"&gt;st-core.fscss&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Official &lt;code&gt;@define&lt;/code&gt; / &lt;code&gt;@use&lt;/code&gt; docs: &lt;a href="https://fscss.devtem.org/define" rel="noopener noreferrer"&gt;fscss.devtem.org/define&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Module README &amp;amp; patterns: &lt;a href="https://github.com/fscss-ttr/st-core.fscss" rel="noopener noreferrer"&gt;st-core.fscss README&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>css</category>
      <category>frontend</category>
      <category>software</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>patterns.fscss: a demo module for styling CSS in plain English</title>
      <dc:creator>FSCSS tutorial</dc:creator>
      <pubDate>Sun, 23 Aug 2026 00:10:15 +0000</pubDate>
      <link>https://dev.to/fscss/patternsfscss-a-demo-module-for-styling-css-in-plain-english-oc</link>
      <guid>https://dev.to/fscss/patternsfscss-a-demo-module-for-styling-css-in-plain-english-oc</guid>
      <description>&lt;p&gt;FSCSS &lt;a href="https://www.npmjs.com/package/fscss" rel="noopener noreferrer"&gt;v1.1.25&lt;/a&gt; shipped &lt;code&gt;pattern()&lt;/code&gt; — a method that matches a plain-English phrase against a stored description and injects the matching CSS. I wrote about the &lt;a href="https://fscss.devtem.org/pattern" rel="noopener noreferrer"&gt;mechanics of &lt;code&gt;pattern()&lt;/code&gt;&lt;/a&gt; itself in an earlier post. This one is about what I built with it: &lt;a href="https://github.com/fscss-ttr/patterns.fscss" rel="noopener noreferrer"&gt;patterns.fscss&lt;/a&gt;, a small demo module you can import today.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it is
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;patterns.fscss&lt;/code&gt; is a pattern library. It bundles a set of design tokens and a set of &lt;code&gt;pattern()&lt;/code&gt; definitions for common UI needs, cards, buttons, hover effects, animations, a few components, so you can write a class body like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;beautiful&lt;/span&gt; &lt;span class="err"&gt;gradient&lt;/span&gt; &lt;span class="err"&gt;hello&lt;/span&gt; &lt;span class="err"&gt;world&lt;/span&gt; &lt;span class="err"&gt;card&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.btn-primary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;solid&lt;/span&gt; &lt;span class="err"&gt;purple&lt;/span&gt; &lt;span class="err"&gt;primary&lt;/span&gt; &lt;span class="err"&gt;button&lt;/span&gt; &lt;span class="err"&gt;with&lt;/span&gt; &lt;span class="err"&gt;white&lt;/span&gt; &lt;span class="err"&gt;label&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and get real CSS out, without calling a mixin by an exact name.&lt;/p&gt;

&lt;p&gt;It is explicitly a demo. It does not try to cover every pattern you might want. It exists to show what a pattern library looks like in practice, and to give people a working repo to fork and extend.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it's structured
&lt;/h2&gt;

&lt;p&gt;The module is two &lt;code&gt;@define&lt;/code&gt; blocks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@define&lt;/span&gt; &lt;span class="n"&gt;pattern-root&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* declares design tokens as CSS custom properties */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@define&lt;/span&gt; &lt;span class="n"&gt;patterns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;thr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.65&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* declares the pattern library, using @use(thr) as
     the shared threshold for every pattern() call */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calling &lt;code&gt;@pattern-root()&lt;/code&gt; sets up the tokens. Calling &lt;code&gt;@patterns(0.7)&lt;/code&gt; registers the library at whatever threshold you want. Everything after that is just writing phrases inside your selectors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using it
&lt;/h2&gt;

&lt;p&gt;Import the published module directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;pattern-root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;patterns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;patterns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;pattern-root&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;patterns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or fork the repo and import your own copy, which is the better option once you start adding patterns of your own:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;pattern-root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;patterns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;"./patterns.fscss"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A note on threshold and collisions
&lt;/h2&gt;

&lt;p&gt;Every pattern in the module shares one threshold, set at the &lt;code&gt;@patterns()&lt;/code&gt; call site. That keeps the call simple, but it means pattern descriptions need to stay lexically distinct from each other. Two descriptions that share most of their words, for example an early draft of this module had "rounded primary white button with purple text" next to "solid purple primary button with white text", can end up close enough in similarity score that which one wins depends on small wording differences in the phrase you actually write. The fix isn't a smarter algorithm, it's writing descriptions that don't overlap that much in the first place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contributing
&lt;/h2&gt;

&lt;p&gt;The repo is set up for contribution. If you have a pattern you use often, plain-English description plus the CSS it should produce, a pull request is the way to get it in. The README has the full guidelines, including the distinctness rule above.&lt;/p&gt;

&lt;p&gt;Repo: &lt;strong&gt;&lt;a href="https://github.com/fscss-ttr/patterns.fscss" rel="noopener noreferrer"&gt;github.com/fscss-ttr/patterns.fscss&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open-source, MIT Licensed&lt;/p&gt;




</description>
      <category>fscss</category>
      <category>webdev</category>
      <category>opensource</category>
      <category>css</category>
    </item>
  </channel>
</rss>
