Cautions

Important cautions when using Atomic CSS. Understanding these helps prevent unexpected issues.

Dynamic Class Binding

Most common mistake

Atomic CSS statically scans source code to detect classes. Class names stored in JavaScript variables are not detected.

Cause

The Atomic CSS extension analyzes source code text at save time to find used class names and generates only the corresponding CSS. Since JavaScript is not executed, strings inside variables cannot be tracked.

Not detected

Dynamic binding via variables cannot detect classes.

<!-- ❌ Class in variable — CSS not generated -->
<script setup>
const boxStyle = "w100px h100px bg6366F1 br8px"
</script>

<div :class="boxStyle"></div>

Detected

Class names that exist as literals in source code are properly detected.

<!-- ✅ Literal class — CSS generated normally -->
<div class="w100px h100px bg6366F1 br8px"></div>

Dynamic Binding in Frameworks

The same issue occurs when dynamically binding classes in Vue, React, Svelte, etc.

Not detected

<!-- ❌ v-for + dynamic binding -->
<script setup>
const items = [
  { cls: "bg6366F1 br8px" },
  { cls: "bg34D399 br12px" },
]
</script>

<div v-for="item in items"
     :class="item.cls">
</div>

Detected

<!-- ✅ Conditionals also as full strings -->
<div :class="active
  ? 'bg6366F1 cFFFFFF'
  : 'bg27272A c71717A'">
</div>

<!-- ✅ This way both class sets are
     present as literals in source and detected -->

String Concatenation Also Fails

Template literals or string concatenation to build class names are also not detected.

Not detected

// ❌ Class generated by string concatenation
const size = 16
const cls = `fs${size}px`  // "fs16px"
// → No "fs16px" literal in source

// ❌ Class generated by function
function getBg(color) {
  return `bg${color}`
}
getBg("FF0000")  // "bgFF0000"
// → No "bgFF0000" literal in source

Detected

// ✅ Use full class names as literals
const cls = isLarge ? 'fs2rem' : 'fs1-4rem'
// → Both 'fs2rem' and 'fs1-4rem' are detected

// ✅ List as literals in map object
const sizeMap = {
  sm: 'fs1-2rem p8px',
  md: 'fs1-4rem p12px',
  lg: 'fs1-6rem p16px',
}
// → All values exist as literals and are detected

Core Principle

The complete class name string must exist as-is somewhere in the source code. Concatenation, splitting, and variable references are not detected.

Class Name Conflicts

Atomic CSS creates class names from the initials of CSS properties, so different properties may share the same abbreviation. They are differentiated by presence of units.

ClassCSSDifferentiation
fs0flex-shrink: 0No unit → flex-shrink
fs16pxfont-size: 16pxWith unit → font-size
fs1-4remfont-size: 1.4remWith unit → font-size
br8pxborder-radius: 8pxWith unit → border-radius
br0border-radius: 0border-radius reset
brnborder-right: 0border-right removal

When in doubt

Use autocomplete. When you type a class name, the hover preview immediately shows what CSS will be generated. When unsure, verify instead of guessing.

Missing Units

Properties that use numeric values must include units. Without units, they may be interpreted as different properties or not work at all.

No unit — unintended result

fs16Does not work (unit required)
w100Does not work (unit required)
gap10Does not work (unit required)
br0border-radius: 0

With unit — correct result

fs16pxfont-size: 16px
w100pxwidth: 100px
gap10pxgap: 10px
br0border-radius: 0

Unit rules summary

  • px — Pixels: w100px, gap8px
  • rem — 1rem=10px: w10rem(100px), gap2rem(20px)
  • p — Percent: w50p(50%), w100p(100%)
  • vh / vw — Viewport: h100vh, w100vw

CSS Cascade Order (Specificity)

All Atomic CSS classes have the same selector specificity (single class). When multiple classes target the same property, the one declared later in the CSS file takes effect. This is not determined by order in the HTML class attribute.

<!-- ⚠️ Which applies, w100px or w200px? -->
<div class="w100px w200px bg18181B p16px">
  Determined by declaration order in CSS file
  (Not by order in HTML class attribute)
</div>

<!-- ✅ Use only one class per property -->
<div class="w200px bg18181B p16px">
  Specify only one clearly
</div>

Caution

Using duplicate classes for the same property makes it hard to predict which one applies. Use only one class per property per element.

When you intentionally need to raise priority, use the i suffix which adds !important.

<!-- Add !important with i suffix -->
<div class="w100pxi bg6366F1 p16px">
  width: 100px !important
</div>

<!-- Override external library styles -->
<div class="external-component df jcc aici">
  Force layout with display: flex !important
</div>

Do not abuse !important

Use the i suffix only when truly necessary, such as overriding external library styles. Avoid using it for regular styling.

rem Base Value

Atomic CSS rem units are designed based on html { font-size: 10px }, meaning 1rem = 10px. Without this setting, rem values will not match their intended sizes.

Without base value (1rem = 16px)

fs1-6remIntended: 16px, Actual: 25.6px
gap2remIntended: 20px, Actual: 32px
w24remIntended: 240px, Actual: 384px

With base value (1rem = 10px)

fs1-6rem16px correct
gap2rem20px correct
w24rem240px correct

Add the following to your project's global CSS:

html {
  font-size: 10px;
}

/* Now rem calculations are intuitive */
/* 1.6rem = 16px */
/* 2rem = 20px */
/* 2.4rem = 24px */
/* 10rem = 100px */

Not using rem?

If you only use px values, this setting is not required. However, rem is recommended as it allows concise expression of values 20px and above.

Hyphen (-) Interpretation

Hyphens are interpreted differently depending on context. Understanding hyphen roles is essential to prevent unintended results.

UsageExampleInterpretation
Decimal pointgap1-5remgap: 1.5rem (15px)
Decimal pointfs1-4remfont-size: 1.4rem (14px)
Value separatorgtc1fr-2fr-1frgrid-template-columns: 1fr 2fr 1fr
Value separatorflex1-1-autoflex: 1 1 auto
Media querysm-dn@media (max-width: 768px) { display: none }
Pseudo-classhover-bgFF0000:hover { background-color: #FF0000 }
Negativeneg-mt10pxmargin-top: -10px

Watch for confusion

gap1-5rem means 1.5rem, not 1rem and 5rem. Whether a hyphen represents a decimal point or value separator is determined by the following unit.

Do Not Edit Generated CSS Files

Do not directly edit CSS files auto-generated by the Atomic CSS extension (such as atomic.css). The extension re-scans and overwrites the content on every file save.

Do not

  • Directly adding styles to atomic.css
  • Modifying/deleting classes in atomic.css
  • Defining custom classes in atomic.css

Correct approach

  • Write global resets/fonts in a separate CSS file
  • Adding Atomic classes in HTML auto-generates the CSS
  • Removing classes from HTML also removes them from CSS

Checklist

Check the following when using Atomic CSS.

Does the class name exist as a literal string in the source code?

Do numeric classes include units (px, rem, p, vh)?

Is html { font-size: 10px } set? (when using rem)

Are you not duplicating classes for the same property?

Have you avoided manually editing auto-generated CSS files?

Have you verified confusing classes with autocomplete preview?