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.
Simply switching the imported CSS file is all that is needed to disable @layer.
Customizing with SCSS
You can customize the output CSS by overriding SCSS variables.
Overriding SCSS configuration variables
The variables defined in lism-css/scss/_setting.scss can be overridden.
_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); $breakpoints: Breakpoint value definitions$common_support_bp: Breakpoints commonly supported across major Property Classes$is_container_query: Whether to use container queries$default_important: Whether to add!importantto Property Classes by default (0|1)$props: Output configuration for Property Classes
These can be overridden using @use with with.
After defining your overrides, import lism-css/scss/main.scss to apply the customized styles.
// Variable override format@use '../path-to/node_modules/lism-css/scss/setting' with ( $breakpoints: ( ..., ), $common_support_bp: 'sm|md|lg', $is_container_query: 1|0, $default_important: 0|1, $props: ( ..., ));
// Then load the Lism SCSS file (use main_no_layer instead of main if you want to disable @layer)@use '../path-to/node_modules/lism-css/scss/main';// @use '../path-to/node_modules/lism-css/scss/main_no_layer';- Toggling
@layeron or off is not controlled by a variable. Switch themain.scssfile you import instead. - When using Astro, the
../path-to/node_modules/prefix is not needed.
Customization examples
// Configuration overrides@use '../path-to/node_modules/lism-css/scss/setting' with ( $breakpoints: ( 'sm': '400px', // Change the sm breakpoint ), $common_support_bp: 'lg', // Generate utility classes up to lg size $is_container_query: 0, // Output using media queries $default_important: 1 // Add !important to Property Classes by default);
@use '../path-to/node_modules/lism-css/scss/main';// Configuration overrides@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} ), ));
// Load the Lism SCSS file@use '../path-to/node_modules/lism-css/scss/main';Notes on SCSS compilation
When importing SCSS files directly, be aware that the load order relative to other lism-css CSS may be affected during compilation.
Customizing with lism.config.js
By placing a lism.config.js file in the root of your project, you can customize component behavior (rather than styles).
export default { props: { hoge: { ... }, foo: { ... }, ... }, tokens: { hoge: [...], foo: [...], ... }, traits: { isHoge: 'is--hoge', setFoo: 'set--foo', ... },};/**
* 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: '',
container: '',
},
},
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
Consider the following configuration file:
import DEFAULT_CONFIG from 'lism-css/default-config';const { props, tokens } = DEFAULT_CONFIG;
export default { props: { // Add Property Class output d: { presets: [...(props.d.presets || []), 'flex', 'grid'] }, p: { utils: { box: '2em' } }, }, tokens: { // Add tokens bdrs: [...(tokens.bdrs || []), '5'], }, traits: { // Add props for Trait (is--* / has--*) output isHoge: 'is--hoge', },};With the above customization, the following behavior is added to Lism components:
d='flex'→ outputs-d:flexd='grid'→ outputs-d:gridp='box'→ outputs-p:boxbdrs='5'→ outputs-bdrs:5isHoge→ outputsis--hoge
<Box p="box" d="flex" bdrs="5" isHoge>Box</Box>
↓ Output
<div class="l--box is--hoge -p:box -d:flex -bdrs:5">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
Since styles are not automatically added, you need to include them manually.
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:
.-d\:flex { display: flex;}.-d\:grid { display: grid;}.-p\:box { padding: 2em;}.-bdrs\:5 { border-radius: var(--bdrs--5);}However, tokens are not auto-generated by this build process and must be added manually.
The build process must be re-run every time the package is updated.
Also, the styles for is-- classes must be manually defined and loaded.
:root { --bdrs--5: 0.125rem;}.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.
// Configuration overrides@use '../path-to/node_modules/lism-css/scss/setting' with ( $props: ( 'd': ( utilities: ( 'flex': 'flex', 'grid': 'grid', ), ), 'p': ( utilities: ( 'box': '2em', ), ), 'bdrs': ( utilities: ( '5': 'var(--bdrs--5)', ), ), ));
// Load the Lism SCSS file@use '../path-to/node_modules/lism-css/scss/main';
// Append token definitions@layer lism-base { :root { --bdrs--5: 0.125rem; }}