Package Exports
- isaaccss
- isaaccss/aliases
- isaaccss/aliases/default.d.ts
- isaaccss/aliases/default.js
- isaaccss/aliases/index.d.ts
- isaaccss/aliases/index.js
- isaaccss/api
- isaaccss/api/cssify.d.ts
- isaaccss/api/cssify.js
- isaaccss/api/index.d.ts
- isaaccss/api/index.js
- isaaccss/api/parseClass.d.ts
- isaaccss/api/parseClass.js
- isaaccss/api/postcssify.d.ts
- isaaccss/api/postcssify.js
- isaaccss/api/transform.d.ts
- isaaccss/api/transform.js
- isaaccss/api/types.d.ts
- isaaccss/api/types.js
- isaaccss/esbuild
- isaaccss/rollup
- 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[!][;property:value[!]...][?][*[*...]]
~~~~~~~ ~~~~~~~~~~ ~~~~~~~~ ~~~~~ ~ ~~~~~~~~~~~~~~~~~~~~~ ~ ~~~~~~~
(1) (2) (3) (4) (5) (6) (7) (8)
- 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/
- If there are ampersands
&
, they becomes that class
e.g.&+&/m-l:1em
->.\&\+\& + .\&\+\& { margin-left: 1rem }
- 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
!
indicates!important
- Multiple
property:value[!]
can be specified, delimited by semicolons;
- Optional trailing
?
generates unnamed@layer{}
- For example, add
?
to the components in a component library, so that applications using it can override the properties
- For example, add
- 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",
},
// for value, specify an array of either
// [propertyNameOrPattern, { alias: value }] or
// [propertyNameOrPattern, [aliasPattern, replacerStringOrFunction]]
value: [
[
"box-shadow",
{
sm: "0 1px 2px hsla($shadow-hsl / 0.1)",
md: "0 1px 2px hsla($shadow-hsl / 0.1),0 3px 6px hsla($shadow-hsl / 0.1)",
},
],
[
// `m:[1]`->{margin:.0625rem} `m-l:[16]`->{margin-left:1rem}
/^margin|^padding|^font-size$/,
[/\[(-?\d*\.?\d+)\]/g, (_, $1) => `${+$1 / 16}rem`.replace(/^0\./, ".")],
],
],
},
],
// 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.
}),
],
};