The same rule, written three ways
Stylus treats braces, semicolons, and colons as optional. Every version below compiles to identical CSS, so the choice is about the people reading the file rather than the output. Two flat rules go in, one nested block comes out, and the punctuation drops off a step at a time.
.alert-bar {padding: 12px 16px;color: #1d4a3a;.close {opacity: 0.6;}}.alert-bar
padding: 12px 16px
color: #1d4a3a
.close
opacity: 0.6.alert-bar
padding 12px 16px
color #1d4a3a
.close
opacity 0.6Pick the middle one when a team writes both CSS and Stylus, since a reviewer coming from plain CSS still reads declarations at a glance. Pick the first while a migration is half finished and a file holds both dialects. The third suits people who write Stylus daily and know where the parser gets ambiguous, which is the subject of the next section.
Four places where dropping the colon changes the meaning
Whitespace syntax reads a declaration as a property followed by a value. Some values break that reading. The converter keeps the colon on the first three cases below and counts them under the output pane, so you never have to spot them yourself.
margin resolves to, not as part of the number. Written with a colon, the value stays a value. Same story for a leading plus.filter: progid:DXImageTransform syntax. Two colons on one line give the parser a split point in the wrong place.border-radius in any imported file swallows this line and runs instead of the property. The converter reads one stylesheet and never sees your imports, so this one stays yours to check.Indentation carries the structure now
With braces gone, whitespace is the syntax. Four habits keep a converted file compiling.
- Match the indent unit already used in the destination file. Tabs and spaces do not mix inside one Stylus file, and the compiler error points at the line after the real problem.
- Watch the depth. Every nesting level adds an indent, and past three or four the block drifts off the right edge while the selector it produces gets heavier than the page needs.
- Convert one stylesheet at a time. A whitespace driven diff is harder to review than a braced one, and a concatenated bundle produces a single wall of indentation nobody checks properly.
- Compile before you commit. The output here is generated from a parse of your CSS, not from Stylus itself, so a run through the real compiler is the check that counts.
Why the named values arrive with a dollar sign
Stylus assigns with = and needs no sigil at all, so brand = #2f6f57 is legal. Bare names share a namespace with property names and with those transparent mixins, which is how a variable called filter or mask turns into a puzzle three months later. The dollar prefix sits outside that namespace, so the output uses $color-1 and up.
A value earns a name after it appears twice. Three groups qualify:
- Colors. Hex in three to eight digits, the
rgb()andhsl()families, the neweroklch()andlab()functions, and the named colors. - Font stacks. Any
font-familyholding a comma. A stack repeated across headings and body copy is the clearest token in most stylesheets. - Function shaped values. Shadows, gradients, transitions, transforms, filters, masks, and clip paths. A shadow like
0 4px 20px rgba(18,32,27,0.09)repeated across six components is the strongest argument for a preprocessor in the first place.
What passes through untouched:
- Single lengths. A
padding: 24pxwritten forty times stays24px. Spacing numbers repeat for unrelated reasons, and$value-7reads worse than the number it replaced. - Custom properties and anything reading
var(). Those already work at runtime. Moving them to compile time breaks any theme switch that writes them from JavaScript. - Bodies of
@keyframesand@font-face. They copy across as written, colors included. A named value inside a keyframe step hides more than it saves.
Rename before the file lands in a repository.$color-1 and $shadow-2 are numbered in order of appearance and carry no meaning. $brand-green and $card-shadow do. Use Copy the assignments to lift the block into a variables.styl partial while you rename, since that partial is where the rest of the project will look for them.
Comments come out as block comments
Stylus has two comment forms and they behave differently. A // line is dropped during compilation and never reaches the browser. A block survives into the compiled CSS. Converting a licence header or an attribution note into // would quietly delete it from your production file, so every comment stays in block form here. Turn the switch off when you want the noise gone instead.
Two other things move during conversion, worth reading in the diff. Repeated selectors merge, so a sheet declaring .btn on line 12 and again on line 400 comes back as one block, which shifts the position of any rule that sat between them. And nesting hides specificity behind indentation without lowering it, so #app .layout .link still outweighs a single class after the compile.
Is Stylus the right destination?
This page converts syntax. Mixins, functions, @extend, partials and @import layout, iteration, and the Stylus color maths are all decisions about intent, and a converter guessing at intent writes code nobody trusts. Expect a starting point, then a pass by hand.
The larger question is whether the destination is worth the trip. Stylus releases arrive rarely now and much of the tooling built around it has gone quiet, while browsers ship native CSS nesting that covers the part most people wanted from a preprocessor. If a .styl codebase already runs in production and a vendor snippet needs folding into it, this converter is the right tool. If a new project is choosing a preprocessor from scratch, Sass has the bigger ecosystem and plain CSS with native nesting has no build step at all.
Everything runs inside your browser tab, so a client stylesheet uploads nothing and nothing persists between visits. A few thousand rules convert in well under a second. When you want to check the trade, send the result through the Stylus to CSS converter and diff the compiled output against the file you started with.
