Search

CSS Methodology

This page explains the CSS design principles behind Lism.

Lism CSS Layer Structure

To address the common problem of CSS specificity becoming overly complex, Lism defines a clear layer structure.

LayerRole
SettingsSASS configuration variables, mixins, and other constructs that do not directly output styles.
Base
@lism-base
The layer for Reset CSS, token definitions, variable sets, and initial element styles.
.set--{state} classes are also defined here.
Trait
@lism-trait
The layer for classes that declaratively attach a role or feature to an element (.is--{name}, .has--{name}).
Primitives
@lism-primitive

The layer for Primitives — the building blocks for composing layouts.
.l--{layout} and .a--{atomic} are defined here.

Components
@lism-component
The layer for UI components with BEM-like structure (.c--{name}). Not included in the core lism-css@lism-css/ui and user-defined c--* classes belong here.
Custom
@lism-custom
A customization layer for overriding existing Lism classes or for user-defined classification classes with custom prefixes (.z--{zone}, .p--{page}, etc.).
Utility
@lism-utility
The layer for utility classes with a clear purpose or style (.u--{name}).
Props
-
Property Classes (.-{prop}:{val}) tied to individual CSS properties.
This group is the only one placed outside of layers, giving it higher specificity while still allowing reasonable coexistence with external CSS.

Design Tokens

CSS custom properties are defined for major CSS properties — typography, spacing, color, shadows, and more — using stepped preset values and semantic keywords.

Using tokens brings consistency to the design, makes the intent behind property usage more readable, and improves maintainability by allowing site-wide adjustments to be made simply by updating token values.

See the Tokens reference page for details.

CSS Class Design

This section explains the design philosophy behind the core class groups in Lism CSS.

Set Class

Set Classes are utility classes defined within the @lism-base layer. They are used for HTML element base styling or for setting variables.

CategoryFormatExample
Set Class.set--{style}.set--plain,
.set--var:hov,
.set--var:bxsh

Primitive Class

Primitive Classes are small building blocks for composing layouts.

These are further categorized into several types:

CategoryFormatExample
Layout Primitives
Primitives that serve as layout building blocks
.l--{name}.l--grid,
.l--columns
Atomic Primitives
The smallest layout unit primitives
.a--{name}.a--divider,
.a--icon

Primitive classes are standalone — they have no variations or child element classes. Only the c-- Component Classes described next follow a BEM-like structure.

Combining Primitives follows these rules:

CombinationAllowedNotes
l-- × l--NGSame category cannot be combined
a-- × a--NGSame category cannot be combined
l-- × a--DiscouragedNot intended to coexist

Trait Class

Trait Classes declare a role on an element or attach a feature to it.

CategoryFormatExample
is-- Trait
Declares a role (“is a …”) on an element
.is--{name}.is--container,
.is--wrapper,
.is--layer,
.is--boxLink
has-- Trait
Attaches a feature (“has a …”) to an element
.has--{name}.has--transition,
.has--gutter,
.has--snap

The decision criteria between is-- and has-- are:

is--has--
Meaning”is a …” (role / existence declaration)“has a …” (feature attachment)
CSS variablesNot requiredRequired (provides customization points)

See the naming guide for the detailed decision criteria and usage guidelines.

Component Class

Component Classes prefixed with c-- are concrete UI components composed from Primitives.
They are not included in the core lism-css and are partially provided via the @lism-css/ui package.

Users can also freely define their own c-- classes inside @layer lism-component.

@layer lism-component {
.c--card { /* ... */ }
.c--pricing { /* ... */ }
}

c-- classes can follow a BEM-like structure (Block / Modifier / Element), each expressed in the following format:

CategoryFormatExample
Block
The base class
.c--{name}.c--button,
.c--card
Modifier
Variation
.c--{name}--{modifier}.c--button--outline
Element
Child element
.c--{name}_{element}.c--card_header,
.c--card_body

Modifiers are used alongside the Block class, e.g. .c--button.c--button--outline.
Elements use a single underscore (_) as the separator.

Combining Blocks (.c--xxx.c--yyy) is generally NG, but the following combinations are allowed:

  • Block with its own Modifier: .c--xxx.c--xxx--variant
  • Block with another Block’s Element: .c--xxx.c--yyy_elem

Utility Class

Utility classes with a clear decorative or functional purpose are defined as follows:

CategoryFormatExample
Utility Class.u--{style}.u--cbox,
.u--trim

Property Class

In Lism CSS, utility classes that correspond to a single CSS property are defined as Property Classes.

Utility classes are provided for major properties, covering commonly used values and dedicated token values, with responsive support built in.

Property Classes come in three formats:

FormatDescriptionExample
.-{prop}:{value}Utility classes for applying the primary values or token values for each property.-fz:l,
.-d:none
.-{prop}A class that receives the --{prop} variable.-p,
.-fz
.-{prop}_{bp}A class that receives the --{prop}_{bp} variable.-p_sm,
.-p_md

* Classes for all CSS properties are not available by default. * Breakpoint-responsive classes are also only available by default for a select subset of major properties.

See the Property Class reference page for the full list.

Responsive Property Classes

The .-{prop}_{bp} class format combined with the --{prop}_{bp} variable format enables responsive styling.

Here is a practical usage example:
BOX
Resize
<div class="-p:20 -p_sm -p_md -bd" style="--p_sm: var(--s40); --p_md: var(--s50)">BOX</div>

See the Responsive styling guide for details.

Naming and placing custom classes

When you add your own classes that match one of Lism CSS’s existing class categories (set--, is--, has--, l--, a--, u--, -{prop}:{value}), use the same prefix and add them to the corresponding definition layer.

If you need to override an existing Lism class, do so within that same layer.

For example, set-- class redefinitions belong in @layer lism-base. In that case, define them after the Lism main.css is loaded, or boost the specificity by repeating the class name (e.g. .set--xxx.set--xxx) to ensure the override takes effect.

@layer lism-base {
/* New addition */
.set--hoge { /* ... */ }
/* Override */
.set--plain.set--plain { /* ... */ }
}

Adding custom classifications

You may also define your own prefixes that don’t match any of the built-in Lism class categories.

Category ExampleFormatExample
Zoning.z--{zoneName} or {zoneName}.z--header,
.z--main,
.z--sidebar
Page classification.p--{type}-{id|slug} or {slug}Page, etc..p--front,
.p--page--{slug}

Place these in @layer lism-custom.

@layer lism-custom {
.z--header { /* ... */ }
.p--front { /* ... */ }
}

Using data attributes for dynamic state

For state management that is dynamically toggled by JavaScript, use data attributes.

Example: [data-opened], [data-active]

© Lism CSS. All rights reserved.