Package Exports
- isaaccss
- isaaccss/esbuild
- isaaccss/lib/aliases/default.d.ts
- isaaccss/lib/aliases/default.js
- isaaccss/lib/aliases/index.d.ts
- isaaccss/lib/aliases/index.js
- isaaccss/lib/applyPostcss.d.ts
- isaaccss/lib/applyPostcss.js
- isaaccss/lib/core/cssify.d.ts
- isaaccss/lib/core/cssify.js
- isaaccss/lib/core/index.d.ts
- isaaccss/lib/core/index.js
- isaaccss/lib/core/parseClass.d.ts
- isaaccss/lib/core/parseClass.js
- isaaccss/lib/core/parseHtml.d.ts
- isaaccss/lib/core/parseHtml.js
- isaaccss/lib/core/transform.d.ts
- isaaccss/lib/core/transform.js
- isaaccss/lib/core/types.d.ts
- isaaccss/lib/core/types.js
- isaaccss/lib/esbuild/index.d.ts
- isaaccss/lib/esbuild/index.js
- isaaccss/lib/esbuild/inject.d.ts
- isaaccss/lib/esbuild/inject.js
- isaaccss/lib/index.browser.d.ts
- isaaccss/lib/index.browser.js
- isaaccss/lib/index.node.d.ts
- isaaccss/lib/index.node.js
- isaaccss/lib/rollup/index.d.ts
- isaaccss/lib/rollup/index.js
- isaaccss/lib/vite/index.d.ts
- isaaccss/lib/vite/index.js
- isaaccss/rollup
- isaaccss/src/aliases/default.ts
- isaaccss/src/aliases/index.ts
- isaaccss/src/applyPostcss.ts
- isaaccss/src/core/cssify.ts
- isaaccss/src/core/index.ts
- isaaccss/src/core/parseClass.ts
- isaaccss/src/core/parseHtml.ts
- isaaccss/src/core/transform.ts
- isaaccss/src/core/types.ts
- isaaccss/src/esbuild/index.ts
- isaaccss/src/esbuild/inject.ts
- isaaccss/src/index.browser.ts
- isaaccss/src/index.node.ts
- isaaccss/src/rollup/index.ts
- isaaccss/src/vite/index.ts
- isaaccss/vite
Readme
isaaccss: Inline-Style-as-a-Class CSS engine
A CSS class DSL like inline styles.
import { is } from "isaaccss";
const Button = () => (
<button class={is`--H:210 --S:100% --L:50% padding:4px_8px @width>=768px/padding:8px_16px border-radius:8px color:white border:3px_solid_hsl(var(--H),var(--S),80%) background:hsl(var(--H),var(--S),var(--L)) :hover/--L:60% :active/--L:40%* @hover:hover/:hover/scale:1.1`}>
Submit
</button>
);
Or using some short aliases:
import { is } from "isaaccss";
const Button = () => (
<button class={is`--H:210 --S:100% --L:50% p:4px_8px @w>=768px/p:8px_16px b-radius:8px c:white b:3px_solid_hsl($H,$S,80%) bg:hsl($H,$S,$L) :hover/--L:60% :active/--L:40%* @hover:hover/:hover/scale:1.1`}>
Submit
</button>
)
- Unlike inline styles:
- Media queries and selectors (combinators, pseudo-class, pseudo-elements) can be described
- Specificity can be adjusted
- Short aliases can be used
Content-Security-Policy
: no need'unsafe-inline'
or'nonce-a682b15c'
forstyle-src
- Unlike Tailwind CSS and Windi CSS:
- This is a class name description rule, not a predefined property set, therefore:
- Less to remember
- Simple and flexible: any media, any selector, any property and any value can be described as is
- High specificity (ID-specificity = 1) by default to override styles from other CSS libraries
- Specificity can be adjusted
- Class names can be compressed
- Invalid class names can be detected
- This is a class name description rule, not a predefined property set, therefore:
- Unlike Linaria:
- Short aliases can be used
Class Format
[@media/][selectors/]property:value[!][?][*]
- Optional
@media/
indicates media queries@foo/...
generates@media foo {...}
- Tokens are parenthesized where necessary
- Optional
selectors/
indicates additional selectors- Pseudo-classes
e.g.:hover/
,:has(>:checked)/
- Pseudo-elements
e.g.::before/
,::part(foo)/
- Child combinator
e.g.>div/
- Adjacent sibling combinator
e.g.+div/
- General sibling combinator
e.g.~div/
- Combination of the above
e.g.:hover>input+label::before/
- Pseudo-classes
- Required
property
indicates the property name- Must be one of the known properties or a custom property
- Required
value
indicates the property value$bar
will be replaced withvar(--bar)
- Custom property set libraries, such as Open Props, can help with design themes
- Optional trailing
!
indicates!important
- For example, add
?
to the components in a component library, so that applications using it can override the properties
- For example, add
- Optional trailing
?
generates unnamed@layer{}
- Optional trailing
*
increases ID-specificity, more than one can be specified- For example, add
*
to the preferred style between:hover
and:active
- For example, add
- An underscore
_
will be replaced with a whitespace\_
will be replaced with_
)
Installation
npm i -D isaaccss
Usage
Configuration Example
import { defaultAliases } from "isaaccss";
import OpenProps from "open-props";
import postcssJitProps from "postcss-jit-props";
export default {
// Whether to pretty-print. Default is `false`.
pretty: true,
// Class name compression setting in boolean or `{ prefix: string }`. Pass `false` to turn off.
// Default is `{ prefix: "#" }`; class names are "#a", "#b", ..., "#aa", "#ab", ...
compress: { prefix: "~" },
// Aliases. If specified, the default aliases are removed.
aliases: [
// If you want to extend the default, pass the `defaultAliases` imported from "isaaccss".
defaultAliases,
// Custom aliases. For example:
{
media: {
dark: "prefers-color-scheme:dark",
light: "prefers-color-scheme:light",
sm: "640px", // use breakpoints like `@w<sm/d:none`
md: "768px",
},
selector: {
"::a": "::after",
"::b": "::before",
":f": ":focus",
":h": ":hover",
},
property: {
items: "align-items",
justify: "justify-content",
},
value: {
abs: "absolute",
rel: "relative",
},
},
],
// Optional PostCSS config. The only field is `plugins`.
// Following configuration is an example of using Open Props (e.g. `color:$blue-1`):
postcss: {
plugins: [postcssJitProps(OpenProps)],
},
};
See src/aliases/default.ts for the default aliases.
esbuild
import esbuild from "esbuild";
import isaaccss from "isaaccss/esbuild";
esbuild.build({
entryPoints: ["src/index.ts"],
outdir: "dist",
bundle: true,
// Inject `isaaccss.inject`.
inject: [isaaccss.inject],
plugins: [
isaaccss.plugin({
// Optional filename filter. Default is following.
filter: /\.[cm][jt]x?$/,
// Optional isaaccss config. See `Configuration Example` section above.
pretty: true,
compress: { prefix: "~" },
aliases: [],
postcss: { plugins: [] },
}),
],
});
Rollup
// rollup.config.js
import isaaccss from "isaaccss/rollup";
/** @type {import("rollup").RollupOptions} */
export default {
input: "src/index.js",
output: { file: "dist/index.js" },
plugins: [
isaaccss({
// Optional include filter. By default, all bundled scripts are included.
include: ["**/*.js"],
// Optional exclude filter. By default, `**/node_modules/**` are excluded.
exclude: ["**/node_modules/**"],
// Optional output filename.
// Default is the output script filename with extension ".css".
output: "dist/index.css",
// Optional isaaccss config. See `Configuration Example` section above.
pretty: true,
compress: { prefix: "~" },
aliases: [],
postcss: { plugins: [] },
}),
],
};
When you want to merge other CSS files with isaaccss CSS, use rollup-plugin-import-css
instead of rollup-plugin-css-only
.
// rollup.config.js
import css from "rollup-plugin-import-css";
import isaaccss from "isaaccss/rollup";
/** @type {import("rollup").RollupOptions} */
export default {
input: "src/index.js",
output: { file: "dist/index.js" },
plugins: [css(), isaaccss()],
};
Vite
- Class name compression is not supported in Vite dev server.
// vite.config.js
import isaaccssPlugin from "isaaccss/vite";
/** @type {import("vite").UserConfig} */
export default {
plugins: [
isaaccssPlugin({
// Options are same as for Rollup isaaccss plugin above.
}),
],
};