<?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>devtemDesign 0.1.0: one config object paints a whole landing page</title>
      <dc:creator>FSCSS tutorial</dc:creator>
      <pubDate>Sun, 25 Oct 2026 10:46:01 +0000</pubDate>
      <link>https://dev.to/fscss/devtemdesign-010-one-config-object-paints-a-whole-landing-page-2ac4</link>
      <guid>https://dev.to/fscss/devtemdesign-010-one-config-object-paints-a-whole-landing-page-2ac4</guid>
      <description>&lt;p&gt;Every landing page I built started the same way: nav, hero, feature cards, pricing, FAQ, footer, then a day of making it responsive. So I wrote an engine that does that part for me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;devtemDesign&lt;/strong&gt; takes one config object and renders the whole page. No framework, no build step, no dependencies. Two tags and one function call.&lt;/p&gt;

&lt;p&gt;This post is both an introduction and a reference for &lt;strong&gt;v0.1.0&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it in 30 seconds
&lt;/h2&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;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/devtemdesign@0.1.0/style.min.css"&lt;/span&gt;&lt;span class="nt"&gt;&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/devtemdesign@0.1.0/script.min.js"&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;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app-root"&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;script&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;devtemDesign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;app-root&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;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cyber&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;logoName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MYAPP&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;heroTitleLine1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Declarative UI,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;heroTitleLine2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Zero-Config Motion&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;heroSubtitle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;One config object. Complete animated landing.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;primaryBtnText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Get started&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;primaryBtnHref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/docs&lt;/span&gt;&lt;span class="dl"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That gives you a sticky glass navbar, an animated hero, ambient background orbs, reveal-on-scroll, a mobile drawer and a footer. Every section except the hero is optional, and a section only renders when its config key is present.&lt;/p&gt;

&lt;p&gt;If you want to skip the code entirely, the &lt;a href="https://design.devtem.org/builder" rel="noopener noreferrer"&gt;builder&lt;/a&gt; generates a config from a description and lets you edit it live.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's in 0.1.0
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;7 templates:&lt;/strong&gt; &lt;code&gt;figsh&lt;/code&gt;, &lt;code&gt;cyber&lt;/code&gt;, &lt;code&gt;aurora&lt;/code&gt;, &lt;code&gt;monochrome&lt;/code&gt;, &lt;code&gt;sunset&lt;/code&gt;, &lt;code&gt;ocean&lt;/code&gt;, and &lt;code&gt;paper&lt;/code&gt; (light).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live theming:&lt;/strong&gt; switch at runtime, add a built-in theme button, or override any design token.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New sections:&lt;/strong&gt; stats with count-up numbers, FAQ accordion, closing CTA, and pricing with a Monthly/Yearly toggle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactions:&lt;/strong&gt; scroll progress bar, active nav link, card spotlight, seamless brand marquee, back-to-top button.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A real lifecycle:&lt;/strong&gt; &lt;code&gt;devtemDesign()&lt;/code&gt; returns &lt;code&gt;{ setTemplate, destroy }&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessibility:&lt;/strong&gt; skip link, focus rings, &lt;code&gt;aria-expanded&lt;/code&gt; on the menu, native &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; for FAQ, full &lt;code&gt;prefers-reduced-motion&lt;/code&gt; support.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A fuller example
&lt;/h2&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;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;devtemDesign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;app-root&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;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ocean&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;themeSwitcher&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;logoName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ORBIT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;navLinks&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;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Features&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#features&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;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Pricing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#pricing&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;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FAQ&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#faq&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;ctaText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Start free&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ctaHref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#pricing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;heroBadge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;New: team workspaces&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;heroTitleLine1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ship analytics,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;heroTitleLine2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;not dashboards&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;heroSubtitle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Turn raw events into answers your whole team can read.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;primaryBtnText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Start free&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;primaryBtnHref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#pricing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;stats&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;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;12k+&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Teams&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;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;99.9%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Uptime&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;features&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;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Live metrics&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;desc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Streams update in under a second.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;⚡&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;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Shared boards&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;desc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;One link for the whole team.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;📊&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;yearlyBadge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Save 20%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;pricing&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;tier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Starter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;features&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;3 boards&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;cta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Start free&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#&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;tier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Team&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$19&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/mo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;yearly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$182&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/yr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;featured&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;badge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Most popular&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;features&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;Unlimited boards&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;Priority support&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;cta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Go Team&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#&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;faq&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;q&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Is there a free plan?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Yes. Starter is free forever.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="na"&gt;cta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;See your data differently&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Create account&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;footer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;tagline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Built with devtemDesign.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;© 2026 Orbit&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see this running, with a template picker and a mobile preview, on the &lt;a href="https://design.devtem.org/examples" rel="noopener noreferrer"&gt;examples page&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Templates
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Template&lt;/th&gt;
&lt;th&gt;Vibe&lt;/th&gt;
&lt;th&gt;Accents&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;figsh&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Futuristic glass&lt;/td&gt;
&lt;td&gt;Cyan, purple, pink&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cyber&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Neon cyberpunk&lt;/td&gt;
&lt;td&gt;Cyan, magenta, red&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;aurora&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Organic nature&lt;/td&gt;
&lt;td&gt;Emerald, violet, blue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;monochrome&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Minimal grayscale&lt;/td&gt;
&lt;td&gt;White, silver&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sunset&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Warm dusk&lt;/td&gt;
&lt;td&gt;Orange, rose, gold&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ocean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cool depth&lt;/td&gt;
&lt;td&gt;Sky, teal, indigo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;paper&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Light mode&lt;/td&gt;
&lt;td&gt;Indigo, pink, cyan&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Every color in the stylesheet comes from a token, which is why the light template works without a separate stylesheet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Runtime control
&lt;/h2&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;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;devtemDesign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;app-root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sunset&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// switch theme, no re-render&lt;/span&gt;
&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;               &lt;span class="c1"&gt;// remove listeners, observers and markup&lt;/span&gt;

&lt;span class="nx"&gt;devtemDesign&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;         &lt;span class="c1"&gt;// "0.1.0"&lt;/span&gt;
&lt;span class="nx"&gt;devtemDesign&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;templates&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;       &lt;span class="c1"&gt;// ["figsh", "cyber", "aurora", ...]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calling &lt;code&gt;devtemDesign()&lt;/code&gt; again on the same container destroys the previous instance first, so there are no leaked listeners.&lt;/p&gt;

&lt;h2&gt;
  
  
  Theme tokens
&lt;/h2&gt;

&lt;p&gt;Override any token with the &lt;code&gt;theme&lt;/code&gt; option:&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="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;accent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#ff4d6d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;accent2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#ffb703&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;bg-deep&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;#0b0710&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;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Token&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;--accent&lt;/code&gt;, &lt;code&gt;--accent2&lt;/code&gt;, &lt;code&gt;--accent3&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Brand colors and gradients&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;--text&lt;/code&gt;, &lt;code&gt;--muted&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Primary and secondary text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--bg-deep&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Page background, and text on filled buttons&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;--glass-bg&lt;/code&gt;, &lt;code&gt;--glass-border&lt;/code&gt;, &lt;code&gt;--glass-blur&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Card surfaces&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;--surface&lt;/code&gt;, &lt;code&gt;--line&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Subtle fills and dividers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--orb&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Ambient orb opacity&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Config reference
&lt;/h2&gt;

&lt;p&gt;All text fields accept HTML, so icons and inline markup work. Only pass content you trust.&lt;/p&gt;

&lt;h3&gt;
  
  
  Core and navigation
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;template&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"figsh"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;One of the 7 templates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;theme&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;object&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Token overrides&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;themeSwitcher&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;boolean or string[]&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Navbar theme button. An array limits the cycle. Choice is saved in &lt;code&gt;localStorage&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cursor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Custom cursor on or off&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;logo&lt;/code&gt;, &lt;code&gt;logoName&lt;/code&gt;, &lt;code&gt;logoHref&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;fscss logo, &lt;code&gt;"CORE"&lt;/code&gt;, &lt;code&gt;"/"&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Brand image, name and link&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;navLinks&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(string or &lt;code&gt;{ label, href }&lt;/code&gt;)[]&lt;/td&gt;
&lt;td&gt;Features, How it works, Pricing&lt;/td&gt;
&lt;td&gt;Navbar and drawer links&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;ctaText&lt;/code&gt;, &lt;code&gt;ctaHref&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;"Get started"&lt;/code&gt;, &lt;code&gt;"#"&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Navbar button&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Hero
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;heroBadge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pill above the title&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;heroTitleLine1&lt;/code&gt;, &lt;code&gt;heroTitleLine2&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;H1 lines. The second has an animated gradient&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;heroSubtitle&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Paragraph under the H1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;primaryBtnText&lt;/code&gt;, &lt;code&gt;primaryBtnHref&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Main button&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;secondaryBtnText&lt;/code&gt;, &lt;code&gt;secondaryBtnHref&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Ghost button, rendered only when text is set&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;brands&lt;/code&gt;, &lt;code&gt;brandsSubtitle&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Hero chips and a seamless marquee that pauses on hover&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Sections
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Section&lt;/th&gt;
&lt;th&gt;Keys&lt;/th&gt;
&lt;th&gt;Anchor&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Stats&lt;/td&gt;
&lt;td&gt;&lt;code&gt;stats: [{ value, label }]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#stats&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Features&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;featuresLabel&lt;/code&gt;, &lt;code&gt;featuresTitle&lt;/code&gt;, &lt;code&gt;featuresSub&lt;/code&gt;, &lt;code&gt;features: [{ title, desc, icon }]&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#features&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Steps&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;stepsLabel&lt;/code&gt;, &lt;code&gt;stepsTitle&lt;/code&gt;, &lt;code&gt;stepsSub&lt;/code&gt;, &lt;code&gt;steps: [{ title, desc }]&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#how&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Panels&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;panelsLabel&lt;/code&gt;, &lt;code&gt;panelsTitle&lt;/code&gt;, &lt;code&gt;panelsSub&lt;/code&gt;, &lt;code&gt;panels: [{ tag, title, desc }]&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pricing&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;pricingLabel&lt;/code&gt;, &lt;code&gt;pricingTitle&lt;/code&gt;, &lt;code&gt;pricingSub&lt;/code&gt;, &lt;code&gt;yearlyBadge&lt;/code&gt;, &lt;code&gt;pricing: [...]&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#pricing&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FAQ&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;faqLabel&lt;/code&gt;, &lt;code&gt;faqTitle&lt;/code&gt;, &lt;code&gt;faqSub&lt;/code&gt;, &lt;code&gt;faq: [{ q, a }]&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#faq&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CTA&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cta: { title, sub, text, href }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Stat values keep their prefix, suffix, commas and decimals, so &lt;code&gt;"$1,200"&lt;/code&gt;, &lt;code&gt;"99.9%"&lt;/code&gt; and &lt;code&gt;"12k+"&lt;/code&gt; all count up correctly.&lt;/p&gt;

&lt;p&gt;A pricing plan looks like this. A Monthly/Yearly toggle appears automatically when any plan has &lt;code&gt;yearly&lt;/code&gt;:&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Pro&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$12&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/mo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;desc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;For product landings.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;features&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;Everything in Free&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;Priority support&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="nx"&gt;cta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Go Pro&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/signup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;featured&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="nx"&gt;badge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Most popular&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;yearly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$115&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/yr&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Footer
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;footer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;tagline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Declarative UI engine for the modern web.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;© 2026 devtem-dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;heading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;links&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Docs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/docs&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="nx"&gt;social&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fab fa-github&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;href&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://github.com/devtem-dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GitHub&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="nx"&gt;legal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Privacy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/privacy&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full schema, with types and defaults, lives at &lt;a href="https://design.devtem.org/api" rel="noopener noreferrer"&gt;design.devtem.org/api&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Upgrading from 0.0.2
&lt;/h2&gt;

&lt;p&gt;Three option names changed to match what the code actually reads:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;0.0.2 docs&lt;/th&gt;
&lt;th&gt;Use now&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;heroTag&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;heroBadge&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;featuresSectionLabel&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;featuresLabel&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;featuresSectionTitle&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;featuresTitle&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Good to know
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Font Awesome is optional. It is only needed for &lt;code&gt;icon&lt;/code&gt; fields and footer social icons. The hamburger, checkmarks and accordions are pure CSS.&lt;/li&gt;
&lt;li&gt;Theming uses &lt;code&gt;color-mix()&lt;/code&gt;, so you need Chrome 111+, Safari 16.2+ or Firefox 113+. Older browsers still render the page but lose some tinted surfaces.&lt;/li&gt;
&lt;li&gt;Rendering replaces the container's contents. Give the engine its own wrapper element.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Docs: &lt;a href="https://design.devtem.org/docs" rel="noopener noreferrer"&gt;https://design.devtem.org/docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Schema reference: &lt;a href="https://design.devtem.org/api" rel="noopener noreferrer"&gt;https://design.devtem.org/api&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Examples: &lt;a href="https://design.devtem.org/examples" rel="noopener noreferrer"&gt;https://design.devtem.org/examples&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Builder: &lt;a href="https://design.devtem.org/builder" rel="noopener noreferrer"&gt;https://design.devtem.org/builder&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;npm: &lt;a href="https://www.npmjs.com/package/devtemdesign" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/devtemdesign&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/devtem-dev/devtemDesign" rel="noopener noreferrer"&gt;https://github.com/devtem-dev/devtemDesign&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is MIT licensed and open to contributions. If you build something with it, I'd like to see it. Drop a link in the comments, and tell me which section you want next &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>fscss</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Create a simple form and style it with FSCSS</title>
      <dc:creator>FSCSS tutorial</dc:creator>
      <pubDate>Thu, 22 Oct 2026 08:19:26 +0000</pubDate>
      <link>https://dev.to/fscss/create-a-simple-form-and-style-it-with-fscss-j4o</link>
      <guid>https://dev.to/fscss/create-a-simple-form-and-style-it-with-fscss-j4o</guid>
      <description>&lt;p&gt;A short walkthrough: HTML structure, FSCSS for layout and chrome, then optional polish with tokens and the form module. Everything compiles to plain CSS.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. Markup first
&lt;/h3&gt;

&lt;p&gt;Keep the form boring and accessible. FSCSS does not replace labels or &lt;code&gt;name&lt;/code&gt; attributes.&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;form&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"contact"&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"contact__title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Contact&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"contact__lead"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;We’ll reply within one business day.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"field"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"field__label"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Name&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"field__input"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="na"&gt;autocomplete=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"field"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"field__label"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Email&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"field__input"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;autocomplete=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"field"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"field__label"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Message&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"field__input field__input--area"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt; &lt;span class="na"&gt;rows=&lt;/span&gt;&lt;span class="s"&gt;"4"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Send&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  2. Load FSCSS
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Prototype (CDN runtime):&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.6/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;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/fscss"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"form-page.fscss"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Or compile:&lt;/strong&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@1.2.6
fscss form-page.fscss form-page.css
&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;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"form-page.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  3. Style with layout helpers and tokens
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;stack&lt;/code&gt;, &lt;code&gt;px&lt;/code&gt; / &lt;code&gt;py&lt;/code&gt;, &lt;code&gt;rounded&lt;/code&gt;, and friends (1.2.5+) keep the sheet short. See &lt;a href="https://fscss.devtem.org/shorthands" rel="noopener noreferrer"&gt;shorthands&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="c"&gt;/* form-page.fscss */&lt;/span&gt;
&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0b1020&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--surface&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#121a30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#22304f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#e6edf7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--muted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#9fb0d0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--accent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#6366f1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--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="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;m&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;min-h&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;center&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;both&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;24px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;bg&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;--bg&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;--text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;ff&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;system-ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.contact&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;w&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="py"&gt;max-w&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;400px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;24px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;bg&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;--surface&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;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--border&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;rounded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.contact__title&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;m&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;fs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.35rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.contact__lead&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;m&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;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;--muted&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.9rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.field&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.field__label&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.8rem&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;--muted&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.field__input&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;w&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="py"&gt;px&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;py&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="py"&gt;rounded&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;--radius&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;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--border&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0a0f1e&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;--text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;font&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inherit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.field__input&lt;/span&gt;&lt;span class="nd"&gt;:focus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;outline&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--accent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;outline-offset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.field__input--area&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;vertical&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;min-h&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.btn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;mt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;px&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;py&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&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;rounded&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;--radius&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;bg&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;--accent&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;font&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inherit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;fw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;600&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.btn&lt;/span&gt;&lt;span class="nd"&gt;:hover&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;brightness&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1.08&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;What you get after compile: normal flex column + gap, axis padding, radius, and colors—no framework runtime.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Optional: reusable button with &lt;code&gt;@define&lt;/code&gt;
&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;@define&lt;/span&gt; &lt;span class="n"&gt;btn&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;#6366f1&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;
  &lt;span class="nt"&gt;display&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;inline-flex&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="nt"&gt;align-items&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;center&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="nt"&gt;justify-content&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;center&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;16&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&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="nt"&gt;border-radius&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;var&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;--radius&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="err"&gt;12&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="k"&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="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;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="nt"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;pointer&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.btn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@btn(var(--accent))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.btn-ghost&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@btn(transparent)&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;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--border&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;--text&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. Optional: &lt;code&gt;form.fscss&lt;/code&gt; module
&lt;/h3&gt;

&lt;p&gt;When you want float labels and shared field chrome instead of hand-rolled classes:&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;form-root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;form-group&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;form-input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;form-label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;form-float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;form-btn-primary&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;form&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;form-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;form-float&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;form-group&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form-input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form-label&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Markup pattern (input before label, &lt;code&gt;placeholder=" "&lt;/code&gt; for &lt;code&gt;:placeholder-shown&lt;/code&gt; tricks) is documented with the module. Use selective imports so you only pull what the page needs.&lt;/p&gt;




&lt;h3&gt;
  
  
  6. Optional: semantic styling with &lt;code&gt;pattern()&lt;/code&gt; (1.2.4+)
&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;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;55&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"soft dark form card"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="err"&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;#121&lt;/span&gt;&lt;span class="nt"&gt;a30&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="nt"&gt;border&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt; &lt;span class="nt"&gt;solid&lt;/span&gt; &lt;span class="err"&gt;#22304&lt;/span&gt;&lt;span class="nt"&gt;f&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;16&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;24&lt;/span&gt;&lt;span class="nt"&gt;px&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;span class="nc"&gt;.contact&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;soft&lt;/span&gt; &lt;span class="err"&gt;dark&lt;/span&gt; &lt;span class="err"&gt;form&lt;/span&gt; &lt;span class="err"&gt;card&lt;/span&gt;
  &lt;span class="py"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;max-w&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;400px&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;Good for role-based phrases; keep critical layout in explicit rules so the form stays predictable.&lt;/p&gt;




&lt;h3&gt;
  
  
  7. Try it in the IDE
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;a href="https://fscss.devtem.org/ide" rel="noopener noreferrer"&gt;fscss.devtem.org/ide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Paste the HTML into an &lt;code&gt;index.html&lt;/code&gt; and the FSCSS into &lt;code&gt;form-page.fscss&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ctrl+Enter&lt;/strong&gt; to compile, preview to check focus states
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export&lt;/strong&gt; when you’re ready &lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Checklist
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Labels associated with controls (wrapping &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; or &lt;code&gt;for&lt;/code&gt; / &lt;code&gt;id&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:focus&lt;/code&gt; styles visible on keyboard
&lt;/li&gt;
&lt;li&gt;Tokens on &lt;code&gt;:root&lt;/code&gt; so themes don’t require rewriting fields
&lt;/li&gt;
&lt;li&gt;Production: compiled CSS only, not the runtime
&lt;/li&gt;
&lt;/ul&gt;




&lt;ul&gt;
&lt;li&gt;Shorthands: &lt;a href="https://fscss.devtem.org/shorthands" rel="noopener noreferrer"&gt;https://fscss.devtem.org/shorthands&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docs: &lt;a href="https://fscss.devtem.org/docs" rel="noopener noreferrer"&gt;https://fscss.devtem.org/docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;IDE: &lt;a href="https://fscss.devtem.org/ide" rel="noopener noreferrer"&gt;https://fscss.devtem.org/ide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;npm: &lt;code&gt;fscss@1.2.6&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simple contact form is a good first FSCSS page: one column (&lt;code&gt;stack&lt;/code&gt;), a few fields, one button—and the same file can grow into tokens, &lt;code&gt;@define&lt;/code&gt;, or a form module without changing the HTML structure.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ui</category>
      <category>fscss</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>FSCSS layout helpers: stack, hstack, center, size, rounded, ratio-fit, and friends</title>
      <dc:creator>FSCSS </dc:creator>
      <pubDate>Wed, 21 Oct 2026 09:14:55 +0000</pubDate>
      <link>https://dev.to/fscss/fscss-layout-helpers-stack-hstack-center-size-rounded-ratio-fit-and-friends-4jg</link>
      <guid>https://dev.to/fscss/fscss-layout-helpers-stack-hstack-center-size-rounded-ratio-fit-and-friends-4jg</guid>
      <description>&lt;p&gt;&lt;strong&gt;FSCSS layout helpers: &lt;code&gt;stack&lt;/code&gt;, &lt;code&gt;hstack&lt;/code&gt;, &lt;code&gt;center&lt;/code&gt;, &lt;code&gt;size&lt;/code&gt;, &lt;code&gt;rounded&lt;/code&gt;, &lt;code&gt;ratio-fit()&lt;/code&gt;, and friends&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;From version 1.2.5 FSCSS added a set of &lt;strong&gt;property shorthands&lt;/strong&gt; aimed at everyday layout and chrome—spacing axes, flex stacks, sizing, and aspect boxes—without inventing a new component system. They compile to ordinary CSS. Use them in &lt;code&gt;.fscss&lt;/code&gt; (CLI, runtime, or &lt;a href="https://fscss.devtem.org/ide" rel="noopener noreferrer"&gt;IDE&lt;/a&gt;); production can ship the compiled sheet only.&lt;/p&gt;

&lt;p&gt;Full list and expansions: &lt;a href="https://fscss.devtem.org/shorthands" rel="noopener noreferrer"&gt;fscss.devtem.org/shorthands&lt;/a&gt; · language: &lt;a href="https://www.npmjs.com/package/fscss" rel="noopener noreferrer"&gt;fscss@1.2.5 - 1.2.6+&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Why these exist
&lt;/h3&gt;

&lt;p&gt;A lot of UI CSS is the same four ideas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Space &lt;strong&gt;along one axis&lt;/strong&gt; (padding/margin x or y)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stack&lt;/strong&gt; children (column or row + gap)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Center&lt;/strong&gt; content in a box
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Size&lt;/strong&gt; a box (square, both axes, or fit a ratio)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Native CSS can do all of that, but the typing is noisy (&lt;code&gt;display: flex; flex-direction: column; gap: …&lt;/code&gt; every time). These helpers expand at compile time so the mental model stays short.&lt;/p&gt;




&lt;h3&gt;
  
  
  Spacing axes
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Shorthand&lt;/th&gt;
&lt;th&gt;Idea&lt;/th&gt;
&lt;th&gt;Typical expansion&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;mx&lt;/code&gt; / &lt;code&gt;my&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;margin on x / y&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;margin-left&lt;/code&gt; + &lt;code&gt;margin-right&lt;/code&gt; / top + bottom&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;px&lt;/code&gt; / &lt;code&gt;py&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;padding on x / y&lt;/td&gt;
&lt;td&gt;same pattern for padding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;inset-x&lt;/code&gt; / &lt;code&gt;inset-y&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;positioned inset on one axis&lt;/td&gt;
&lt;td&gt;without forcing the other axis to &lt;code&gt;0&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;px&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;py&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;mx&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="py"&gt;max-w&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;420px&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;Use these when you only care about one axis. Prefer full &lt;code&gt;margin&lt;/code&gt; / &lt;code&gt;padding&lt;/code&gt; when all four sides share one value.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;stack&lt;/code&gt; and &lt;code&gt;hstack&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Vertical and horizontal flex stacks with gap:&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;.panel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;stack&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="c"&gt;/* column + gap */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.toolbar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;hstack&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="c"&gt;/* row + gap */&lt;/span&gt;
  &lt;span class="py"&gt;fwrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c"&gt;/* if you also use wrap helpers */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Roughly: &lt;code&gt;display: flex&lt;/code&gt;, direction column or row, and &lt;code&gt;gap&lt;/code&gt; from the value. Ideal for forms, toolbars, and card bodies where “children in a line with space between them” is the whole layout story.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;center&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Center children in the box (axis or both, depending on the form your build supports—commonly flex centering):&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;.hero&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;min-h&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;40vh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;center&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;both&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* or center: true — see docs */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Handy for empty states, icon wells, and hero blocks without repeating &lt;code&gt;align-items&lt;/code&gt; / &lt;code&gt;justify-content&lt;/code&gt; every time.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;size&lt;/code&gt; and friends
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Helper&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;size&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;width &lt;strong&gt;and&lt;/strong&gt; height (one value → square, or two values)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;max-size&lt;/code&gt; / &lt;code&gt;min-size&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;both axes’ max/min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;insert: ratio-fit();&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;size a box to a ratio inside a container&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;.avatar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;48px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;rounded&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="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.thumb&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;size&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;180px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.media&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="n"&gt;ratio-fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;9&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;&lt;code&gt;ratio-fit&lt;/code&gt; is for the common “keep 16:9 (or any ratio) without a padding-hack essay.” Exact expansion is in the &lt;a href="https://fscss.devtem.org/shorthands" rel="noopener noreferrer"&gt;shorthands reference&lt;/a&gt;—treat it as the declarative cousin of aspect-ratio + constrained width/height patterns.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;rounded&lt;/code&gt; and surface chrome
&lt;/h3&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="py"&gt;rounded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#121a30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;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;10px&lt;/span&gt; &lt;span class="m"&gt;30px&lt;/span&gt; &lt;span class="m"&gt;#0003&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;&lt;code&gt;rounded&lt;/code&gt; maps to &lt;code&gt;border-radius&lt;/code&gt;. Together with color/spacing shorthands (&lt;code&gt;bg&lt;/code&gt;, &lt;code&gt;p&lt;/code&gt;, &lt;code&gt;m&lt;/code&gt;, …) you can sketch a card shell in a few lines and still compile to standard properties.&lt;/p&gt;




&lt;h3&gt;
  
  
  Small composed example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.page&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;min-h&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;24px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0b1020&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;#e6edf7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;ff&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;system-ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.wrap&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;max-w&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;960px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;mx&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="py"&gt;stack&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="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.row&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;hstack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;fwrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;flex&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="py"&gt;min-w&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;240px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;p&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;rounded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#121a30&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="m"&gt;#22304f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;stack&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="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.icon&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;40px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;rounded&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;center&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#1b2745&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;Read it top to bottom: page padding → centered column → horizontal row of cards → each card is a vertical stack. No design-system runtime—only CSS the browser already understands after compile.&lt;/p&gt;




&lt;h3&gt;
  
  
  Runtime note: &lt;code&gt;fscss-props&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;If you only need &lt;strong&gt;property&lt;/strong&gt; shorthands in the browser (not full &lt;code&gt;@arr&lt;/code&gt; / &lt;code&gt;@define&lt;/code&gt; / &lt;code&gt;pattern()&lt;/code&gt;), &lt;a href="https://github.com/Figsh/fscss-props" rel="noopener noreferrer"&gt;fscss-props&lt;/a&gt; expands a similar surface at runtime and exposes JS APIs (&lt;code&gt;element.fscssProp&lt;/code&gt;, &lt;code&gt;fscssPropText&lt;/code&gt;) for live updates. Full language features still go through the FSCSS compiler (CLI, &lt;code&gt;runtime.js&lt;/code&gt; / &lt;code&gt;esm.js&lt;/code&gt;, or the IDE).&lt;/p&gt;




&lt;h3&gt;
  
  
  When to use what
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Goal&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;One-off page / prototype&lt;/td&gt;
&lt;td&gt;Shorthands in &lt;code&gt;.fscss&lt;/code&gt; + CDN runtime or IDE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Design tokens + charts + modules&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;@import&lt;/code&gt; packs (&lt;code&gt;st-core@v2&lt;/code&gt;, etc.) &lt;strong&gt;and&lt;/strong&gt; shorthands for local layout&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Production&lt;/td&gt;
&lt;td&gt;Compile with CLI; ship the CSS file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JS-driven tweaks of padding/size only&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;fscss-props&lt;/code&gt; or set CSS variables / longhands from JS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Shorthands do not replace modules. They remove friction &lt;strong&gt;between&lt;/strong&gt; modules—nav bars, card grids, toolbars—where flex + gap + radius is enough.&lt;/p&gt;




&lt;h3&gt;
  
  
  Try it
&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;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.6/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;Or open the &lt;a href="https://fscss.devtem.org/ide" rel="noopener noreferrer"&gt;FSCSS IDE&lt;/a&gt;, paste a &lt;code&gt;.card { stack: 12px; rounded: 16px; p: 20px; }&lt;/code&gt; block, and hit compile.&lt;/p&gt;




</description>
      <category>css</category>
      <category>webdev</category>
      <category>fscss</category>
      <category>jamstack</category>
    </item>
    <item>
      <title>st-core.fscss now automates setup in the FSCSS IDE</title>
      <dc:creator>FSCSS tutorial</dc:creator>
      <pubDate>Mon, 19 Oct 2026 14:52:06 +0000</pubDate>
      <link>https://dev.to/fscss/st-corefscss-now-automates-setup-in-the-fscss-ide-1ml5</link>
      <guid>https://dev.to/fscss/st-corefscss-now-automates-setup-in-the-fscss-ide-1ml5</guid>
      <description>&lt;p&gt;Enabling &lt;strong&gt;st-core&lt;/strong&gt; in the browser IDE no longer means hunting docs and pasting imports by hand. One terminal flow checks the package, installs helper snippets, drops a working line-chart + spider demo, compiles, and opens the preview.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/fscss-ttr/st-core.fscss" rel="noopener noreferrer"&gt;fscss-ttr/st-core.fscss&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Enable script:&lt;/strong&gt; &lt;a href="https://github.com/fscss-ttr/st-core.fscss/blob/main/xfcmds/enable.xfcmd" rel="noopener noreferrer"&gt;xfcmds/enable.xfcmd&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Package config:&lt;/strong&gt; &lt;a href="https://github.com/fscss-ttr/st-core.fscss/blob/main/package.json" rel="noopener noreferrer"&gt;package.json&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;IDE:&lt;/strong&gt; &lt;a href="https://fscss.devtem.org/ide" rel="noopener noreferrer"&gt;fscss.devtem.org/ide&lt;/a&gt; · &lt;a href="https://fscss.devtem.org/xfcmds-guide" rel="noopener noreferrer"&gt;xfcmds guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enabling &lt;strong&gt;st-core&lt;/strong&gt; in the browser IDE no longer means hunting docs and pasting imports by hand. One terminal flow checks the package, installs helper snippets, drops a working line-chart + spider demo, compiles, and opens the preview.&lt;/p&gt;


&lt;h2&gt;
  
  
  How it’s wired
&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"xfcmd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"enable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./xfcmds/enable.xfcmd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"disable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./xfcmds/disable.xfcmd"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plus the usual module metadata:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt;: &lt;code&gt;st-core&lt;/code&gt;, &lt;code&gt;version&lt;/code&gt;: &lt;code&gt;2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fscss_version&lt;/code&gt;: &lt;code&gt;&amp;gt;=1.2.3&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;file.modules&lt;/code&gt; / &lt;code&gt;remote&lt;/code&gt;: &lt;code&gt;./st-core@v2.fscss&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;file.usage.directive&lt;/code&gt;: &lt;code&gt;st-*&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Long &lt;code&gt;helpers&lt;/code&gt; list (root, container, phone, chart*, spider*, stat-card, …)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you run &lt;code&gt;libon st-core&lt;/code&gt; (or &lt;code&gt;libck st-core&lt;/code&gt; → &lt;code&gt;yes&lt;/code&gt;), the IDE loads &lt;strong&gt;enable.xfcmd&lt;/strong&gt; from the package and runs it top to bottom.&lt;/p&gt;




&lt;h2&gt;
  
  
  What enable.xfcmd does
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Announce&lt;/strong&gt; — &lt;code&gt;{name}@{version}&lt;/code&gt;, required FSCSS range, import line
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;add snippets for helpers&lt;/code&gt;&lt;/strong&gt; — one editor snippet per helper in &lt;code&gt;package.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extra snippets&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;st-data&lt;/code&gt; — sample &lt;code&gt;@arr series[...]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;st-chart-block&lt;/code&gt; — chart shell + &lt;code&gt;@st-chart-points&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;st-spider-block&lt;/code&gt; — spider shell + &lt;code&gt;@st-spider-points&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create demo project&lt;/strong&gt; under &lt;code&gt;st-core-demo/&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Line chart FSCSS (&lt;code&gt;@st-root&lt;/code&gt;, sales array, fill/line/dots/grid/axis)&lt;/li&gt;
&lt;li&gt;Spider / radar FSCSS (skills array, grid/spokes/fill/line/dots)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;index.html&lt;/code&gt; linking both + minimal markup&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open → compile → preview&lt;/strong&gt; and print next steps in the terminal
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Disable&lt;/strong&gt; only removes snippets and prints a note; it does &lt;strong&gt;not&lt;/strong&gt; delete &lt;code&gt;st-core-demo/&lt;/code&gt; (you remove that folder yourself if you want).&lt;/p&gt;




&lt;h2&gt;
  
  
  Try it in the IDE
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ctrl+`                 # terminal
libck st-core          # report + checks
yes                    # or: libon st-core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Snippets for &lt;code&gt;st-root&lt;/code&gt;, &lt;code&gt;st-chart-fill&lt;/code&gt;, &lt;code&gt;st-spider-points&lt;/code&gt;, …&lt;/li&gt;
&lt;li&gt;Files under &lt;code&gt;st-core-demo/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Preview with a weekly-style chart and a spider chart side by side
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then in any &lt;code&gt;.fscss&lt;/code&gt; tab, type a helper name (e.g. &lt;code&gt;st-chart-fill&lt;/code&gt;) to insert the snippet.&lt;/p&gt;

&lt;p&gt;Selective import still works the usual way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@import((
  st-root as root,
  st-chart-fill as area,
  st-chart-line as stroke,
  st-chart-points as points
) from st-core@v2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Read README, copy import, build HTML by hand&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;libck&lt;/code&gt; → &lt;code&gt;yes&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Guess helper names&lt;/td&gt;
&lt;td&gt;Snippets from the real helper list&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Empty workspace&lt;/td&gt;
&lt;td&gt;Runnable chart + spider demo&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Same &lt;strong&gt;xfcmd&lt;/strong&gt; model any package can use: point &lt;code&gt;package.json&lt;/code&gt; → &lt;code&gt;enable&lt;/code&gt; / &lt;code&gt;disable&lt;/code&gt; scripts, ship demos under a dedicated folder, keep &lt;code&gt;liboff&lt;/code&gt; non-destructive.&lt;/p&gt;




&lt;h2&gt;
  
  
  Related
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/fscss-ttr/st-core.fscss" rel="noopener noreferrer"&gt;st-core.fscss&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/fscss-ttr/st-core.fscss/blob/main/xfcmds/enable.xfcmd" rel="noopener noreferrer"&gt;enable.xfcmd&lt;/a&gt; · &lt;a href="https://github.com/fscss-ttr/st-core.fscss/blob/main/package.json" rel="noopener noreferrer"&gt;package.json&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://fscss.devtem.org/ide" rel="noopener noreferrer"&gt;FSCSS IDE&lt;/a&gt; · &lt;a href="https://fscss.devtem.org/xfcmds-guide" rel="noopener noreferrer"&gt;xfcmds guide&lt;/a&gt; · &lt;a href="https://github.com/fscss-ttr/FSCSS/tree/main/xfcmds" rel="noopener noreferrer"&gt;org xfcmds&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How it’s wired
&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"xfcmd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"enable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./xfcmds/enable.xfcmd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"disable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./xfcmds/disable.xfcmd"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plus the usual module metadata:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt;: &lt;code&gt;st-core&lt;/code&gt;, &lt;code&gt;version&lt;/code&gt;: &lt;code&gt;2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fscss_version&lt;/code&gt;: &lt;code&gt;&amp;gt;=1.2.3&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;file.modules&lt;/code&gt; / &lt;code&gt;remote&lt;/code&gt;: &lt;code&gt;./st-core@v2.fscss&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;file.usage.directive&lt;/code&gt;: &lt;code&gt;st-*&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Long &lt;code&gt;helpers&lt;/code&gt; list (root, container, phone, chart*, spider*, stat-card, …)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you run &lt;code&gt;libon st-core&lt;/code&gt; (or &lt;code&gt;libck st-core&lt;/code&gt; → &lt;code&gt;yes&lt;/code&gt;), the IDE loads &lt;strong&gt;enable.xfcmd&lt;/strong&gt; from the package and runs it top to bottom.&lt;/p&gt;




&lt;h2&gt;
  
  
  What enable.xfcmd does
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Announce&lt;/strong&gt; — &lt;code&gt;{name}@{version}&lt;/code&gt;, required FSCSS range, import line
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;add snippets for helpers&lt;/code&gt;&lt;/strong&gt; — one editor snippet per helper in &lt;code&gt;package.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extra snippets&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;st-data&lt;/code&gt; — sample &lt;code&gt;@arr series[...]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;st-chart-block&lt;/code&gt; — chart shell + &lt;code&gt;@st-chart-points&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;st-spider-block&lt;/code&gt; — spider shell + &lt;code&gt;@st-spider-points&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create demo project&lt;/strong&gt; under &lt;code&gt;st-core-demo/&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Line chart FSCSS (&lt;code&gt;@st-root&lt;/code&gt;, sales array, fill/line/dots/grid/axis)&lt;/li&gt;
&lt;li&gt;Spider / radar FSCSS (skills array, grid/spokes/fill/line/dots)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;index.html&lt;/code&gt; linking both + minimal markup&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open → compile → preview&lt;/strong&gt; and print next steps in the terminal
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Disable&lt;/strong&gt; only removes snippets and prints a note; it does &lt;strong&gt;not&lt;/strong&gt; delete &lt;code&gt;st-core-demo/&lt;/code&gt; (you remove that folder yourself if you want).&lt;/p&gt;




&lt;h2&gt;
  
  
  Try it in the IDE
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ctrl+`                 # terminal
libck st-core          # report + checks
yes                    # or: libon st-core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Snippets for &lt;code&gt;st-root&lt;/code&gt;, &lt;code&gt;st-chart-fill&lt;/code&gt;, &lt;code&gt;st-spider-points&lt;/code&gt;, …&lt;/li&gt;
&lt;li&gt;Files under &lt;code&gt;st-core-demo/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Preview with a weekly-style chart and a spider chart side by side
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then in any &lt;code&gt;.fscss&lt;/code&gt; tab, type a helper name (e.g. &lt;code&gt;st-chart-fill&lt;/code&gt;) to insert the snippet.&lt;/p&gt;

&lt;p&gt;Selective import still works the usual way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@import((
  st-root as root,
  st-chart-fill as area,
  st-chart-line as stroke,
  st-chart-points as points
) from st-core@v2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Read README, copy import, build HTML by hand&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;libck&lt;/code&gt; → &lt;code&gt;yes&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Guess helper names&lt;/td&gt;
&lt;td&gt;Snippets from the real helper list&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Empty workspace&lt;/td&gt;
&lt;td&gt;Runnable chart + spider demo&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Same &lt;strong&gt;xfcmd&lt;/strong&gt; model any package can use: point &lt;code&gt;package.json&lt;/code&gt; → &lt;code&gt;enable&lt;/code&gt; / &lt;code&gt;disable&lt;/code&gt; scripts, ship demos under a dedicated folder, keep &lt;code&gt;liboff&lt;/code&gt; non-destructive.&lt;/p&gt;




&lt;h2&gt;
  
  
  Related
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/fscss-ttr/st-core.fscss" rel="noopener noreferrer"&gt;st-core.fscss&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/fscss-ttr/st-core.fscss/blob/main/xfcmds/enable.xfcmd" rel="noopener noreferrer"&gt;enable.xfcmd&lt;/a&gt; · &lt;a href="https://github.com/fscss-ttr/st-core.fscss/blob/main/package.json" rel="noopener noreferrer"&gt;package.json&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://fscss.devtem.org/ide" rel="noopener noreferrer"&gt;FSCSS IDE&lt;/a&gt; · &lt;a href="https://fscss.devtem.org/xfcmds-guide" rel="noopener noreferrer"&gt;xfcmds guide&lt;/a&gt; · &lt;a href="https://github.com/fscss-ttr/FSCSS/tree/main/xfcmds" rel="noopener noreferrer"&gt;org xfcmds&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open the IDE, run &lt;code&gt;libck st-core&lt;/code&gt;, type &lt;code&gt;yes&lt;/code&gt;, and you should land on a compiled pure-CSS chart demo without leaving the browser.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to Build Dual-Pass Strokes with FSCSS Array Methods</title>
      <dc:creator>FSCSS tutorial</dc:creator>
      <pubDate>Fri, 16 Oct 2026 11:48:07 +0000</pubDate>
      <link>https://dev.to/fscss/how-to-build-dual-pass-strokes-with-fscss-array-methods-20oo</link>
      <guid>https://dev.to/fscss/how-to-build-dual-pass-strokes-with-fscss-array-methods-20oo</guid>
      <description>&lt;p&gt;&lt;code&gt;clip-path: polygon()&lt;/code&gt; can fill a shape. It cannot stroke one.&lt;/p&gt;

&lt;p&gt;So pure-CSS chart lines in &lt;strong&gt;FSCSS&lt;/strong&gt; (and libraries like st-core) fake a stroke with a &lt;strong&gt;dual-pass polygon&lt;/strong&gt;: walk the data forward for the top edge, walk it backward for a parallel edge offset by line width, fill the thin band between them.&lt;/p&gt;

&lt;p&gt;This post unpacks that pattern with &lt;code&gt;@arr&lt;/code&gt;, &lt;code&gt;inline()&lt;/code&gt;, &lt;code&gt;$&lt;/code&gt;, &lt;code&gt;count()&lt;/code&gt;, and &lt;code&gt;.reverse&lt;/code&gt; — the same building blocks used in st-core’s &lt;code&gt;@st-chart-line&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;You have points as CSS variables:&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;--st-p1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;32&lt;/span&gt;&lt;span class="o"&gt;%;&lt;/span&gt;
&lt;span class="nt"&gt;--st-p2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;55&lt;/span&gt;&lt;span class="o"&gt;%;&lt;/span&gt;
&lt;span class="nt"&gt;--st-p3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;20&lt;/span&gt;&lt;span class="o"&gt;%;&lt;/span&gt;
&lt;span class="c"&gt;/* … Y positions (top = 0%) */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You want a &lt;strong&gt;polyline with thickness&lt;/strong&gt;, not a filled area under the curve.&lt;/p&gt;

&lt;p&gt;SVG would use &lt;code&gt;stroke&lt;/code&gt; + &lt;code&gt;stroke-width&lt;/code&gt;. With only &lt;code&gt;clip-path&lt;/code&gt;, you build a closed ribbon:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;→ → → →  (along the data)
← ← ← ←  (back along data + width)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fill that ribbon with &lt;code&gt;background: var(--st-accent)&lt;/code&gt; and it reads as a line.&lt;/p&gt;




&lt;h2&gt;
  
  
  The full pattern
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.line&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="err"&gt;@arr&lt;/span&gt; &lt;span class="err"&gt;name-idx[count(@arr.name!.length,&lt;/span&gt; &lt;span class="err"&gt;1)]&lt;/span&gt;
  &lt;span class="err"&gt;@arr&lt;/span&gt; &lt;span class="err"&gt;name-reversed-idx[@arr.name-idx!.reverse]&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="nb"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;"{}
      empty-@arr.name-idx[] {
        $i: @arr.name-idx[];
        num( &amp;lt;$i - 1&amp;gt; * 100 / &amp;lt;@arr.name!.length - 1&amp;gt;)% var(--st-p$i),
      }
    "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;"{}
      empty-@arr.name-reversed-idx[] reverse {
        $i: @arr.name-reversed-idx[];
        $isLast: equal($i, 1);

        num( &amp;lt;$i - 1&amp;gt; * 100 / &amp;lt;@arr.name!.length - 1&amp;gt; )%
          calc(var(--st-p$i) + var(--st-chart-line-width)),
      }
    "&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;--st-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;--st-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="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;--st-accent&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;Assume you already have:&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;@arr&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;60&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="m"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and something (e.g. &lt;code&gt;@st-chart-points&lt;/code&gt;) that wrote &lt;code&gt;--st-p1&lt;/code&gt; … &lt;code&gt;--st-p5&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Piece by piece
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Index array — &lt;code&gt;count()&lt;/code&gt; + &lt;code&gt;@arr&lt;/code&gt;
&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;@arr&lt;/span&gt; &lt;span class="n"&gt;name-idx&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="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;name&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@arr.name!.length&lt;/code&gt; → number of data points (&lt;code&gt;5&lt;/code&gt; in the example)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;count(5, 1)&lt;/code&gt; → sequence &lt;code&gt;1, 2, 3, 4, 5&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Stored as &lt;code&gt;@arr name-idx[...]&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You loop &lt;strong&gt;indices&lt;/strong&gt;, not raw values. Y still comes from &lt;code&gt;var(--st-p$i)&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Reversed index — &lt;code&gt;.reverse&lt;/code&gt;
&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;@arr&lt;/span&gt; &lt;span class="n"&gt;name-reversed-idx&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;name-idx&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Forward: &lt;code&gt;[1, 2, 3, 4, 5]&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Reverse: &lt;code&gt;[5, 4, 3, 2, 1]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The second pass must go &lt;strong&gt;right → left&lt;/strong&gt; so the polygon boundary does not cross itself when you close the band.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. &lt;code&gt;inline("{} … ")&lt;/code&gt; — expand loops inside &lt;code&gt;polygon()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;clip-path: polygon(...)&lt;/code&gt; is one CSS declaration. FSCSS cannot drop a normal block loop in the middle of the argument list. &lt;strong&gt;&lt;code&gt;inline("...")&lt;/code&gt;&lt;/strong&gt; runs the inner FSCSS and splices the &lt;strong&gt;text result&lt;/strong&gt; into the polygon stop list.&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;inline&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;"{}
  empty-@arr.name-idx[] {
    $i: @arr.name-idx[];
    num( &amp;lt;$i - 1&amp;gt; * 100 / &amp;lt;@arr.name!.length - 1&amp;gt;)% var(--st-p$i),
  }
"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rough compile for 5 points:&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="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nt"&gt;var&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;--st-p1&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
&lt;span class="err"&gt;25&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nt"&gt;var&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;--st-p2&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
&lt;span class="err"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nt"&gt;var&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;--st-p3&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
&lt;span class="err"&gt;75&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nt"&gt;var&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;--st-p4&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
&lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nt"&gt;var&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;--st-p5&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. &lt;code&gt;empty-@arr.…[]&lt;/code&gt; — the loop form
&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;empty-&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;name-idx&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="nt"&gt;i&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;name-idx&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="c"&gt;/* emitted fragment per index */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Iterates every entry of &lt;code&gt;name-idx&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$i&lt;/code&gt; is the current index (&lt;code&gt;1&lt;/code&gt; … &lt;code&gt;N&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Whatever you write inside becomes one (or more) polygon stops&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;empty-&lt;/code&gt; prefix is the FSCSS loop driver used throughout st-core-style mixins.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;code&gt;$i&lt;/code&gt; and &lt;code&gt;var(--st-p$i)&lt;/code&gt; — dynamic custom properties
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;i&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;name-idx&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="nt"&gt;var&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;--st-p&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;i&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;$i&lt;/code&gt; is substituted at compile time, so you get &lt;code&gt;--st-p1&lt;/code&gt;, &lt;code&gt;--st-p2&lt;/code&gt;, … — one variable per vertex. That is how array length stays flexible without hardcoding eight stops.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. X spacing — &lt;code&gt;num()&lt;/code&gt; and length math
&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;num&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;i&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt; &lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="err"&gt;100&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&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;name&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="n"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&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;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;i&lt;/th&gt;
&lt;th&gt;formula (N = 5)&lt;/th&gt;
&lt;th&gt;X&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0 * 100 / 4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0%&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1 * 100 / 4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;25%&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2 * 100 / 4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;50%&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;…&lt;/td&gt;
&lt;td&gt;…&lt;/td&gt;
&lt;td&gt;…&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;code&gt;4 * 100 / 4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;100%&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Points are evenly distributed across the box, independent of how many values you pass.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Second pass — offset Y by stroke width
&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;num&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;i&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt; &lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="err"&gt;100&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&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;name&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="n"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;%&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;--st-p&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;i&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;--st-chart-line-width&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same X as the matching forward point. Y is pushed &lt;strong&gt;down&lt;/strong&gt; by &lt;code&gt;--st-chart-line-width&lt;/code&gt; (e.g. &lt;code&gt;1.5px&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Because the index array is &lt;strong&gt;reversed&lt;/strong&gt;, you traverse those offset points from the last data index back to the first.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Closing stop
&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;-100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nt"&gt;calc&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;var&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;--st-p1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nt"&gt;var&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;--st-chart-line-width&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A final stitch so the polygon closes cleanly near the start of the offset edge. (Exact close strategy can vary; st-core uses this trailing stop after the reverse loop.)&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Fill the band
&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;background&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;var&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;--st-accent&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The clipped region is only the thin ribbon — so a solid fill looks like a stroked line.&lt;/p&gt;




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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pass 1 (forward idx):
  (x1, y1) → (x2, y2) → … → (xN, yN)

Pass 2 (reversed idx, y + width):
  (xN, yN+w) → … → (x2, y2+w) → (x1, y1+w)

Close → fill
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concern&lt;/th&gt;
&lt;th&gt;Owned by&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;How many points&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;@arr.name!.length&lt;/code&gt; + &lt;code&gt;count()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Order of second edge&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.reverse&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Emitting stops inside &lt;code&gt;polygon()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;inline()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Y values&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;var(--st-p$i)&lt;/code&gt; (written elsewhere)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Thickness&lt;/td&gt;
&lt;td&gt;&lt;code&gt;var(--st-chart-line-width)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Minimal standalone sketch
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@arr&lt;/span&gt; &lt;span class="n"&gt;data&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="m"&gt;55&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="m"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;45&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c"&gt;/* write Y vars (simplified) */&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;data-idx&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="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;data&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&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="n"&gt;empty-&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;data-idx&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="nt"&gt;i&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;data-idx&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nt"&gt;--st-p&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;i&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;num&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;100&lt;/span&gt; &lt;span class="nt"&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;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;i&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;span class="nc"&gt;.line&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="py"&gt;--st-chart-line-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--st-accent&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="err"&gt;@arr&lt;/span&gt; &lt;span class="err"&gt;data-idx[count(@arr.data!.length,&lt;/span&gt; &lt;span class="err"&gt;1)]&lt;/span&gt;
  &lt;span class="err"&gt;@arr&lt;/span&gt; &lt;span class="err"&gt;data-rev[@arr.data-idx!.reverse]&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="nb"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;"{}
      empty-@arr.data-idx[] {
        $i: @arr.data-idx[];
        num(&amp;lt;$i - 1&amp;gt; * 100 / &amp;lt;@arr.data!.length - 1&amp;gt;)% var(--st-p$i),
      }
    "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;"{}
      empty-@arr.data-rev[] {
        $i: @arr.data-rev[];
        num(&amp;lt;$i - 1&amp;gt; * 100 / &amp;lt;@arr.data!.length - 1&amp;gt;)%
          calc(var(--st-p$i) + var(--st-chart-line-width)),
      }
    "&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;--st-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;--st-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="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;--st-accent&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;Host needs &lt;code&gt;position: relative&lt;/code&gt; and a defined height. Put &lt;code&gt;&amp;lt;div class="line"&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt; inside it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Polar variant (same idea)
&lt;/h2&gt;

&lt;p&gt;Spider/radar lines in st-core use the same dual-pass idea in polar space:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Forward: &lt;code&gt;var(--st-sx$i) var(--st-sy$i)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Reverse: each vertex scaled toward the center (&lt;code&gt;--st-spider-stroke-scale&lt;/code&gt;, e.g. &lt;code&gt;0.97&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Still: forward path + return path + fill the band. Only the coordinate system changes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common pitfalls
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;No index array&lt;/strong&gt; — looping raw values does not give you &lt;code&gt;$i&lt;/code&gt; for &lt;code&gt;--st-p$i&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No reverse on the second pass&lt;/strong&gt; — self-intersecting polygon, broken stroke.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forgetting &lt;code&gt;inline()&lt;/code&gt;&lt;/strong&gt; — loop syntax is invalid inside &lt;code&gt;polygon()&lt;/code&gt;’s argument list.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Width in % only&lt;/strong&gt; — prefer &lt;code&gt;px&lt;/code&gt; (or a fixed unit) for &lt;code&gt;--st-chart-line-width&lt;/code&gt; so thickness stays stable.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Points not written&lt;/strong&gt; — dual-pass only &lt;em&gt;reads&lt;/em&gt; &lt;code&gt;--st-p*&lt;/code&gt;; something must write them first.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Why FSCSS helps
&lt;/h2&gt;

&lt;p&gt;Without a preprocessor you either hardcode N stops or generate CSS in JS. With &lt;code&gt;@arr&lt;/code&gt; + &lt;code&gt;inline()&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;N is data-driven
&lt;/li&gt;
&lt;li&gt;X spacing is automatic
&lt;/li&gt;
&lt;li&gt;Reverse pass is one &lt;code&gt;.reverse&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Output is still plain CSS &lt;code&gt;clip-path&lt;/code&gt; — fast, cacheable, no chart library&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the whole dual-pass stroke trick: &lt;strong&gt;two ordered walks over the same indices, one offset, one fill.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/fscss-ttr/st-core.fscss" rel="noopener noreferrer"&gt;st-core.fscss&lt;/a&gt; — &lt;code&gt;@st-chart-line&lt;/code&gt;, &lt;code&gt;@st-spider-line&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://fscss.devtem.org" rel="noopener noreferrer"&gt;FSCSS&lt;/a&gt; — &lt;code&gt;@arr&lt;/code&gt;, &lt;code&gt;inline()&lt;/code&gt;, &lt;a href="https://fscss.devtem.org/ide" rel="noopener noreferrer"&gt;CLI&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Requires FSCSS &lt;strong&gt;1.2.x&lt;/strong&gt; for the array / import patterns used above.&lt;/p&gt;

</description>
      <category>css</category>
      <category>fscss</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to generate 1,000 CSS classes in 3 lines of FSCSS</title>
      <dc:creator>FSCSS </dc:creator>
      <pubDate>Thu, 15 Oct 2026 22:33:53 +0000</pubDate>
      <link>https://dev.to/fscss/how-to-generate-1000-css-classes-in-3-lines-of-fscss-5ep9</link>
      <guid>https://dev.to/fscss/how-to-generate-1000-css-classes-in-3-lines-of-fscss-5ep9</guid>
      <description>&lt;p&gt;&lt;strong&gt;Open this example in the FSCSS IDE:  &lt;a href="https://fscss.devtem.org/ide#code=%40arr%20classes%5B%20count(1000%2C%201)%20%5D%0A.item-%40arr.classes%5B%5D%20%7B%0A%20%20%20%20margin%3A%20%40arr.classes%5B%5Dpx%3B%0A%20%20%7D" rel="noopener noreferrer"&gt;Run it live&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It is completely normal if this looks strange at first. FSCSS uses a small “template + loop” model so you can describe a pattern once and expand it into standard CSS.&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;@arr&lt;/span&gt; &lt;span class="n"&gt;classes&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;1000&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="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;item-&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;classes&lt;/span&gt;&lt;span class="p"&gt;[]&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="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;classes&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three lines in. About a thousand rules out.&lt;/p&gt;




&lt;h2&gt;
  
  
  Line 1 — Build a list of numbers
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@arr&lt;/span&gt; &lt;span class="n"&gt;classes&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;1000&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="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Piece&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@arr classes[...]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Declare an array named &lt;code&gt;classes&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;count(1000, 1)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Count from &lt;strong&gt;1&lt;/strong&gt; up to &lt;strong&gt;1000&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Behind the scenes the list is effectively:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[1, 2, 3, …, 999, 1000]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Arrays in FSCSS are &lt;strong&gt;1-indexed&lt;/strong&gt; and string-native. &lt;code&gt;count(n, start)&lt;/code&gt; is the built-in that fills them without typing every value.&lt;/p&gt;




&lt;h2&gt;
  
  
  Line 2 — Loop the selector
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.item-&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;classes&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;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Piece&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.item-&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fixed class prefix&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@arr.classes[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Auto-loop&lt;/strong&gt;: expand this rule once per item&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Empty &lt;code&gt;[]&lt;/code&gt; means “for each entry in the array.” The compiler stamps out:&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;.item-1&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="nc"&gt;.item-2&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="nc"&gt;.item-3&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="c"&gt;/* … */&lt;/span&gt;
&lt;span class="nc"&gt;.item-1000&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;h2&gt;
  
  
  Line 3 — Reuse the same index in the value
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;    &lt;span class="nt"&gt;margin&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;classes&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="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the same loop, &lt;code&gt;@arr.classes[]&lt;/code&gt; is the &lt;strong&gt;current&lt;/strong&gt; item. For &lt;code&gt;.item-1&lt;/code&gt; that becomes &lt;code&gt;1px&lt;/code&gt;; for &lt;code&gt;.item-500&lt;/code&gt;, &lt;code&gt;500px&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So each expanded rule stays consistent: class number and property value come from the same step of the array.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final CSS (abbreviated)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.item-1&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;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.item-2&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;2px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.item-3&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;3px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;/* … hundreds of rules later … */&lt;/span&gt;
&lt;span class="nc"&gt;.item-1000&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;1000px&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;You are not shipping FSCSS to the browser forever. You either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;prototype in the &lt;a href="https://fscss.devtem.org/ide" rel="noopener noreferrer"&gt;IDE&lt;/a&gt; / runtime, or
&lt;/li&gt;
&lt;li&gt;compile with the CLI: &lt;code&gt;fscss input.fscss output.css&lt;/code&gt; and ship plain CSS.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Real-world tweaks
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Fixed step sizes&lt;/strong&gt; (e.g. spacing scale):&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;@arr&lt;/span&gt; &lt;span class="n"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;4&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="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;32&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;64&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gap-&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;steps&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;gap&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;steps&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fewer utilities, still generated:&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;@arr&lt;/span&gt; &lt;span class="n"&gt;n&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;32&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="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;m-&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;n&lt;/span&gt;&lt;span class="p"&gt;[]&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="n"&gt;calc&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;n&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.25rem&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;&lt;strong&gt;Pair with &lt;code&gt;%n()&lt;/code&gt; multiplexing&lt;/strong&gt; when several properties share one value:&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;@arr&lt;/span&gt; &lt;span class="n"&gt;n&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;8&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="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;box-&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;n&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&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="nt"&gt;width&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;height&lt;/span&gt;&lt;span class="o"&gt;[:&lt;/span&gt; &lt;span class="nt"&gt;calc&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;n&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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




&lt;h2&gt;
  
  
  Why this pattern exists
&lt;/h2&gt;

&lt;p&gt;Utility sheets and design tokens often need &lt;strong&gt;many parallel rules&lt;/strong&gt; (margins, radii, z-index layers, animation delays). Hand-writing them is slow and error-prone. A short FSCSS template:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Defines the data (&lt;code&gt;@arr&lt;/code&gt; / &lt;code&gt;count&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;Loops selectors and values together (&lt;code&gt;[]&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;Compiles to boring, predictable CSS
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Same idea powers denser modules (charts, staggered delays, icon packs)—the 1,000-class demo is just the clearest “aha.”&lt;/p&gt;




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

&lt;ol&gt;
&lt;li&gt;Open the &lt;a href="https://fscss.devtem.org/ide#code=%40arr%20classes%5B%20count(1000%2C%201)%20%5D%0A.item-%40arr.classes%5B%5D%20%7B%0A%20%20%20%20margin%3A%20%40arr.classes%5B%5Dpx%3B%0A%20%20%7D" rel="noopener noreferrer"&gt;IDE link above&lt;/a&gt;.
&lt;/li&gt;
&lt;li&gt;Press &lt;strong&gt;Ctrl+Enter&lt;/strong&gt; (Cmd on Mac) to compile.
&lt;/li&gt;
&lt;li&gt;Scroll the CSS panel — you should see &lt;code&gt;.item-1&lt;/code&gt; through &lt;code&gt;.item-1000&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then change &lt;code&gt;1000&lt;/code&gt; to &lt;code&gt;12&lt;/code&gt; or replace &lt;code&gt;count(...)&lt;/code&gt; with a hand-picked list and compile again.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;FSCSS:&lt;/strong&gt; &lt;a href="https://www.npmjs.com/package/fscss" rel="noopener noreferrer"&gt;npm&lt;/a&gt; · &lt;a href="https://fscss.devtem.org/docs" rel="noopener noreferrer"&gt;docs&lt;/a&gt; · &lt;a href="https://fscss.devtem.org/ide" rel="noopener noreferrer"&gt;IDE&lt;/a&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>fscss</category>
    </item>
    <item>
      <title>FSCSS IDE: write, compile, and preview FSCSS in the browser</title>
      <dc:creator>FSCSS tutorial</dc:creator>
      <pubDate>Thu, 15 Oct 2026 09:50:56 +0000</pubDate>
      <link>https://dev.to/fscss/fscss-ide-write-compile-and-preview-fscss-in-the-browser-33hc</link>
      <guid>https://dev.to/fscss/fscss-ide-write-compile-and-preview-fscss-in-the-browser-33hc</guid>
      <description>&lt;p&gt;FSCSS has a full &lt;strong&gt;browser IDE&lt;/strong&gt; — multi-file workspace, live compile, preview, component registry, snippets, terminal, and export — in the web app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://fscss.devtem.org/ide" rel="noopener noreferrer"&gt;fscss.devtem.org/ide&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Guide:&lt;/strong&gt; &lt;a href="https://fscss.devtem.org/ide-guide" rel="noopener noreferrer"&gt;fscss.devtem.org/ide-guide&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;Area&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Editor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Monaco + FSCSS highlighting and autocomplete (&lt;code&gt;def&lt;/code&gt;, &lt;code&gt;arr&lt;/code&gt;, &lt;code&gt;imp&lt;/code&gt;, &lt;code&gt;pat&lt;/code&gt;, …)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Files&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.fscss&lt;/code&gt;, &lt;code&gt;.css&lt;/code&gt;, &lt;code&gt;.html&lt;/code&gt;, &lt;code&gt;.js&lt;/code&gt;, folders, entry file (star)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Run&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Compile active or entry file (&lt;code&gt;Ctrl+Enter&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Preview&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Live page from HTML + all compiled CSS + JS modules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Components&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Search registry packs; one-click &lt;code&gt;@import((*) from name)&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Export&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;CSS, min CSS, standalone HTML, ZIP, JSON backup, share link&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Workspace autosaves to &lt;code&gt;localStorage&lt;/code&gt; (keys &lt;code&gt;fside:&lt;/code&gt;). Export a JSON backup if you’re in a locked-down browser.&lt;/p&gt;


&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;a href="https://fscss.devtem.org/ide" rel="noopener noreferrer"&gt;the IDE&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Edit &lt;code&gt;main.fscss&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Ctrl+Enter&lt;/code&gt;&lt;/strong&gt; — CSS on the right.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Ctrl+Shift+Enter&lt;/code&gt;&lt;/strong&gt; — compile and open preview.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export&lt;/strong&gt; when you’re happy.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On Mac, use &lt;strong&gt;Cmd&lt;/strong&gt; instead of Ctrl.&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="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;accent&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;#9&lt;/span&gt;&lt;span class="nt"&gt;d7eff&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#12121a&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;#e8e3ff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200px&lt;/span&gt; &lt;span class="m"&gt;100px&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;1rem&lt;/span&gt; &lt;span class="m"&gt;1.25rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;rounded&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="nl"&gt;border-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;accent&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;h2&gt;
  
  
  Layout (mental map)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Top:&lt;/strong&gt; Run, Preview, Auto, Export, Import, theme, settings
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Left:&lt;/strong&gt; Files · Components · Snippets · Tools
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Center:&lt;/strong&gt; tabs + editor | CSS / Preview
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bottom:&lt;/strong&gt; Terminal + Problems
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Status:&lt;/strong&gt; compiler version, errors, cursor
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Drag the dividers to resize. On phones the sidebar overlays and panes stack.&lt;/p&gt;




&lt;h2&gt;
  
  
  Components without leaving the tab
&lt;/h2&gt;

&lt;p&gt;Open &lt;strong&gt;Components&lt;/strong&gt; (&lt;code&gt;Alt+2&lt;/code&gt;). Cards load from the public libs index (with fallbacks). &lt;strong&gt;Import&lt;/strong&gt; inserts:&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;overlapui&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;at the top of the current FSCSS file (skipped if already present). &lt;strong&gt;Repo&lt;/strong&gt; jumps to GitHub. Search matches name, description, keywords.&lt;/p&gt;

&lt;p&gt;Useful packs: &lt;strong&gt;st-core&lt;/strong&gt;, &lt;strong&gt;overlapui&lt;/strong&gt;, &lt;strong&gt;circle-progress&lt;/strong&gt;, &lt;strong&gt;icon-mask&lt;/strong&gt;, and more on the &lt;a href="https://fscss.devtem.org/libraries" rel="noopener noreferrer"&gt;libraries&lt;/a&gt; page.&lt;/p&gt;




&lt;h2&gt;
  
  
  Shortcuts worth muscle memory
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Keys&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Compile&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Ctrl+Enter&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compile + preview&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Ctrl+Shift+Enter&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Command palette&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Ctrl+Shift+P&lt;/code&gt; / &lt;code&gt;F1&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auto-compile toggle&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Alt+A&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Files / Components / Snippets / Tools&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Alt+1&lt;/code&gt; … &lt;code&gt;Alt+4&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;New file&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Alt+N&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Terminal&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Ctrl+&lt;/code&gt;`&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shortcuts list&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Alt+/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Full table: &lt;a href="https://fscss.devtem.org/ide-guide" rel="noopener noreferrer"&gt;ide-guide&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Terminal
&lt;/h2&gt;

&lt;p&gt;Focus with &lt;code&gt;Ctrl+&lt;/code&gt;`. Handy commands:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;`text&lt;br&gt;
compile · all · preview&lt;br&gt;
libs [query]&lt;br&gt;
version 1.2.5&lt;br&gt;
export · help&lt;br&gt;
`&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;exec(_log, …)&lt;/code&gt; and preview &lt;code&gt;console.*&lt;/code&gt; land here too.&lt;/p&gt;




&lt;h2&gt;
  
  
  Export / share
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Compiled or minified CSS
&lt;/li&gt;
&lt;li&gt;Standalone HTML
&lt;/li&gt;
&lt;li&gt;ZIP (sources + &lt;code&gt;dist/*.css&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;JSON backup (merge or replace on import)
&lt;/li&gt;
&lt;li&gt;Share link; URL hash &lt;code&gt;#code=&lt;/code&gt; / &lt;code&gt;#run?code=&lt;/code&gt; opens shared FSCSS
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Good to know
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Remote &lt;code&gt;@import&lt;/code&gt; and the component list need &lt;strong&gt;network&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Preview is a &lt;strong&gt;sandboxed iframe&lt;/strong&gt; (no parent localStorage).
&lt;/li&gt;
&lt;li&gt;Switch compiler version in settings or &lt;code&gt;version x.y.z&lt;/code&gt; (jsDelivr &lt;code&gt;esm.min.js&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;Exposed for debugging: &lt;code&gt;window.xfscss&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Related
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://fscss.devtem.org/ide" rel="noopener noreferrer"&gt;IDE&lt;/a&gt; · &lt;a href="https://fscss.devtem.org/ide-guide" rel="noopener noreferrer"&gt;IDE guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://fscss.devtem.org/" rel="noopener noreferrer"&gt;Docs&lt;/a&gt; · &lt;a href="https://fscss.devtem.org/examples" rel="noopener noreferrer"&gt;Examples&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/fscss" rel="noopener noreferrer"&gt;npm fscss&lt;/a&gt; · &lt;a href="https://github.com/Figsh/xfscss" rel="noopener noreferrer"&gt;Figsh/xfscss&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open the IDE, hit &lt;strong&gt;Ctrl+Enter&lt;/strong&gt;, and ship the CSS when you're ready.&lt;/p&gt;

</description>
      <category>fscss</category>
      <category>tooling</category>
      <category>frontend</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Build a Pure CSS Radar Chart — Lightweight, Max Performance</title>
      <dc:creator>FSCSS </dc:creator>
      <pubDate>Sun, 11 Oct 2026 19:55:02 +0000</pubDate>
      <link>https://dev.to/fscss/build-a-pure-css-radar-chart-lightweight-max-performance-2f38</link>
      <guid>https://dev.to/fscss/build-a-pure-css-radar-chart-lightweight-max-performance-2f38</guid>
      <description>&lt;p&gt;Most radar charts pull in SVG path math or a JavaScript charting library. You can skip both.&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;st-core.fscss v2&lt;/strong&gt;, a spider (radar) chart is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an FSCSS array of scores (0–100)&lt;/li&gt;
&lt;li&gt;polar coordinates stored as CSS variables (&lt;code&gt;--st-sxN&lt;/code&gt;, &lt;code&gt;--st-syN&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;shapes drawn with &lt;code&gt;clip-path: polygon()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;rings and spokes from gradients&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No canvas. No SVG. No chart runtime on the critical path.&lt;/p&gt;

&lt;p&gt;Source: &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;/p&gt;




&lt;h2&gt;
  
  
  Here’s how it works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Data is an array
&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;@arr&lt;/span&gt; &lt;span class="n"&gt;skills&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;65&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;85&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Length can be 5, 6, 8 — whatever you need. Geometry (number of polygon vertices) is fixed when FSCSS expands the mixins.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. One mixin writes coordinates
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.spider&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@st-spider-points(skills,&lt;/span&gt; &lt;span class="err"&gt;42)&lt;/span&gt;  &lt;span class="c"&gt;/* array, max radius % of the box */&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;280px&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;280px&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;50%&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;For each index &lt;code&gt;i&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;angle = &lt;code&gt;(i - 1) × 360° / N&lt;/code&gt; (0° at the &lt;strong&gt;top&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;radius = &lt;code&gt;(value / 100) × rmax&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;CSS gets:
&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="nt"&gt;--st-sxN&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;calc&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;r&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="o"&gt;*&lt;/span&gt; &lt;span class="nt"&gt;sin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;θ&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="nt"&gt;--st-syN&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;calc&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;r&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="o"&gt;*&lt;/span&gt; &lt;span class="nt"&gt;cos&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;θ&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trig stays in the browser’s &lt;code&gt;calc()&lt;/code&gt;. Updating values later is rewriting those variables.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Renderers only read variables
&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;@st-spider-fill&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;spider-fill&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;skills&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-spider-line&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;spider-line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;skills&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-spider-dots&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;spider-dot-&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;skills&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;9px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-spider-grid&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;spider-grid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-spider-spokes&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;spider-spokes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;skills&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;fill&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Closed polygon through every &lt;code&gt;--st-sx/sy&lt;/code&gt; pair&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;line&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dual-pass polygon (outer path + path scaled toward center) so the stroke has real thickness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;dots&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Absolutely positioned markers at each vertex&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;grid&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Concentric rings (&lt;code&gt;radial-gradient&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;spokes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Thin radial axes (&lt;code&gt;conic-gradient&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Rule:&lt;/strong&gt; call &lt;code&gt;@st-spider-points&lt;/code&gt; on the &lt;strong&gt;host&lt;/strong&gt;. Children inherit. Same model as linear &lt;code&gt;@st-chart-points&lt;/code&gt; / fill / line in st-core.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Markup is plain HTML
&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;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"spider"&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;"spider-grid"&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;"spider-spokes"&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;"spider-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;"spider-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&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"spider-dot-1"&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;"spider-dot-2"&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;"spider-dot-3"&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;"spider-dot-4"&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;"spider-dot-5"&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;"spider-dot-6"&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;Dots need real nodes — the mixin emits &lt;code&gt;.spider-dot-1&lt;/code&gt; … &lt;code&gt;.spider-dot-N&lt;/code&gt; rules; it does not invent elements.&lt;/p&gt;




&lt;h2&gt;
  
  
  Here’s how values can be displayed on the dot nodes
&lt;/h2&gt;

&lt;p&gt;Markers are normal DOM nodes, so you can show the score next to (or inside) each dot without a chart API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option A — &lt;code&gt;data-value&lt;/code&gt; + CSS &lt;code&gt;::after&lt;/code&gt;
&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;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"spider-dot-1"&lt;/span&gt; &lt;span class="na"&gt;data-value=&lt;/span&gt;&lt;span class="s"&gt;"80"&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;"spider-dot-2"&lt;/span&gt; &lt;span class="na"&gt;data-value=&lt;/span&gt;&lt;span class="s"&gt;"65"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- … --&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;.spider-dot-1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nc"&gt;.spider-dot-2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nc"&gt;.spider-dot-3&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nc"&gt;.spider-dot-4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nc"&gt;.spider-dot-5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nc"&gt;.spider-dot-6&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* st-core already sets left/top from --st-sx / --st-sy */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-value&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;::after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data-value&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="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-1.4em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.65rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-variant-numeric&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tabular-nums&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;--st-text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;white-space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;pointer-events&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&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;Push labels slightly outward per axis if they collide with the polygon (different &lt;code&gt;top&lt;/code&gt; / &lt;code&gt;left&lt;/code&gt; offsets per index).&lt;/p&gt;

&lt;h3&gt;
  
  
  Option B — nested label element
&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;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"spider-dot-1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"dot-label"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;80&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;/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;.dot-label&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="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100%&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.65rem&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;--st-muted&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;
  
  
  Option C — update labels from JS with the series
&lt;/h3&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;setSeries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;host&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="nx"&gt;rmax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&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;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;css&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&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;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&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;ang&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;n&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;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;rmax&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;css&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;`--st-sx&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&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;: calc(50% + (&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; * 1%) * sin(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ang&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; * 1deg));`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;css&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;`--st-sy&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&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;: calc(50% - (&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; * 1%) * cos(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ang&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; * 1deg));`&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;dot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;host&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="s2"&gt;`.spider-dot-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="c1"&gt;// or: dot.querySelector(".dot-label").textContent = v;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;host&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="nx"&gt;cssText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;css&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;Geometry and labels stay in sync because both come from the same array pass.&lt;/p&gt;

&lt;p&gt;Axis names (Speed, Quality, …) stay outside the dots — absolute labels around the circle — so vertices stay readable at small sizes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Here’s why it’s lighter
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Traditional radar&lt;/th&gt;
&lt;th&gt;st-core radar&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Chart.js / D3 / Recharts bundle&lt;/td&gt;
&lt;td&gt;Mixins → CSS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SVG path string updates&lt;/td&gt;
&lt;td&gt;Custom properties + &lt;code&gt;clip-path&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Layout + paint on every redraw&lt;/td&gt;
&lt;td&gt;Often compositor-only if you transition &lt;code&gt;clip-path&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Library hydration before first paint&lt;/td&gt;
&lt;td&gt;CSS paints as soon as the stylesheet applies&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Compile time:&lt;/strong&gt; FSCSS expands loops into concrete &lt;code&gt;polygon()&lt;/code&gt; stops and selectors. Array &lt;strong&gt;length&lt;/strong&gt; is fixed in the stylesheet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Runtime:&lt;/strong&gt; Changing scores is assigning &lt;code&gt;--st-sxN&lt;/code&gt; / &lt;code&gt;--st-syN&lt;/code&gt; (and optional label text). No path serializer, no virtual DOM for the shape.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Size:&lt;/strong&gt; A compiled spider block is on the order of &lt;strong&gt;~1 kb&lt;/strong&gt; of CSS for the chart rules — not a 50–200 kb chart dependency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance profile:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First paint: no JS required for a static series
&lt;/li&gt;
&lt;li&gt;Updates: style recalc + composite; avoid layout thrash if size is fixed
&lt;/li&gt;
&lt;li&gt;Multi-series: extra layers are extra divs + inherited variables, not extra chart instances&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s “max performance” in the practical sense: &lt;strong&gt;minimum work per frame and minimum bytes on the wire.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Here are some use cases of spider (radar) charts
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Skills / competency matrices&lt;/strong&gt; — Speed, Quality, UX, Scale, Cost, Support for a team or candidate.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Product scorecards&lt;/strong&gt; — Compare features across dimensions (performance, price, ecosystem, docs, support).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sprint or OKR health&lt;/strong&gt; — Delivery, quality, collaboration, predictability on one glanceable shape.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security / compliance posture&lt;/strong&gt; — Control families as axes; one polygon per system or vendor.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Player or character stats&lt;/strong&gt; — Games and education UIs where polar layout is the expected metaphor.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Brand or perception studies&lt;/strong&gt; — Trust, value, innovation, service — survey averages as radii.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Anywhere humans already think in “balanced vs spiky” profiles, a radar chart communicates faster than six separate bars.&lt;/p&gt;




&lt;h2&gt;
  
  
  Here’s how to do multi-series radar charts with still pure CSS
&lt;/h2&gt;

&lt;p&gt;Each series is a &lt;strong&gt;separate host&lt;/strong&gt; with its own &lt;code&gt;@st-spider-points&lt;/code&gt;. Shared grid and spokes sit underneath.&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;st-core&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-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;st-spider-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;arr&lt;/span&gt; &lt;span class="n"&gt;seriesA&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;90&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;seriesB&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;55&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;seriesC&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;70&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="m"&gt;65&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-spider-fill&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;fill-a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seriesA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-spider-line&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;line-a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seriesA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-spider-dots&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;dot-a-&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seriesA&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="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-spider-fill&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;fill-b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seriesB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-spider-line&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;line-b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seriesB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-spider-dots&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;dot-b-&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seriesB&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="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-spider-fill&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;fill-c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seriesC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-spider-line&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;line-c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seriesC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-spider-dots&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;dot-c-&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seriesC&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="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-spider-grid&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;spider-grid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-spider-spokes-n&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;multi-spokes&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="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;multi-spider&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;320px&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;320px&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;50%&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;--st-surface&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.series-a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@st-spider-points(seriesA,&lt;/span&gt; &lt;span class="err"&gt;42)&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="py"&gt;--st-accent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ff9f43&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--st-spider-fill-opacity&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="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.series-b&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@st-spider-points(seriesB,&lt;/span&gt; &lt;span class="err"&gt;42)&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="py"&gt;--st-accent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#54a0ff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--st-spider-fill-opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.series-c&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@st-spider-points(seriesC,&lt;/span&gt; &lt;span class="err"&gt;42)&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="py"&gt;--st-accent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ff6b9d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--st-spider-fill-opacity&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="p"&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 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;"multi-spider"&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;"spider-grid"&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;"multi-spokes"&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;"series-a"&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;"fill-a"&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;"line-a"&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;"dot-a-1"&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;"dot-a-2"&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;"dot-a-3"&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;"dot-a-4"&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;"dot-a-5"&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;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"series-b"&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;"fill-b"&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;"line-b"&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;"dot-b-1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- … --&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;"series-c"&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;"fill-c"&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;"line-c"&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;"dot-c-1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- … --&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;&lt;strong&gt;Why this stays pure CSS:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No JS chart instance per series
&lt;/li&gt;
&lt;li&gt;Isolation is DOM + custom properties, not a scene graph
&lt;/li&gt;
&lt;li&gt;Opacity and accent are tokens (&lt;code&gt;--st-spider-fill-opacity&lt;/code&gt;, &lt;code&gt;--st-accent&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;Spoke count can match the axis count via &lt;code&gt;@st-spider-spokes-n(..., 5)&lt;/code&gt; without tying spokes to one series’ array&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If two series shared one host and only one &lt;code&gt;@st-spider-points&lt;/code&gt; call, the last write would win and every series would draw the same shape. Separate hosts fix that — the same multi-series rule as linear st-core charts.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;FSCSS &lt;a href="https://github.com/Figsh/xfscss" rel="noopener noreferrer"&gt;CLI&lt;/a&gt;, Vscode &lt;a href="https://marketplace.visualstudio.com/items?itemName=Figsh.fscss" rel="noopener noreferrer"&gt;extention&lt;/a&gt;, or prototyping via its &lt;a href="https://fscss.devtem.org/" rel="noopener noreferrer"&gt;cdn&lt;/a&gt;&lt;/em&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;@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;st-core&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full API in the repo: &lt;strong&gt;&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;/strong&gt;&lt;/p&gt;




&lt;p&gt;Pure CSS radar charts are not a compromise. With st-core they’re a &lt;strong&gt;styling problem&lt;/strong&gt;: arrays in, variables out, polygons on screen — lightweight by construction, fast by default.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>fscss</category>
      <category>performance</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Pure CSS Spider / Radar Charts Are Here in st-core.fscss v2</title>
      <dc:creator>FSCSS tutorial</dc:creator>
      <pubDate>Sat, 10 Oct 2026 23:11:32 +0000</pubDate>
      <link>https://dev.to/fscss/pure-css-spider-radar-charts-are-here-in-st-corefscss-v2-24on</link>
      <guid>https://dev.to/fscss/pure-css-spider-radar-charts-are-here-in-st-corefscss-v2-24on</guid>
      <description>&lt;p&gt;No SVG. No canvas. No JS charting library.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;st-core.fscss v2&lt;/strong&gt; now draws spider (radar) charts the same way it draws area and line charts: FSCSS arrays, CSS custom properties, and &lt;code&gt;clip-path: polygon()&lt;/code&gt;. The result looks like a modern product dashboard — skills matrices, multi-axis scores, team comparisons — and the payload stays tiny.&lt;/p&gt;

&lt;p&gt;The module Source:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&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;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this feels modern
&lt;/h2&gt;

&lt;p&gt;Modern UI is not “more libraries.” It’s &lt;strong&gt;clarity, density, and motion that doesn’t cost a framework&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Spider charts in st-core lean on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Token-driven color&lt;/strong&gt; — &lt;code&gt;--st-accent&lt;/code&gt;, &lt;code&gt;--st-surface&lt;/code&gt;, &lt;code&gt;--st-border&lt;/code&gt;. Change one variable; the whole chart follows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Soft polar geometry&lt;/strong&gt; — fill via &lt;code&gt;color-mix&lt;/code&gt;, stroke as a dual-pass polygon, rings and spokes as gradients. No harsh SVG strokes fighting your theme.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Composable layers&lt;/strong&gt; — grid, spokes, fill, line, dots stack as plain divs. Multi-series is just more layers with their own accent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native inheritance&lt;/strong&gt; — coordinates are custom properties. Children inherit. Multi-team cards don’t need a state tree; they need scoped hosts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That combination reads as “product UI,” not “demo from 2014.”&lt;/p&gt;




&lt;h2&gt;
  
  
  Why st-core stays lightweight
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What you don’t ship&lt;/th&gt;
&lt;th&gt;What you do ship&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Chart.js / D3 / Recharts&lt;/td&gt;
&lt;td&gt;A few &lt;code&gt;@define&lt;/code&gt; mixins&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SVG path builders&lt;/td&gt;
&lt;td&gt;&lt;code&gt;clip-path: polygon()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Canvas + DPR logic&lt;/td&gt;
&lt;td&gt;CSS &lt;code&gt;%&lt;/code&gt; + &lt;code&gt;sin()&lt;/code&gt; / &lt;code&gt;cos()&lt;/code&gt; in &lt;code&gt;calc()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hydration for the chart&lt;/td&gt;
&lt;td&gt;Optional JS that only sets variables&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Geometry is decided at &lt;strong&gt;compile time&lt;/strong&gt; from &lt;code&gt;@arr&lt;/code&gt; length. Runtime work is rewriting &lt;code&gt;--st-sxN&lt;/code&gt; / &lt;code&gt;--st-syN&lt;/code&gt; (or &lt;code&gt;--st-pN&lt;/code&gt; for linear charts). Animations can use &lt;code&gt;transition: clip-path&lt;/code&gt; on the compositor.&lt;/p&gt;

&lt;p&gt;Compiled CSS for a chart class stays on the order of &lt;strong&gt;about a kilobyte&lt;/strong&gt;, not a hundred. The page paints charts with zero chart-library JavaScript.&lt;/p&gt;

&lt;p&gt;That’s the st-core bet: &lt;strong&gt;visualization as styling&lt;/strong&gt;, not as an app runtime.&lt;/p&gt;




&lt;h2&gt;
  
  
  The one rule (same as linear charts)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Points write. Renderers read.&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;@st-spider-points(array)  →  writes --st-sxN / --st-syN on the host
@st-spider-fill / line / dots  →  only read those variables
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Call points on the &lt;strong&gt;host&lt;/strong&gt; that owns the series. Multi-series means one host per series — same pattern as multi-line area charts in v2.&lt;/p&gt;

&lt;p&gt;Angle &lt;code&gt;0°&lt;/code&gt; is at the &lt;strong&gt;top&lt;/strong&gt;. Values are 0–100 scores scaled by &lt;code&gt;rmax&lt;/code&gt; (default &lt;code&gt;42%&lt;/code&gt; of the box).&lt;/p&gt;




&lt;h2&gt;
  
  
  What you can build
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Minimal radar
&lt;/h3&gt;

&lt;p&gt;Six axes, one series, grid + spokes + fill + line + dots.&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;st-core&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-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;st-spider-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;arr&lt;/span&gt; &lt;span class="n"&gt;skills&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;65&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;85&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-spider-fill&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;spider-fill&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;skills&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-spider-line&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;spider-line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;skills&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-spider-dots&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;spider-dot-&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;skills&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;9px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-spider-grid&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;spider-grid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-spider-spokes&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;spider-spokes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;skills&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spider&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;@st-spider-points&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;skills&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&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="nt"&gt;width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;280&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;height&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;280&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;50&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="nt"&gt;var&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;--st-surface&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="p"&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 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;"spider"&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;"spider-grid"&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;"spider-spokes"&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;"spider-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;"spider-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&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"spider-dot-1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- … through .spider-dot-6 --&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;Dots need real DOM nodes — the mixin only generates the CSS.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Team comparison cards
&lt;/h3&gt;

&lt;p&gt;Two hosts, two accents, shared label layout:&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;@arr&lt;/span&gt; &lt;span class="n"&gt;teamA&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;92&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;78&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;55&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;80&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;teamB&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;68&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;82&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;62&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;58&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spider-wrap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;team-a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;@st-spider-points&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;teamA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;--st-accent&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="nt"&gt;--st-spider-fill-opacity&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;28&lt;/span&gt;&lt;span class="o"&gt;%;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.spider-wrap.team-b&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@st-spider-points(teamB,&lt;/span&gt; &lt;span class="err"&gt;42)&lt;/span&gt;
  &lt;span class="py"&gt;--st-accent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#4fffb0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--st-spider-fill-opacity&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Axis labels are ordinary absolute spans (Speed, Quality, UX, Scale, Cost, Support,...) around the circle. No special chart API — just layout.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Multi-series overlay
&lt;/h3&gt;

&lt;p&gt;One polar grid, five polygons, each series a full-size absolute layer with its own &lt;code&gt;@st-spider-points&lt;/code&gt; and &lt;code&gt;--st-accent&lt;/code&gt;. Lower &lt;code&gt;--st-spider-fill-opacity&lt;/code&gt; keeps overlaps readable.&lt;br&gt;
&lt;iframe height="600" src="https://codepen.io/editor/David-Hux/embed/01a127f4-f01c-7065-9307-00280f61dea8?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Live updates without a library
&lt;/h3&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;polarVars&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="nx"&gt;rmax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&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;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&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;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&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;ang&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;n&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;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;rmax&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s2"&gt;`--st-sx&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&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;: calc(50% + (&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; * 1%) * sin(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ang&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; * 1deg));`&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
      &lt;span class="s2"&gt;`--st-sy&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&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;: calc(50% - (&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; * 1%) * cos(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ang&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; * 1deg));`&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &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="nx"&gt;host&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="nx"&gt;cssText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;polarVars&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;65&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;55&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;85&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same length as the compiled polygon; values morph. Optional &lt;code&gt;transition&lt;/code&gt; on &lt;code&gt;clip-path&lt;/code&gt; for soft motion.&lt;/p&gt;




&lt;h2&gt;
  
  
  Under the hood (short)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Technique&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Coordinates&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;--st-sxN&lt;/code&gt; / &lt;code&gt;--st-syN&lt;/code&gt; from &lt;code&gt;sin&lt;/code&gt; / &lt;code&gt;cos&lt;/code&gt; in &lt;code&gt;calc()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fill&lt;/td&gt;
&lt;td&gt;Closed &lt;code&gt;polygon()&lt;/code&gt; + &lt;code&gt;color-mix&lt;/code&gt; with &lt;code&gt;--st-spider-fill-opacity&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stroke&lt;/td&gt;
&lt;td&gt;Dual-pass polygon; inner path scaled by &lt;code&gt;--st-spider-stroke-scale&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rings&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;radial-gradient&lt;/code&gt; stops at 20 / 40 / 60 / 80%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spokes&lt;/td&gt;
&lt;td&gt;Thin &lt;code&gt;conic-gradient&lt;/code&gt; bands from &lt;code&gt;-90deg&lt;/code&gt; + center mask&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Everything is documented in the repo: &lt;strong&gt;README&lt;/strong&gt; (API + examples), &lt;strong&gt;EXPLAINED&lt;/strong&gt; (every &lt;code&gt;@define&lt;/code&gt;), &lt;strong&gt;integration/html&lt;/strong&gt; (dual-team and multi-series demos).&lt;/p&gt;




&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;

&lt;p&gt;NPM CLI:&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
charts.fscss charts.css

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Testing via CDN:&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.5/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 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;st-core&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prefer &lt;a href="https://marketplace.visualstudio.com/items?itemName=Figsh.fscss" rel="noopener noreferrer"&gt;FSCSS CLI&lt;/a&gt; for production CSS with zero runtime preprocessor.&lt;/p&gt;

&lt;p&gt;Requires FSCSS &lt;strong&gt;v1.2.3+&lt;/strong&gt;. MIT licensed.&lt;/p&gt;




&lt;p&gt;Area and line charts proved that dashboards don’t need a JS chart runtime. Spider charts extend that idea into polar space without changing the contract: &lt;strong&gt;arrays in, custom properties out, polygons on screen.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Explore the module, the demos, and the under-the-hood write-up here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&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;/strong&gt;&lt;/p&gt;

&lt;p&gt;Pure CSS. Still lightweight. Now with radar.&lt;/p&gt;

</description>
      <category>fscss</category>
      <category>css</category>
      <category>opensource</category>
      <category>showdev</category>
    </item>
    <item>
      <title>FSCSS loops</title>
      <dc:creator>FSCSS tutorial</dc:creator>
      <pubDate>Fri, 09 Oct 2026 10:04:58 +0000</pubDate>
      <link>https://dev.to/fscss/fscss-loops-1hm0</link>
      <guid>https://dev.to/fscss/fscss-loops-1hm0</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;FSCSS loops: &lt;code&gt;@arr&lt;/code&gt;, &lt;code&gt;%n()&lt;/code&gt;, &lt;code&gt;rpt()&lt;/code&gt;, and &lt;code&gt;inline()&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;source:&lt;/strong&gt; &lt;a href="https://fscss.devtem.org/loop" rel="noopener noreferrer"&gt;fscss.devtem.org/loop&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;FSCSS loops expand arrays into &lt;strong&gt;properties&lt;/strong&gt;, &lt;strong&gt;selectors&lt;/strong&gt;, or &lt;strong&gt;value fragments&lt;/strong&gt;. They run at compile time (CLI) or in the browser runtime. The browser only ever sees plain CSS.&lt;/p&gt;

&lt;p&gt;This post is a short tour. See &lt;a href="https://fscss.devtem.org/loop" rel="noopener noreferrer"&gt;The full cheat sheet&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setup
&lt;/h2&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.5/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;p&gt;Or compile: &lt;code&gt;npm install -g fscss@1.2.5&lt;/code&gt; → &lt;code&gt;fscss in.fscss out.css&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Rules of thumb
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Arrays are &lt;strong&gt;1-indexed&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[]&lt;/code&gt; iterates; &lt;code&gt;[n]&lt;/code&gt; is a fixed index.&lt;/li&gt;
&lt;li&gt;Index lists: &lt;code&gt;count(@arr.name!.length)&lt;/code&gt; or &lt;code&gt;count(n, 1)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Put &lt;code&gt;empty{ /* preserve */ }&lt;/code&gt; &lt;strong&gt;before&lt;/strong&gt; many loop-driven rules so intermediate tokens are not treated as selectors.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;%n&lt;/code&gt; → properties · &lt;code&gt;rpt&lt;/code&gt; + &lt;code&gt;@arr[]&lt;/code&gt; → selectors · &lt;code&gt;inline("@arr[] { }")&lt;/code&gt; → fragments inside values.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Property loop — &lt;code&gt;%n()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Same value on many properties:&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;@arr&lt;/span&gt; &lt;span class="n"&gt;sizing&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max-height&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;sizing&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;sizing&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;.box&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="err"&gt;%4($sizing.list[:&lt;/span&gt; &lt;span class="err"&gt;200px;])&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;width&lt;/code&gt; / &lt;code&gt;height&lt;/code&gt; / &lt;code&gt;max-width&lt;/code&gt; / &lt;code&gt;max-height: 200px&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
Classics: &lt;code&gt;%2(width, height[: 100px;])&lt;/code&gt;. Also see &lt;a href="https://fscss.devtem.org/shorthands" rel="noopener noreferrer"&gt;1.2.5 shorthands&lt;/a&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  2. Auto-index — &lt;code&gt;:nth-child&lt;/code&gt;
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@arr&lt;/span&gt; &lt;span class="n"&gt;delays&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="m"&gt;0.3s&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="m"&gt;0.7s&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;colors&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="m"&gt;#f59e0b&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="m"&gt;#3b82f6&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;indexes&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="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;colors&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&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="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;/* preserve */&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="k"&gt;@arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indexes&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="nt"&gt;index&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;indexes&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nt"&gt;animation&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;bounce&lt;/span&gt; &lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;5&lt;/span&gt;&lt;span class="nt"&gt;s&lt;/span&gt; &lt;span class="nt"&gt;infinite&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;delays&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="p"&gt;];&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;index&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;p&gt;One rule per index — staggered delays and colors without copy-paste.&lt;/p&gt;


&lt;h2&gt;
  
  
  3. Nested selectors — &lt;code&gt;rpt()&lt;/code&gt;
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&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="no"&gt;blue&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="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;colors&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;/* preserve */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;rpt&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;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="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;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="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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;→ &lt;code&gt;div&lt;/code&gt;, &lt;code&gt;div div&lt;/code&gt;, &lt;code&gt;div div div&lt;/code&gt;, …&lt;br&gt;&lt;br&gt;
Guide: &lt;a href="https://fscss.devtem.org/nested-loop" rel="noopener noreferrer"&gt;nested-loop&lt;/a&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  4. Value fragments — &lt;code&gt;inline()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Loops inside a declaration (custom props, &lt;code&gt;clip-path&lt;/code&gt;, chart polygons):&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;@arr&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;10&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="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;40&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;idx&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="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;values&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&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="nb"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;"empty{}
@arr.idx[] {
  $i: @arr.idx[];
  --val-@arr.idx[]: @arr.values[$i!]px;
}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pair with &lt;a href="https://fscss.devtem.org/num" rel="noopener noreferrer"&gt;&lt;code&gt;num()&lt;/code&gt;&lt;/a&gt; for spacing math&lt;/p&gt;




&lt;h2&gt;
  
  
  5. &lt;code&gt;empty{ /* preserve */ }&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Loop machinery can look like selectors. A leading:&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;empty&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;/* preserve */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;keeps &lt;code&gt;rpt&lt;/code&gt; / auto-index / &lt;code&gt;inline&lt;/code&gt; blocks from eating the surrounding structure (1.2.1+)&lt;/p&gt;




&lt;h2&gt;
  
  
  next
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resource&lt;/th&gt;
&lt;th&gt;URL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Loops (canonical)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://fscss.devtem.org/loop" rel="noopener noreferrer"&gt;fscss.devtem.org/loop&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Arrays&lt;/td&gt;
&lt;td&gt;&lt;a href="https://fscss.devtem.org/arrays" rel="noopener noreferrer"&gt;/arrays&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Array methods&lt;/td&gt;
&lt;td&gt;&lt;a href="https://fscss.devtem.org/array-methods" rel="noopener noreferrer"&gt;/array-methods&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;num &amp;amp; count&lt;/td&gt;
&lt;td&gt;&lt;a href="https://fscss.devtem.org/num" rel="noopener noreferrer"&gt;/num&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Examples&lt;/td&gt;
&lt;td&gt;&lt;a href="https://fscss.devtem.org/examples" rel="noopener noreferrer"&gt;/examples&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>fscss</category>
      <category>tutorial</category>
      <category>webdev</category>
      <category>css</category>
    </item>
    <item>
      <title>Introducing overlapui.css — drop-in overlap stacks for any stack</title>
      <dc:creator>FSCSS </dc:creator>
      <pubDate>Tue, 06 Oct 2026 16:17:58 +0000</pubDate>
      <link>https://dev.to/fscss/introducing-overlapuicss-drop-in-overlap-stacks-for-any-stack-3m27</link>
      <guid>https://dev.to/fscss/introducing-overlapuicss-drop-in-overlap-stacks-for-any-stack-3m27</guid>
      <description>&lt;p&gt;You want stacked avatars, a peeking card pile, or a “+” that fans into actions — and you don’t want a JS component library or an FSCSS build step just for that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;overlapui.css&lt;/strong&gt; is the plain-CSS build of &lt;a href="https://github.com/fscss-ttr/overlapui.fscss" rel="noopener noreferrer"&gt;overlapui&lt;/a&gt;: same behavior as the FSCSS module, shipped as a &lt;strong&gt;single stylesheet&lt;/strong&gt; you can link from npm or jsDelivr and use with &lt;strong&gt;utility class names&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Works with &lt;strong&gt;any modern web setup&lt;/strong&gt;: static HTML, React, Vue, Svelte, Next, Nuxt, Astro, WordPress themes — if you can load a CSS file, you can use it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;npm&lt;/strong&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;overlapui
&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;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"node_modules/overlapui/overlapui.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;CDN&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;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;
  &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/overlapui@1.0.0/overlapui.min.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;CSS import&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;@import&lt;/span&gt; &lt;span class="sx"&gt;url("https://cdn.jsdelivr.net/npm/overlapui@1.0.0/overlapui.min.css")&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No FSCSS process required for this path.&lt;/p&gt;




&lt;h2&gt;
  
  
  Utility classes (drop-in)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Class&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.avatar-overlap&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Horizontal face stack (&lt;code&gt;data-alph&lt;/code&gt; + optional &lt;code&gt;img&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.card-overlap&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Vertical notification / card stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.img-overlap&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Overlapping photo strip&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.circle-overlap&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Radial menu (&lt;code&gt;--n&lt;/code&gt; = satellite count)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Theme with &lt;strong&gt;&lt;code&gt;--ou-*&lt;/code&gt;&lt;/strong&gt; variables on &lt;code&gt;:root&lt;/code&gt; or a parent — no preprocessor.&lt;/p&gt;




&lt;h2&gt;
  
  
  Minimal example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;overlapui CSS-only&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;
    &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/overlapui@1.0.0/overlapui.min.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="py"&gt;--ou-center-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#6366f1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="py"&gt;--ou-ring&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0f172a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;body&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;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;min-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="py"&gt;place-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;48px&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;#0b1220&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;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"avatar-overlap"&lt;/span&gt; &lt;span class="na"&gt;tabindex=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;data-alph=&lt;/span&gt;&lt;span class="s"&gt;"g"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;G&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;data-alph=&lt;/span&gt;&lt;span class="s"&gt;"h"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;H&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;data-alph=&lt;/span&gt;&lt;span class="s"&gt;"i"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;I&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;data-alph=&lt;/span&gt;&lt;span class="s"&gt;"j"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;J&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ul&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;"circle-overlap"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"--n:5"&lt;/span&gt; &lt;span class="na"&gt;tabindex=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Menu"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;+&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Home"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;H&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Search"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;S&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Chat"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;C&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Groups"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;G&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Profile"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;P&lt;span class="nt"&gt;&amp;lt;/a&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;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hover or focus a stack to open it. Interaction is &lt;strong&gt;CSS-only&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Frameworks
&lt;/h2&gt;

&lt;p&gt;Same classes in JSX/Vue/Svelte markup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"avatar-overlap"&lt;/span&gt; &lt;span class="na"&gt;tabIndex&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;data-alph&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Ada&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;data-alph&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"b"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Bo&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Import once in the app shell (&lt;code&gt;layout.css&lt;/code&gt;, &lt;code&gt;global.css&lt;/code&gt;, or &lt;code&gt;import 'overlapui/overlapui.css'&lt;/code&gt;).&lt;/p&gt;




&lt;h2&gt;
  
  
  Lightweight by design
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Compiled from &lt;strong&gt;overlapui.fscss&lt;/strong&gt; — one focused module, not a full design system
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No runtime JS&lt;/strong&gt; for open/close
&lt;/li&gt;
&lt;li&gt;Tokens (&lt;code&gt;--ou-size&lt;/code&gt;, &lt;code&gt;--ou-overlap&lt;/code&gt;, &lt;code&gt;--ou-center-bg&lt;/code&gt;, …) keep restyles local
&lt;/li&gt;
&lt;li&gt;Prefer the &lt;strong&gt;FSCSS source&lt;/strong&gt; when you need custom selectors or a smaller selective compile; use &lt;strong&gt;&lt;code&gt;.css&lt;/code&gt;&lt;/strong&gt; when you want drop-in speed
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;npm:&lt;/strong&gt; &lt;code&gt;overlapui&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/fscss-ttr/overlapui.fscss" rel="noopener noreferrer"&gt;github.com/fscss-ttr/overlapui.fscss&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Drop in the file. Use the classes. Ship the stack.&lt;/p&gt;

</description>
      <category>css</category>
      <category>frontend</category>
      <category>ui</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Free visual builder for pure CSS charts — st-core.fscss</title>
      <dc:creator>FSCSS tutorial</dc:creator>
      <pubDate>Tue, 06 Oct 2026 11:44:25 +0000</pubDate>
      <link>https://dev.to/fscss/free-visual-builder-for-pure-css-charts-st-corefscss-3eod</link>
      <guid>https://dev.to/fscss/free-visual-builder-for-pure-css-charts-st-corefscss-3eod</guid>
      <description>&lt;p&gt;You can design a line or area chart, toggle grid and dots, pick an accent, and leave with &lt;strong&gt;FSCSS, HTML, and CSS&lt;/strong&gt;—without wiring Chart.js or an SVG library.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://hub.devtem.org/st-core.fscss/visual-builder/" rel="noopener noreferrer"&gt;st-core Visual Chart Builder&lt;/a&gt;&lt;/strong&gt; is free and open-source. It sits on &lt;strong&gt;st-core@v2&lt;/strong&gt;: charts as CSS custom properties and &lt;code&gt;clip-path&lt;/code&gt; polygons, driven by FSCSS arrays.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Module:&lt;/strong&gt; &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;/p&gt;




&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;Most “chart builders” emit React, canvas, or heavy chart SDKs. This one is aimed at &lt;strong&gt;lightweight, pre-designed, modern charts&lt;/strong&gt; that ship as CSS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No SVG / canvas requirement&lt;/strong&gt; for the core series
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Any length&lt;/strong&gt; dataset (&lt;code&gt;@arr&lt;/code&gt;), not a fixed 8 points
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;X spacing&lt;/strong&gt; from &lt;code&gt;array.length&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Y&lt;/strong&gt; as normalized &lt;code&gt;--st-p1&lt;/code&gt; … &lt;code&gt;--st-pN&lt;/code&gt; (&lt;code&gt;100 − value&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;Optional &lt;strong&gt;JS&lt;/strong&gt; only when you want to live-update those variables
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The builder is a front door: tune data and layers, preview, copy code.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the builder gives you
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Control&lt;/th&gt;
&lt;th&gt;Effect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Data list&lt;/td&gt;
&lt;td&gt;Comma / space separated values 0–100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Presets&lt;/td&gt;
&lt;td&gt;Rising, Decline, Volatile, Flat, Climb, Peaks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Layers&lt;/td&gt;
&lt;td&gt;Fill, line, grid, dots&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Height / radius&lt;/td&gt;
&lt;td&gt;Chart box&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Accent&lt;/td&gt;
&lt;td&gt;&lt;code&gt;--st-accent&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grid rows / cols&lt;/td&gt;
&lt;td&gt;Background grid density&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Array &amp;amp; class names&lt;/td&gt;
&lt;td&gt;Generated selectors&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Outputs&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;FSCSS&lt;/strong&gt; — &lt;code&gt;@import&lt;/code&gt; st-core@v2, &lt;code&gt;@arr&lt;/code&gt;, &lt;code&gt;@st-chart-*&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTML&lt;/strong&gt; — full minimal page with runtime script
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSS&lt;/strong&gt; — approximate or runtime-expanded rules
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Preview uses the &lt;strong&gt;FSCSS ESM API&lt;/strong&gt; with stable version, with a &lt;strong&gt;polygon fallback&lt;/strong&gt; so the chart still paints if compile fails.&lt;/p&gt;




&lt;h2&gt;
  
  
  The chart model (what you’re designing)
&lt;/h2&gt;

&lt;p&gt;Minimal mental model:&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;st-core&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-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;arr&lt;/span&gt; &lt;span class="n"&gt;myData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;56&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;67&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;43&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;67&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-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="n"&gt;myData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;st-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="n"&gt;myData&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="k"&gt;@st-chart-points&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;myData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&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="nt"&gt;height&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;220&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;width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%;&lt;/span&gt;
  &lt;span class="nt"&gt;max-width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;520&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="nt"&gt;var&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;--st-surface&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;12&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;overflow&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;hidden&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="p"&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 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;"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;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;@st-chart-fill&lt;/code&gt; / &lt;code&gt;@st-chart-line&lt;/code&gt;&lt;/strong&gt; — renderer for a selector (how many points the polygon expects).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;@st-chart-points&lt;/code&gt;&lt;/strong&gt; — writes &lt;code&gt;--st-pN&lt;/code&gt; on the element (the actual Y values).
&lt;/li&gt;
&lt;li&gt;Children can inherit points from a parent, or set their own for multi-series.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Runtime / CDN:&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.5/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;h2&gt;
  
  
  Live updates (optional JS)
&lt;/h2&gt;

&lt;p&gt;Same variables the builder sets on the preview:&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;updatePoints&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&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;el&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="nx"&gt;cssText&lt;/span&gt; &lt;span class="o"&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;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`--st-p&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&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="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;v&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="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &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="nf"&gt;updatePoints&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="s2"&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;60&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;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pair with &lt;code&gt;transition&lt;/code&gt; on &lt;code&gt;clip-path&lt;/code&gt; for soft redraws—exactly what the generated snippets include.&lt;/p&gt;




&lt;h2&gt;
  
  
  Who it’s for
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dashboards&lt;/strong&gt; that should stay CSS-first and cacheable
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design / content&lt;/strong&gt; people who want a chart without a JS chart stack
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;dev&lt;/strong&gt; who need a correct &lt;code&gt;@arr&lt;/code&gt; + mixin skeleton before pasting into a larger layout (phone shell, stat cards, multi-series)
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;v2 is the path for new work: dynamic length, even X spacing, dual-edge line polygons. Details live in the module README and &lt;code&gt;EXPLAINED.md&lt;/code&gt;.&lt;/p&gt;




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

&lt;ol&gt;
&lt;li&gt;Open &lt;strong&gt;&lt;a href="https://hub.devtem.org/st-core.fscss/visual-builder/" rel="noopener noreferrer"&gt;Visual Chart Builder&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enter points or click a preset
&lt;/li&gt;
&lt;li&gt;Toggle fill / line / grid / dots
&lt;/li&gt;
&lt;li&gt;Copy &lt;strong&gt;CSS&lt;/strong&gt;, &lt;strong&gt;FSCSS&lt;/strong&gt; or &lt;strong&gt;HTML&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Ship with CLI compile when you want:
&lt;/li&gt;
&lt;/ol&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@latest
fscss chart.fscss chart.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Builder (free):&lt;/strong&gt; &lt;a href="https://hub.devtem.org/st-core.fscss/visual-builder/" rel="noopener noreferrer"&gt;hub.devtem.org/st-core.fscss/visual-builder&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Module (open source):&lt;/strong&gt; &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;/ul&gt;

&lt;p&gt;Pre-designed doesn’t have to mean heavy. With st-core, the “design” is tokens and polygons—and the builder is there so you can see it before you commit a single line to production.&lt;/p&gt;

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