Docs
検索

lism.config.js でのカスタマイズ

プロジェクトのルート直下に lism.config.js(または lism.config.ts / lism.config.mjs)を置き、次のセットアップを行うと、コンポーネントが受け付ける props / tokens / traits やブレイクポイントを拡張できます。

lism.config.js を使うには @lism-css/plugin が必要です。Vite / Astro では統合プラグインでコンポーネントと CSS の両方に自動反映されます。Next.js では withLism() を使います。それ以外の構成では CSS だけを同梱の CLI でビルドします(統合プラグインを使わない構成で反映する)。

セットアップ

@lism-css/plugin の統合プラグイン lismCss() を、Vite / Astro の設定ファイルに追加します。これ1つで、lism.config.js の読み込み・CSS への自動反映・型定義 lism-env.d.ts の自動生成がまとめて有効になります。

lism.config.js を読み込むのはこのプラグインです。設定ファイルに追加していないと、lism.config.js を置いても内容は使われません。

pnpm add -D @lism-css/plugin
import { defineConfig } from 'astro/config';
import { lismCss } from '@lism-css/plugin/astro';
export default defineConfig({
integrations: [lismCss()],
});

Next.js では統合プラグインの代わりに、@lism-css/plugin/nextwithLism() を使います。セットアップ手順はインストールの「Next.js での導入」を参照してください。

プラグインはプロジェクトルートから lism.config.tslism.config.mjslism.config.js の順で自動検出します。別の場所のファイルを使う場合は configPath オプションでパスを指定できます。

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

設定ファイルの書き方

フォーマット

export default {
props: {
hoge: { ... },
foo: { ... },
...
},
tokens: {
hoge: { ... },
foo: { ... },
...
},
traits: {
isHoge: 'is--hoge',
setFoo: 'set--foo',
...
},
// breakpoints と isFullMode も同じファイルで指定します(後述)
};
デフォルト値
/**
 * isVar: 1 → クラス出力はせずstyle属性での変数出力のみ (--bdw, --keycolor など)
 * bp: 0(= bp 省略時のデフォルト)→ Prop-valユーティリティクラス化されなければ、style属性で出力するだけ。
 * bp: 1 → .-prop と --prop の セットがベースにあり、.-prop_bp と .--prop_bp で ブレイクポイント指定できる。
 *       .-prop{property:var(--prop)} が基本で、ユーティリティクラスは .-prop:val{property:value} となる。
 *
 * ↓コンポーネント処理で使用される
 * tokenClass: 1 → 対応するトークン値がそのまま全てユーティリティクラス化されるもの。
 * 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' } },
  // 実 line-height(unitless比率)を --lh で管理する。既定の行間管理は hl(half-leading)。
  // トークン値も任意数値も --lh 経由で出力する(素の line-height 出力だと * ルールに阻まれ子要素へ継承されないため)。
  lh: {
    prop: 'lineHeight',
    token: 'lh',
    tokenClass: 1,
    utils: { '1': '1' },
    alwaysVar: 1,
  },
  hl: {
    prop: '--hl',
    isVar: 1,
    token: 'hl',
    tokenClass: 1,
    bp: 1,
    // hl="0" で half-leading なし (--hl:0px) を表現できるようにするユーティリティ。
    utils: { '0': '0px' },
  },
  lts: { prop: 'letterSpacing', token: 'lts', tokenClass: 1 },
  ta: { prop: 'textAlign', presets: ['center', 'left', 'right'] },
  td: { prop: 'textDecoration', utils: { none: 'none' } },
  tt: {
    prop: 'textTransform',
    presets: ['uppercase', 'lowercase'],
    // 旧クラス名 -tt:upper / -tt:lower との互換。props の upper / lower を -tt:uppercase / -tt:lowercase に解決する。
    shorthands: { 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 },

  contentSize: { isVar: 1, presets: ['s', 'm', 'l', 'xl'], token: 'sz' },
  sz: { prop: 'inlineSize', token: 'sz', bp: 1 },
  'min-sz': { prop: 'minInlineSize', token: 'sz', bp: 1 },
  'max-sz': {
    prop: 'maxInlineSize',
    token: 'sz',
    tokenClass: 1,
    // full / bleed は inline-size / margin-inline も書き換える複合ルール(_size.scss)なので、BP 値(--max-sz_{bp})としては使えない。
    bp: 1,
    presets: ['full', 'bleed'],
    exUtility: {
      full: '',
      bleed: '',
    },
  },
  bsz: { prop: 'blockSize', token: 'sz' },
  'min-bsz': { prop: 'minBlockSize', token: 'sz' },
  'max-bsz': { prop: 'maxBlockSize', token: 'sz' },

  // bg
  bg: { prop: 'background' },
  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',
    // keycolor は palette カタログ経由で var(--keycolor) に解決される(#479)。
    presets: ['base', 'base-2', 'text', 'brand', 'accent', 'keycolor', 'inherit', 'transparent'],
    // bdc と同様に currentColor を短く書けるようにする(-bgc:current)。
    utils: { current: 'currentColor' },
    token: 'color',
    exUtility: { inherit: { 'background-color': 'inherit' } },
    alwaysVar: 1,
  },

  c: {
    // Note: bg系(bgclip)より後にくるように。
    prop: 'color',
    presets: ['base', 'text', 'text-2', 'brand', 'accent', 'keycolor', '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', 'keycolor', 'inherit', 'transparent'],
    utils: { current: 'currentColor' },
    token: 'color',
  },
  bdw: { isVar: 1, bp: 1 }, // --bdw のみ
  'bd-x': { prop: 'borderInline' },
  'bd-y': { prop: 'borderBlock' },
  'bd-s': { prop: 'borderInlineStart' },
  'bd-e': { prop: 'borderInlineEnd' },
  'bd-bs': { prop: 'borderBlockStart' },
  'bd-be': { 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'],
    bp: 1,
  },
  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-s': { prop: 'insetInlineStart', token: 'space' },
  'i-e': { prop: 'insetInlineEnd', token: 'space' },
  'i-bs': { prop: 'insetBlockStart', token: 'space' },
  'i-be': { 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 },
  ps: { prop: 'paddingInlineStart', token: 'space', tokenClass: 1, bp: 1 },
  pe: { prop: 'paddingInlineEnd', token: 'space', tokenClass: 1, bp: 1 },
  pbs: { prop: 'paddingBlockStart', token: 'space', tokenClass: 1, bp: 1 },
  pbe: { prop: 'paddingBlockEnd', token: 'space', tokenClass: 1, bp: 1 },
  pl: { prop: 'paddingLeft', token: 'space', tokenClass: 1, bp: 1 },
  pr: { prop: 'paddingRight', token: 'space', tokenClass: 1, bp: 1 },
  pt: { prop: 'paddingTop', token: 'space', tokenClass: 1, bp: 1 },
  pb: { prop: 'paddingBottom', token: 'space', tokenClass: 1, 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 },
  ms: { prop: 'marginInlineStart', presets: ['auto'], token: 'space', tokenClass: 1, bp: 1 },
  me: { prop: 'marginInlineEnd', presets: ['auto'], token: 'space', tokenClass: 1, bp: 1 },
  mbs: { prop: 'marginBlockStart', presets: ['auto', '0'], token: 'space', tokenClass: 1, bp: 1 },
  mbe: { prop: 'marginBlockEnd', presets: ['auto'], token: 'space', tokenClass: 1, bp: 1 },
  ml: { prop: 'marginLeft', token: 'space', tokenClass: 1, bp: 1 },
  mr: { prop: 'marginRight', token: 'space', tokenClass: 1, bp: 1 },
  mt: { prop: 'marginTop', token: 'space', tokenClass: 1, bp: 1 },
  mb: { prop: 'marginBottom', token: 'space', tokenClass: 1, bp: 1 },

  g: {
    prop: 'gap',
    presets: ['0', 'inherit'],
    exUtility: { inherit: { gap: 'inherit' } },
    token: 'space',
    tokenClass: 1,
    bp: 1,
  },
  cg: { prop: 'columnGap', token: 'space', tokenClass: 1, bp: 1 },
  rg: { prop: 'rowGap', token: 'space', tokenClass: 1, 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'],
    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'], bp: 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;

カスタマイズ例

例えば次のような設定ファイルを用意するとします。

lism.config.js でのカスタマイズ例
import DEFAULT_CONFIG from 'lism-css/default-config';
const { props } = DEFAULT_CONFIG;
export default {
props: {
// 既存propにpresetsを追加
ta: { presets: [...(props.ta.presets || []), 'justify'] },
// 既存propにutility値を追加
p: { utils: { box: '2em' } },
// 新しいpropの追加(filterはデフォルトに含まれない)
filter: { utils: { blur: 'blur(3px)' } },
},
tokens: {
// トークンは { key: value } の値マップで定義(既定に deep-merge される)
// → :root { --lts--2xl: .5em } の出力と -lts:2xl のユーティリティが自動生成される
lts: { '2xl': '.5em' },
},
traits: {
// Trait(is--* / has--*)出力用のプロパティを追加
isHoge: 'is--hoge',
},
};

上記のカスタマイズによって、Lismコンポーネントでは次のような挙動が追加されます。

  • ta='justify'-ta:justify を出力する。
  • p='box'-p:box を出力する。
  • filter='blur'-filter:blur を出力する。
  • lts='2xl'-lts:2xl を出力する。
  • isHogeis--hoge を出力する。
<Box p="box" ta="justify" filter="blur" lts="2xl" isHoge>Box</Box>
↓ 出力結果
<div class="l--box is--hoge -p:box -ta:justify -filter:blur -lts:2xl">Box</div>

統合プラグインを使っていれば、これらのクラスに対応する CSS と型定義も自動で生成されます。統合プラグインを使わない構成では CLI ビルドで CSS を生成してください。

ブレイクポイント(xs / xl)の有効化

デフォルトのブレイクポイントは xs: 0(無効)/ sm: 480px / md: 800px / lg: 1120px / xl: 0(無効)です。値 0 は「無効(CSS クエリを出力しない)」を表します。

xsxl を有効化するには、lism.config.jsbreakpoints に、有効化したいブレイクポイントのサイズだけを指定します。

lism.config.js
export default {
breakpoints: {
xs: '360px', // xs を有効化
xl: '1400px', // xl を有効化
},
};

これだけで、ブレイクポイント対応(bp: 1)の全 Property Class が xs / xl のブレイクポイント対応クラス(-p_xs / -p_xl など)も出力するようになります。prop ごとに個別指定する必要はありません。

コンポーネント側でもオブジェクト記法で xs / xl を指定できるようになります。

<Box p={{ base: 20, xs: 10, sm: 30 }} />

full.css を読み込んでいる場合も、xs / xl はデフォルトでは無効です(出力されるのは sm / md / lg)。利用するには上記と同様に、breakpoints でサイズを指定して有効化してください。

xs / xl などを有効化すると bp: 1 の全 Property Class に該当ブレイクポイントのブロックが追加されるぶん、CSS サイズが増えます。CSS Purge との併用が前提の設計です。CSS Purge を使わない場合は、bp のリスト形式(bp: ['sm', 'md'] など)で prop ごとに出力ブレイクポイントを絞ることを検討してください。

SCSS を直接利用する構成では、$breakpoints の上書きでも有効化できます(SCSS でのカスタマイズを参照)。

isFullMode

全部入りビルド(full.cssを読み込むだけでは、コンポーネント側の出力は変わりません(例: t="20" はインラインスタイルとして出力されます)。コンポーネントの出力も full.css に合わせるには、isFullMode を有効にします。

lism.config.js
export default {
isFullMode: true,
};

isFullMode: true にすると、コンポーネントの props 設定に full 用の設定が適用されます。

  • t="20" のような値が、インラインスタイルではなく -t クラス+--t 変数で出力されます。
  • ta={['start', 'center']} のようなブレイクポイント指定が、full.css にブレイクポイント対応クラスがある Property Class で警告なく使えます。
  • 例外として、変数出力専用(isVar 系)には bds / bdc を除いてブレイクポイント対応が追加されません。contentSize などの isVar 系、単位なし比率を保つため対象外の lh、border ショートハンド系は、isFullMode を有効にしてもブレイクポイント指定で警告が出ます。
  • 設定は「デフォルト設定 → full 用設定 → lism.config.jsprops」の順でマージされ、後のものほど優先されます。
  • isFullMode は、full.css(または isFullMode を有効にして CLI ビルドした main.css)を読み込んでいることが前提です。デフォルトの main.css のまま有効にすると、出力されたクラスに対応するスタイルが存在しない状態になります。
  • isFullMode はビルド時の設定です。ランタイムの window._LISM_CSS_CONFIG_ では切り替えられません。

型サポート

型は2種類あります。設定ファイルを書くときの LismConfig と、コンポーネントを使うときの lism-env.d.ts です。

設定ファイルを書くときの型(LismConfig)

lism-css/config-types から LismConfig 型を読み込むと、設定ファイルのキー名や値の形をエディタが補完・チェックしてくれます。propsporps とタイプミスした、といった間違いをその場で見つけられます。

lism.config.ts では satisfies LismConfig を付けるのがおすすめです。型チェックが効きつつ、書いた内容(追加した prop / token のキーなど)の具体的な型はそのまま保たれます。

lism.config.ts
import type { LismConfig } from 'lism-css/config-types';
export default {
props: {
filter: { utils: { blur: 'blur(3px)' } },
},
breakpoints: {
xs: '360px',
},
} satisfies LismConfig;

lism.config.js(JavaScript)でも、JSDoc の @type を付ければ同じように補完・チェックが効きます。

lism.config.js
/** @type {import('lism-css/config-types').LismConfig} */
export default {
props: {
filter: { utils: { blur: 'blur(3px)' } },
},
};

コンポーネントを使うときの型(lism-env.d.ts)

統合プラグインを使っている場合、lism.config.js の内容は lism-env.d.ts として自動生成され、コンポーネント側の型に反映されます。手書きの型拡張は不要です。lism-env.d.ts は git にコミットしてください。

  • 追加した prop / trait は CustomPropRegistry / CustomTraitRegistry の拡張として出力されます。<Box filter="blur" isHoge> のような新規 prop / trait も、エディタや astro check で型エラーになりません。
  • breakpoints で有効化した xs / xl も、オブジェクト記法や配列記法の型・補完に反映されます。手書きで対応する方法は Responsive ページを参照してください。
  • isFullMode: true のときは、ta などへのブレイクポイント指定(配列・オブジェクト記法)も型エラーになりません。

なお、既存 prop への値追加(ta="justify" など)はもともと任意の文字列を受け付けるため、型エラーにはなりません(補完候補には出ません)。

統合プラグインを使わない構成で isFullMode の型だけ切り替えるには、プロジェクト直下の型定義ファイル(例: src/lism-env.d.ts)で次のように拡張してください。

src/lism-env.d.ts
import 'lism-css';
declare module 'lism-css' {
interface FullModeRegistry {
enabled: true; // キー名は任意。1つでもキーがあれば full 版の型に切り替わる
}
}

統合プラグインを使わない構成で反映する

統合プラグインを使わない構成では、lism.config.js は自動では反映されません。CSS は @lism-css/plugin 同梱の CLI でビルドします。

コンポーネント側は lism.config.js を読まないため、p="box" のような追加値はクラスとして認識されません。コンポーネントから使うには、Lism Props の :value 記法p=":box")で強制的にクラス化してください。クライアント側でレンダリングされるコンポーネントなら、ブラウザで window._LISM_CSS_CONFIG_ に同じ内容を定義して実行時にマージすることもできます(isFullMode は除く)。

CLI ビルド

@lism-css/plugin が提供する lism-css build を実行すると、lism.config.js を読み込んで設定を反映した CSS を生成します。

npx lism-css build

カスタマイズ例の設定なら、次のスタイルが lism-css/main.css に生成されます。

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

tokens に値を書いておけば、.-lts\:2xl { letter-spacing: var(--lts--2xl) } のようにトークンを参照する Property Class に加えて、参照先のCSS変数(:root { --lts--2xl: .5em })も生成されます。値に '-' を指定したキーは「名前だけを定義し、実値は出力しない」指定です。palette.keycolor のようにCSS変数を持たないトークンや、bdrs.inner のように実値を手書き SCSS 側で定義するトークンで使います。

一方で is-- クラスのスタイルは自動生成されないため、別途手動で定義して読み込ませる必要があります。

is-- クラスのスタイルは手動読み込みが必要です。
@layer lism-trait {
.is--hoge {
/* ... */
}
}
  • パッケージのスタイルを再ビルドするコマンドのため、パッケージ更新ごとにビルドが必要です。
  • full.css / full_no_layer.css はデフォルトでは再ビルドされません。full.css を使用している場合は --full オプションを付けてください。isFullMode が有効なら、main.css にも full 用の設定が適用されます。
npx lism-css build --full

© 2026 Lism CSS.