Search

Customize

This page explains how to customize the CSS and component behavior available from the lism-css npm package.

Disabling @layer

You can disable @layer by importing lism-css/main_no_layer.css instead of lism-css/main.css.

Just swap the imported CSS file — no other changes needed.

Customizing with SCSS

You can customize the output CSS by overriding SCSS variables.

Overridable variables

The variables defined in lism-css/scss/_setting.scss can be overridden via @use ... with (...).

_setting.scss
@use 'sass:map';
@use 'sass:string';
@use './prop-config' as props;

$default_important: 0 !default;
$is_container_query: 1 !default;
$common_support_bp: 'md' !default;

$breakpoints: () !default;
$breakpoints: map.merge(
  (
    'sm': '480px',
    'md': '800px',
    'lg': '1120px',
  ),
  $breakpoints
);

$props: () !default;
$props: map.deep-merge(props.$props, $props);
VariablePurpose
$breakpointsBreakpoint value definitions
$common_support_bpBreakpoints commonly supported across major Property Classes
$is_container_queryWhether to use container queries (1 = container query / 0 = media query)
$default_importantWhether to add !important to Property Classes by default (0 / 1)
$propsPer-Property Class output configuration

Basic format

After defining your overrides, import lism-css/scss/main.scss to apply the customized styles.

SCSS variable override format
// 1. Override configuration variables
@use '../path-to/node_modules/lism-css/scss/setting' with (
$breakpoints: (
'sm': '400px', // individual keys can be overridden
),
$common_support_bp: 'lg', // 'sm' | 'md' | 'lg'
$is_container_query: 0, // 1 = container query / 0 = media query
$default_important: 1, // 0 / 1
$props: (
// Per-Prop settings (see below)
)
);
// 2. Load main.scss (use main_no_layer.scss to disable @layer)
@use '../path-to/node_modules/lism-css/scss/main';
  • Toggling @layer on or off is not controlled by a variable. Switch the main.scss file you import instead.
  • When using Astro, the ../path-to/node_modules/ prefix is not needed.

Customizing individual $props

For each Property Class, you can adjust the output range or add utility classes.

Customize Property Class output
@use '../path-to/node_modules/lism-css/scss/setting' with (
$props: (
'fz': (
important: 1,
// Output !important for fz utility classes
),
'h': (
bp: 0,
// Disable breakpoint-responsive classes for 'h'
),
'p': (
bp: 'lg',
// Output utility classes for 'p' up to lg size
utilities: (
'box': '2em',
),
// Add .-p:box{--p:2em}
),
)
);
@use '../path-to/node_modules/lism-css/scss/main';

Notes on SCSS compilation

When importing SCSS files directly, note that compilation order relative to other lism-css styles may be affected.

Customizing with lism.config.js

By placing a lism.config.js (or lism.config.mjs) file in the root of your project, you can customize component behavior (rather than styles).

Registering the Vite plugin (required)

To make lism.config.js take effect, you must register lism-css/vite-plugin in your Vite (or Astro) config file. Without registration, the file is ignored and default settings are used.

Registration example in astro.config.mjs
import { defineConfig } from 'astro/config';
import lismCss from 'lism-css/vite-plugin';
export default defineConfig({
vite: {
plugins: [lismCss()],
},
});

The plugin auto-detects lism.config.js then lism.config.mjs from the project root. To use a file at a different location, specify the path via the configPath option:

plugins: [lismCss({ configPath: './config/lism.config.js' })],

Format

export default {
props: {
hoge: { ... },
foo: { ... },
...
},
tokens: {
hoge: [...],
foo: [...],
...
},
traits: {
isHoge: 'is--hoge',
setFoo: 'set--foo',
...
},
};
Default values
/**
 * isVar: 1 → クラス出力はせずstyle属性での変数出力のみ (--bdw, --keycolor など)
 * bp: 0 → Prop-valユーティリティクラス化されなければ、style属性で出力するだけ。
 * bp: 1 → .-prop と --prop の セットがベースにあり、.-prop_bp と .--prop_bp で ブレイクポイント指定できる。
 *       .-prop{property:var(--prop)} が基本で、ユーティリティクラスは .-prop:val{property:value} となる。
 *
 * ↓コンポーネント処理で使用される
 * tokenClass: 1 → 対応するトークン値がそのまま全てユーティリティクラス化されるもの。
 *             2 → ユーティリティクラスされ、内容は別途ファイルで記述するもの。
 * shorthands: → コンポーネント側で短く書くための設定
 *
 * ↓SCSS出力で使用される
 * alwaysVar: 1 → state変数扱い。 .-prop,[class*=-prop:] {property:var(--prop)} の base 出力となり、
 *   ユーティリティクラスは --prop をセットする形になる。
 *   加えて BPクラスも .-prop_$bp { property: var(--prop); --prop: var(--prop_$bp) !important; } を出力し、
 *   常に --prop が当該要素の現在値になるよう上書きされる(consumer が --prop を参照できる)。
 * important: 1 → !important を付けて最終的に出力する
 */

const PLACE_PRESETS = ['start', 'center', 'end'] as const;
const PLACE_FX_PRESETS = ['flex-start', 'flex-end'] as const;
const PLACE_SHORTHANDS = { s: 'start', e: 'end', c: 'center', fs: 'flex-start', fe: 'flex-end' } as const;

export default {
  f: { prop: 'font', presets: ['inherit'] },
  fz: { prop: 'fontSize', token: 'fz', tokenClass: 1, bp: 1 },
  fw: {
    prop: 'fontWeight',
    token: 'fw',
    tokenClass: 1,
    presets: ['100', '200', '300', '400', '500', '600', '700', '800', '900'],
  },
  ff: { prop: 'fontFamily', token: 'ff', tokenClass: 1 },
  fs: { prop: 'fontStyle', presets: ['italic'], shorthands: { i: 'italic' } },
  lh: {
    prop: 'lineHeight',
    presets: ['1'],
    token: 'hl',
    tokenClass: 2,
    exUtility: { 1: '' },
  },
  hl: {
    isVar: 1,
    token: 'hl',
    tokenClass: 0,
    bp: 1,
  },
  lts: { prop: 'letterSpacing', token: 'lts', tokenClass: 1 },
  ta: { prop: 'textAlign', presets: ['center', 'left', 'right'] },
  td: { prop: 'textDecoration', utils: { none: 'none' } },
  tt: { prop: 'textTransform', utils: { upper: 'uppercase', lower: 'lowercase' } },
  // te: { prop: 'textEmphasis', presets: ['filled'] },
  // tsh: { prop: 'textShadow' },

  d: {
    prop: 'display',
    presets: ['none', 'block', 'flex', 'inline-flex', 'grid', 'inline-grid', 'inline', 'inline-block'],
    bp: 1,
  },
  o: { prop: 'opacity', presets: ['0'], token: 'o', tokenClass: 1 },
  v: { prop: 'visibility', presets: ['hidden'] },
  ov: { prop: 'overflow', presets: ['hidden', 'auto', 'clip'] },
  'ov-x': { prop: 'overflowX', presets: ['clip', 'auto', 'scroll'] },
  'ov-y': { prop: 'overflowY', presets: ['clip', 'auto', 'scroll'] },
  // overflow-clip-margin → safariで使えない
  ar: {
    prop: 'aspectRatio',
    presets: ['21/9', '16/9', '3/2', '1/1'], // 4/3, 2/1
    token: 'ar',
    tokenClass: 1,
    bp: 1,
  },

  // size
  w: { prop: 'width', utils: { fit: 'fit-content' }, presets: ['100%'], token: 'sz', bp: 1 },
  h: { prop: 'height', utils: { fit: 'fit-content' }, presets: ['100%'], token: 'sz', bp: 1 },
  'min-w': { prop: 'minWidth', presets: ['100%'], token: 'sz', bp: 1 },
  'max-w': { prop: 'maxWidth', presets: ['100%'], token: 'sz', bp: 1 },
  'min-h': { prop: 'minHeight', presets: ['100%'], token: 'sz', bp: 1 },
  'max-h': { prop: 'maxHeight', presets: ['100%'], token: 'sz', bp: 1 },

  sz: { prop: 'inlineSize', token: 'sz' },
  'min-sz': { prop: 'minInlineSize', token: 'sz' },
  'max-sz': {
    prop: 'maxInlineSize',
    token: 'sz',
    tokenClass: 1,
    presets: ['full'],
    exUtility: {
      full: '',
      bleed: '',
    },
  },
  bsz: { prop: 'blockSize', token: 'sz' },
  'min-bsz': { prop: 'minBlockSize', token: 'sz' },
  'max-bsz': { prop: 'maxBlockSize', token: 'sz' },

  // bg
  bg: { prop: 'background', bp: 1 },
  bgi: { prop: 'backgroundImage' },
  bgr: { prop: 'backgroundRepeat', presets: ['no-repeat'] },
  bgp: { prop: 'backgroundPosition', presets: ['center'] },
  bgsz: { prop: 'backgroundSize', presets: ['cover', 'contain'] },
  // bga: { prop: 'backgroundAttachment' }, // fixed
  // bgo: { prop: 'backgroundOrigin' }, // border, padding, content
  // bgblend: { prop: 'backgroundBlendMode' },
  // bgclip: {
  // 	prop: 'backgroundClip',
  // 	presets: ['text'],
  // },
  bgc: {
    prop: 'backgroundColor',
    presets: ['base', 'base-2', 'text', 'brand', 'accent', 'inherit', 'transparent'],
    token: 'color',
    exUtility: { inherit: { 'background-color': 'inherit' } },
    alwaysVar: 1,
  },

  c: {
    // Note: bg系(bgclip)より後にくるように。
    prop: 'color',
    presets: ['base', 'text', 'text-2', 'brand', 'accent', 'inherit'],
    token: 'color',
    exUtility: {
      inherit: { color: 'inherit' }, // --c ではなく color で出力したい
      // mix: {'--_c1:currentColor;--_c2:transparent;--c:color-mix(in srgb, var(--_c1) var(--_mix-c, 50%), var(--_c2))'},
    },
    alwaysVar: 1,
  },
  keycolor: { isVar: 1, token: 'color' },
  bd: { prop: 'border', presets: ['none'] },
  bds: { isVar: 1, presets: ['dashed', 'dotted', 'double'] },
  bdc: {
    isVar: 1,
    presets: ['brand', 'accent', 'divider', 'inherit', 'transparent'],
    utils: { current: 'currentColor' },
    token: 'color',
  },
  bdw: { isVar: 1, bp: 1 }, // --bdw のみ
  'bd-x': { prop: 'borderInline' },
  'bd-y': { prop: 'borderBlock' },
  'bd-x-s': { prop: 'borderInlineStart' },
  'bd-x-e': { prop: 'borderInlineEnd' },
  'bd-y-s': { prop: 'borderBlockStart' },
  'bd-y-e': { prop: 'borderBlockEnd' },
  'bd-t': { prop: 'borderTop' },
  'bd-b': { prop: 'borderBottom' },
  'bd-l': { prop: 'borderLeft' },
  'bd-r': { prop: 'borderRight' },

  bdrs: {
    prop: 'borderRadius',
    presets: ['0'],
    token: 'bdrs',
    tokenClass: 1,
    bp: 1,
    alwaysVar: 1,
  },
  'bdrs-tl': { prop: 'borderTopLeftRadius', token: 'bdrs' },
  'bdrs-tr': { prop: 'borderTopRightRadius', token: 'bdrs' },
  'bdrs-br': { prop: 'borderBottomRightRadius', token: 'bdrs' },
  'bdrs-bl': { prop: 'borderBottomLeftRadius', token: 'bdrs' },
  'bdrs-ss': { prop: 'borderStartStartRadius', token: 'bdrs' },
  'bdrs-se': { prop: 'borderStartEndRadius', token: 'bdrs' },
  'bdrs-es': { prop: 'borderEndStartRadius', token: 'bdrs' },
  'bdrs-ee': { prop: 'borderEndEndRadius', token: 'bdrs' },

  bxsh: { prop: 'boxShadow', utils: { 0: 'none' }, token: 'bxsh', tokenClass: 1, bp: 1 },

  // position
  pos: {
    prop: 'position',
    presets: ['static', 'fixed', 'sticky', 'relative', 'absolute'],
  },
  z: { prop: 'zIndex', presets: ['-1', '0', '1', '99'] },
  t: { prop: 'top', utils: { 0: '0%' }, presets: ['50%', '100%'], token: 'space' },
  l: { prop: 'left', utils: { 0: '0%' }, presets: ['50%', '100%'], token: 'space' },
  r: { prop: 'right', utils: { 0: '0%' }, presets: ['50%', '100%'], token: 'space' },
  b: { prop: 'bottom', utils: { 0: '0%' }, presets: ['50%', '100%'], token: 'space' },
  i: { prop: 'inset', utils: { 0: '0%' }, token: 'space' },
  'i-x': { prop: 'insetInline', token: 'space' },
  'i-y': { prop: 'insetBlock', token: 'space' },
  'i-x-s': { prop: 'insetInlineStart', token: 'space' },
  'i-x-e': { prop: 'insetInlineEnd', token: 'space' },
  'i-y-s': { prop: 'insetBlockStart', token: 'space' },
  'i-y-e': { prop: 'insetBlockEnd', token: 'space' },

  // space
  p: {
    prop: 'padding',
    presets: ['0'],
    token: 'space',
    tokenClass: 1,
    alwaysVar: 1,
    bp: 1,
  },
  px: { prop: 'paddingInline', presets: ['0'], token: 'space', tokenClass: 1, bp: 1 },
  py: { prop: 'paddingBlock', presets: ['0'], token: 'space', tokenClass: 1, bp: 1 },
  'px-s': { prop: 'paddingInlineStart', token: 'space', bp: 1 },
  'px-e': { prop: 'paddingInlineEnd', token: 'space', bp: 1 },
  'py-s': { prop: 'paddingBlockStart', token: 'space', bp: 1 },
  'py-e': { prop: 'paddingBlockEnd', token: 'space', bp: 1 },
  pl: { prop: 'paddingLeft', token: 'space', bp: 1 },
  pr: { prop: 'paddingRight', token: 'space', bp: 1 },
  pt: { prop: 'paddingTop', token: 'space', bp: 1 },
  pb: { prop: 'paddingBottom', token: 'space', bp: 1 },
  m: {
    prop: 'margin',
    presets: ['auto', '0'],
    token: 'space',
    tokenClass: 1,
    alwaysVar: 1,
    bp: 1,
  },
  mx: { prop: 'marginInline', presets: ['auto', '0'], token: 'space', tokenClass: 1, bp: 1 },
  my: { prop: 'marginBlock', presets: ['auto', '0'], token: 'space', tokenClass: 1, bp: 1 },
  'mx-s': { prop: 'marginInlineStart', presets: ['auto'], token: 'space', bp: 1 },
  'mx-e': { prop: 'marginInlineEnd', presets: ['auto'], token: 'space', bp: 1 },
  'my-s': { prop: 'marginBlockStart', token: 'space', bp: 1, presets: ['auto', '0'], tokenClass: 1 },
  'my-e': { prop: 'marginBlockEnd', presets: ['auto'], token: 'space', bp: 1 },
  ml: { prop: 'marginLeft', token: 'space', bp: 1 },
  mr: { prop: 'marginRight', token: 'space', bp: 1 },
  mt: { prop: 'marginTop', token: 'space', bp: 1 },
  mb: { prop: 'marginBottom', token: 'space', bp: 1 },

  g: {
    prop: 'gap',
    presets: ['0', 'inherit'],
    exUtility: { inherit: { gap: 'inherit' } },
    token: 'space',
    tokenClass: 1,
    bp: 1,
  },
  cg: { prop: 'columnGap', token: 'space', bp: 1 },
  rg: { prop: 'rowGap', token: 'space', bp: 1 },
  cols: { isVar: 1, bp: 1 },
  rows: { isVar: 1, bp: 1 },

  // flex
  fxf: { prop: 'flexFlow' },
  fxw: { prop: 'flexWrap', presets: ['wrap'], bp: 1 },
  fxd: { prop: 'flexDirection', presets: ['column', 'column-reverse', 'row-reverse'], bp: 1 },
  fx: { prop: 'flex', presets: ['1'], bp: 1 },
  fxg: { prop: 'flexGrow', presets: ['1'] },
  fxsh: { prop: 'flexShrink', presets: ['0'] },
  fxb: { prop: 'flexBasis', bp: 1 },

  // grid
  // gd: { prop: 'grid' },
  gt: {
    prop: 'gridTemplate',
    bp: 1,
  },
  gta: { prop: 'gridTemplateAreas', bp: 1 },
  gtc: {
    prop: 'gridTemplateColumns',
    presets: ['subgrid'],
    bp: 1,
  },
  gtr: {
    prop: 'gridTemplateRows',
    presets: ['subgrid'],
    // exUtility: { repeat: { '--rows': '1', '--gtr': 'repeat(var(--rows), 1fr)' } },
    bp: 1,
  },
  gaf: { prop: 'gridAutoFlow', presets: ['row', 'column'], bp: 1 }, //dense
  gac: { prop: 'gridAutoColumns' },
  gar: { prop: 'gridAutoRows' },

  // grid item
  ga: { prop: 'gridArea', utils: { '1/1': '1 / 1' }, bp: 1 },
  gc: { prop: 'gridColumn', utils: { '1/-1': '1 / -1' }, bp: 1 },
  gr: { prop: 'gridRow', utils: { '1/-1': '1 / -1' }, bp: 1 },
  gcs: { prop: 'gridColumnStart' },
  gce: { prop: 'gridColumnEnd' },
  grs: { prop: 'gridRowStart' },
  gre: { prop: 'gridRowEnd' },

  // places
  // -(ai|ac|ji|jc|aslf|jslf):   /    -$1:
  ai: {
    prop: 'alignItems',
    presets: [...PLACE_PRESETS, 'stretch', ...PLACE_FX_PRESETS],
    shorthands: PLACE_SHORTHANDS,
    bp: 1,
  },
  ac: {
    prop: 'alignContent',
    presets: [...PLACE_PRESETS, ...PLACE_FX_PRESETS],
    utils: { between: 'space-between' },
    shorthands: PLACE_SHORTHANDS,
    bp: 1,
  },
  ji: {
    prop: 'justifyItems',
    presets: [...PLACE_PRESETS, 'stretch', ...PLACE_FX_PRESETS],
    shorthands: PLACE_SHORTHANDS,
    bp: 1,
  },
  jc: {
    prop: 'justifyContent',
    presets: [...PLACE_PRESETS, ...PLACE_FX_PRESETS],
    utils: { between: 'space-between' },
    shorthands: PLACE_SHORTHANDS,
    bp: 1,
  },
  pi: { prop: 'placeItems', presets: PLACE_PRESETS },
  pc: { prop: 'placeContent', presets: PLACE_PRESETS },
  aslf: {
    prop: 'alignSelf',
    presets: [...PLACE_PRESETS, 'stretch'],
    shorthands: PLACE_SHORTHANDS,
  },
  jslf: {
    prop: 'justifySelf',
    presets: [...PLACE_PRESETS, 'stretch'],
    shorthands: PLACE_SHORTHANDS,
  },
  pslf: { prop: 'placeSelf', presets: PLACE_PRESETS },
  order: { prop: 'order', presets: ['0', '-1', '1'] },

  // transform
  // translate: {
  // 	prop: 'translate',
  // 	utils: {
  // 		'-50X': '-50% 0',
  // 		'-50Y': '0 -50%',
  // 		'-50XY': '-50% -50%',
  // 	},
  // },

  // rotate: {
  // 	prop: 'rotate',
  // 	utils: {
  // 		[`45`]: '45deg',
  // 		'-45': '-45deg',
  // 		[`90`]: '90deg',
  // 		'-90': '-90deg',
  // 		// '180': '180deg',
  // 	},
  // },

  // scale: {
  // 	prop: 'scale',
  // 	utils: {
  // 		'-X': '-1 1',
  // 		'-Y': '1 -1',
  // 		'-XY': '-1 -1',
  // 	},
  // },

  // others
  ovw: { prop: 'overflowWrap', presets: ['anywhere'] },
  whs: { prop: 'whiteSpace', presets: ['nowrap'] },
  // wordbreak: { prop: 'wordBreak', utils: { keep: 'keep-all', all: 'break-all' } },
  float: { prop: 'float', presets: ['left', 'right'] },
  clear: { prop: 'clear', presets: ['both'] },
  iso: { prop: 'isolation', presets: ['isolate'] },
  wm: { prop: 'writingMode', presets: ['vertical-rl'], bp: 1 },
} as const;

Customization example

Here’s an example configuration:

Customization example using lism.config.js
import DEFAULT_CONFIG from 'lism-css/default-config';
const { props, tokens } = DEFAULT_CONFIG;
export default {
props: {
// Add presets to an existing prop
ta: { presets: [...(props.ta.presets || []), 'justify'] },
// Add a utility value to an existing prop
p: { utils: { box: '2em' } },
// Add a brand-new prop (filter is not in defaults)
filter: { utils: { blur: 'blur(3px)' } },
},
tokens: {
// Props with tokenClass:1 are auto-classed when you add tokens
lts: [...(tokens.lts || []), '2xl'],
},
traits: {
// Add props for Trait (is--* / has--*) output
isHoge: 'is--hoge',
},
};

With the above customization, the following behavior is added to Lism components:

  • ta='justify' → outputs -ta:justify
  • p='box' → outputs -p:box
  • filter='blur' → outputs -filter:blur
  • lts='2xl' → outputs -lts:2xl
  • isHoge → outputs is--hoge
<Box p="box" ta="justify" filter="blur" lts="2xl" isHoge>Box</Box>
↓ Output
<div class="l--box is--hoge -p:box -ta:justify -filter:blur -lts:2xl">Box</div>

Note that customizations via lism.config.js only affect the HTML output from components. The styles for any added utility classes are not automatically loaded.

How to load additional styles

Adding props in lism.config.js alone does not produce styles for the corresponding utility classes. Use one of the following approaches to add the styles.

Hand-write styles for small additions

For small additions, you don’t need to rebuild via the CLI or reconfigure SCSS. The Lism Props :value notation combined with hand-written rules in global.css is enough.

global.css
@layer lism-base {
:root {
--lts--2xl: 0.15em;
}
}
/* Property Classes are not wrapped in @layer */
.-lts\:2xl {
letter-spacing: var(--lts--2xl);
}
<Text lts=":2xl">...</Text>

Switch to the CLI / SCSS routes below only when you want to extend tokens systematically.

Build CSS using the lism-css CLI command

Running npx lism-css build will trigger a style build inside the lism-css package with some of your lism.config.js customizations applied.

In this example, the following styles would be automatically generated into lism-css/main.css by this command:

.-ta\:justify {
text-align: justify;
}
.-p\:box {
padding: 2em;
}
.-filter\:blur {
filter: blur(3px);
}
.-lts\:2xl {
letter-spacing: var(--lts--2xl);
}

However, the build only goes as far as generating utility classes that reference tokens, such as .-lts\:2xl { letter-spacing: var(--lts--2xl) }. The referenced CSS variables themselves (the actual token values, such as --lts--2xl: 0.15em) are not auto-generated. The same applies to is-- class styles.

You need to define these manually and load them yourself.

The following must be loaded manually:
@layer lism-base {
:root {
--lts--2xl: 0.15em;
}
}
@layer lism-trait {
.is--hoge {
/* ... */
}
}

Since this command rebuilds the package styles, it must be run each time the package is updated.

Adding styles manually

You can, of course, write all the necessary CSS manually and load it yourself without using the build command.

Overriding SCSS files

You can also override SCSS variables in line with your lism.config.js configuration before loading the styles.

Customize SCSS to match lism.config.js
// Configuration overrides
@use '../path-to/node_modules/lism-css/scss/setting' with (
$props: (
'ta': (
utilities: (
'justify': 'justify',
),
),
'p': (
utilities: (
'box': '2em',
),
),
'filter': (
utilities: (
'blur': 'blur(3px)',
),
),
'lts': (
utilities: (
'2xl': 'var(--lts--2xl)',
),
),
)
);
// Load the Lism SCSS file
@use '../path-to/node_modules/lism-css/scss/main';
// Append token definitions
@layer lism-base {
:root {
--lts--2xl: 0.15em;
}
}

© Lism CSS. All rights reserved.