Contact

Currently building at the Recurse Center

Building a VSCode extension for CSS variables

šŸ”—
CSVars on Microsoft Marketplace

I tend to do a lot of frontend work with vanilla css, and sometimes css modules which have been my tools of choice since moving away from Stitches. I really like to have a design system (or a system of any kind) when working on a project because going back to cross-reference values is exhausting and Tailwind is a great utility to diminish this headache greatly but I like to treat Tailwind as what it is ā€“ a utility. CSS is wide, broad and rather intricate. I sincerely do not think that a Swiss Army knife replaces a full tool kit for building anything worth its weightā€”sure, itā€™s handy if Iā€™m stranded in the woods and need to open a can of beans, but for real work? Iā€™d rather not hack my way through with a spork and a mini-screwdriver. Give me the right tool for the job every time.

As such, I tend to use both vanilla CSS and tailwind in most cases because px-auto and way faster than having to type out padding-inline: auto; or padding-left: auto; padding-right: auto; for the uninitiated. But here lies the case where I like to be very specific with my CSS and CSS Variables fill that role for me perfectly, especially in the scenario where I have to toggle themes and values. The drawback here is not being able to get a reference to the value when I want to use it. Enter CSVars.

This is what it looks like in use CSVars completion example

index.css is defined as so:

:root {
  --primary-color: #3498db; /* Main brand color used for CTAs, links, and highlights */
}

index.css

Why CSS variables and not extend Tailwind styles?

Well Iā€™m glad you asked. The most obvious reason here would be that I would be constricted to Tailwind when I need theme-specific styling. When the codebase grows larger, packages would be added and they would need to be styled. Say I was using a Radix primitive, I would like to have the option to have themes for my primitive and defining this in CSS is way more readable to me (opinions may vary) than writing out Tailwind shortcuts on one single line where my editor canā€™t fully breathe.

button {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 8px; /* For when there's a prefix or suffix icon */
	width: max-content;
	height: 40px;
	padding-inline: 12px;
	border-radius: 8px;
	font-size: 12px;
	color: var(--color-text-strong);
	background-color: var(--color-primary);
	pointer: cursor;
}

button[data-variant:"secondary"] {
	color: var(--color-text-surface);
	background-color: var(--color-secondary)
}

button.css

The Tailwind equivalent of this would look something like this:

<!-- Primary Button -->
<button class="flex items-center justify-center gap-2 w-max h-10 px-3 rounded-lg text-xs text-[var(--color-text-strong)] bg-[var(--color-primary)] cursor-pointer">
	Primary Button
</button>

<!-- Secondary Button -->
<button class="flex items-center justify-center gap-2 w-max h-10 px-3 rounded-lg text-xs text-[var(--color-text-surface)] bg-[var(--color-secondary)] cursor-pointer" data-variant="secondary">
	Secondary Button
</button>

button.html

Or if we wanted to go the @apply way would do this:

<!-- HTML Structure -->
<button class="btn-primary">
	Primary Button
</button>

<button class="btn-secondary">
	Secondary Button
</button>
@layer components {
  .btn-primary {
    @apply flex items-center justify-center gap-2 w-max h-10 px-3 rounded-lg text-xs cursor-pointer;
    color: var(--color-text-strong);
    background-color: var(--color-primary);
  }
  
  .btn-secondary {
    @apply flex items-center justify-center gap-2 w-max h-10 px-3 rounded-lg text-xs cursor-pointer;
    color: var(--color-text-surface);
    background-color: var(--color-secondary);
  }
}

haha would you look at that we still fall back to css

Thereā€™s probably a more hacky way to get this done but Iā€™m scared to look it up.

There is also the issue of separation of concern. I like the idea of having different things sit in different places according to their use. The way one would create a folder for hooks should be the same way one should have an button.css or an button.module.css. I tend to skim over code according to keywords and I do not read lines fully so the absence of line breaks and the consolidation that Tailwind aims to provide does not really help me understanding what is happening with my styles.

Third reason would be portability. I want to know that the styles that I write are being written in the language that the engine would use and not something that is interpreted and going to be converted into css at the end of the day. Working with Barima Effah (CTO) at NewComma opened up my eyes to this because when he would work on his design system, he would go into detail with PostCSS and css variables were abundant because they just simply worked! No need remembering what the hex code for the dropdown is when it can be referenced anywhere with a css variable. That is peak state management to me.

I love Tailwind and it really shines when you want to get up and go without having worrying about defining styling, especially colors, from scratch but I canā€™t help to fall back to good olā€™ css when I need to be more specific.

How does CSVars work?

Itā€™s really simple. It watches for file changes (triggered by file saves) and gathers all the saved variables for you to reference. The completion is triggered when the user types in var( . A completion dropdown shows up next to your cursor with a list of available variables and filters based on the current text you typed in so far. The cherry on top is you have a preview of your values right there, just like TailwindšŸ‘šŸ½. This way you can glance through and pick exactly what youā€™re looking for. In the details section of the highlights completion, you will find the full definition of the variable, The comment associated with the variable and where the variable can be found (filename : line number)

Caveats

Please try out CSVars and let me know what you think, bad or good. Thank you for reading through my ramblingsšŸ˜„