SCSS Styles
Create or update layout, theme, module, and registration files for a component in core and targeted themes.
Read ../_shared/component-context.md for naming conventions, theme paths, and common gotchas.
When to use
When the user asks to:
- Change a component's CSS layout (e.g., "change chip from inline-flex to flex")
- Add visual styling for a new state (e.g., "add selected state styles to badge")
- Create layout/theme skeletons for a new component (as part of
component)
- Wire up a new component's
_index.scss and register it in a theme's entry point
- Add or change a component's dependencies
- Add box-shadow, border-radius, or other visual properties
Not for variable declarations (use manage-scss-variables) or design system foundation modules like spacing/color-system/typography (use manage-scss-modules).
Inputs
| Input |
Required |
Description |
| Component name |
Yes |
kebab-case (e.g., chip, button, info-bar) |
| Changes |
Yes |
Description of structural or visual changes, or "scaffold" for new components |
| Target themes |
No |
Which themes to update: all, or a list like default, fluent. Default: ask the user |
| Scope |
No |
layout, theme, module, register, or all. Default: inferred from changes. |
| Dependencies |
No |
Other components this depends on (e.g., icon, button) |
Procedure
Step 1: Classify the changes
- Structural properties →
_layout.scss: display, flex, grid, padding, margin, gap, position, overflow, box-sizing, font metrics
- Visual properties →
_theme.scss: color, background, border-color, box-shadow, opacity, outline, text-decoration
- Wiring →
_index.scss: dependencies, variable forwarding, mixin exposure
- Registration → theme
index.scss: @forward + @include in entry point
For new components, all four are needed.
Step 2: Apply layout and theme to core
Edit packages/core/scss/components/{component}/_layout.scss and/or _theme.scss.
Layout mixin (kendo-{component}--layout-base):
@mixin kendo-{component}--layout-base() {
.k-{component} {
// structural properties referencing $kendo-{component}-* variables
}
}
Theme mixin (kendo-{component}--theme-base):
@mixin kendo-{component}--theme-base() {
.k-{component} {
// visual properties referencing $kendo-{component}-* variables
}
}
Rules:
- Never assign concrete values in core — only reference
$kendo-{component}-* variables
- Keep the mixin names unchanged (
--layout-base, --theme-base)
- New CSS properties that need customization require new variables (use
manage-scss-variables skill first)
- State selectors:
.k-{component}.k-hover, .k-{component}.k-selected, etc.
- For new components, use templates from ../_shared/file-templates.md
Step 3: Apply layout and theme to targeted themes
Most themes delegate directly to core and don't need changes:
// packages/{theme}/scss/{component}/_layout.scss
@mixin kendo-{component}--layout() {
@include kendo-{component}--layout-base();
}
Only edit theme-specific layout/theme files when:
- A theme needs to override core's structure (rare)
- A theme adds extra selectors not in core
- A theme has theme-specific visual tweaks beyond variables
For new components, use templates from ../_shared/file-templates.md.
Step 4: Create or update _index.scss
For each theme in the target themes list, create or edit packages/{theme}/scss/{component}/_index.scss:
// Dependencies
@use "../core/_index.scss" as *;
// Component
@forward "./_variables.scss";
@use "./_layout.scss" as *;
@use "./_theme.scss" as *;
// Expose
@mixin kendo-{component}--styles() {
@include import-once( "{component}" ) {
@include core-styles();
@include kendo-{component}--layout();
@include kendo-{component}--theme();
}
}
If the component has dependencies on other components, add them after core:
// Dependencies
@use "../core/_index.scss" as *;
@use "../icon/_index.scss" as *;
@use "../button/_index.scss" as *;
Step 5: Register in theme entry point (new components only)
Edit packages/{theme}/scss/index.scss for each targeted theme:
Add @forward — in the existing @forward section, preserving the dependency-based order used in the file (do not reorder alphabetically):
@forward "./{component}/_index.scss";
Add @include — inside @mixin kendo-theme--styles(), in the appropriate category group:
@include kendo-{component}--styles();
Step 6: Validate
npm run lint:styles 2>&1
npm run sass 2>&1
Gotchas
- Core changes propagate automatically — most themes call
@include kendo-{component}--layout-base(), so changes to core affect all themes.
- New CSS properties need variables — don't hardcode values in core. Add a variable via
manage-scss-variables first, then reference it here.
- State classes, not pseudo-classes — use
.k-{component}.k-hover (class applied by JS), not .k-{component}:hover (CSS pseudo).
- BEM naming — sub-elements:
.k-{component}-{element}, modifiers: .k-{component}-{modifier}.
- Component names in
@include import-once("...") must be unique across the entire theme.
@forward must come before any @use of the same module — SCSS module system requirement.
- Order matters in
index.scss — dependencies must be @included before the components that use them.
- Check
packages/{theme}/scss/index.scss to verify the registration location — components should be added in dependency order within the appropriate category group.
backdrop-filter/filter on a container traps position: fixed descendants — per the Filter Effects spec, applying backdrop-filter (or filter) directly to an element creates a CSS containing block for that element's position: fixed/absolute descendants. If the element also has overflow: hidden (common on k- root containers), any inline-declared Popup/Dialog/Tooltip nested inside it (rather than portaled to <body>) gets visually clipped to the container's bounds instead of overlaying the viewport (see kendo-themes#5968, #6096). This is the root cause behind Meridian's translucency/glass effect on components like .k-card, .k-appbar, .k-bottom-nav, .k-drawer, .k-expander, .k-pager. Fix pattern: move backdrop-filter off the real element onto a content-less ::before pseudo-element (content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;) — a pseudo-element has no descendants, so it can carry the filter without trapping anything. If the base selector has no default position, add position: relative (scoped with :not() around any modifier classes that already set position: fixed/sticky, e.g. .k-appbar:not(.k-appbar-fixed):not(.k-appbar-sticky)) so the pseudo sizes correctly. Do not use isolation: isolate as a shortcut — it can create unrelated stacking-context regressions for siblings. Before reusing an element's ::before/::after for this, check it isn't already used for something else (e.g. .k-toolbar's pseudo-elements are already used for spacer/scroll-fade effects — see kendo-themes#6121 — so that one needs a different approach).
1---2name: manage-scss-styles3description: Create or update SCSS layout mixins, theme mixins, module entry points (_index.scss), and registration in theme entry points for a Kendo UI component. Covers the full component SCSS lifecycle — structural styles, visual styles, wiring, and registration. Use this skill when the user wants to change a component's CSS structure, add visual states, create the style skeleton for a new component, wire up dependencies, or register a component in a theme.4---56# SCSS Styles78Create or update layout, theme, module, and registration files for a component in core and targeted themes.910Read [../_shared/component-context.md](../_shared/component-context.md) for naming conventions, theme paths, and common gotchas.1112## When to use1314When the user asks to:15- Change a component's CSS layout (e.g., "change chip from inline-flex to flex")16- Add visual styling for a new state (e.g., "add selected state styles to badge")17- Create layout/theme skeletons for a new component (as part of `component`)18- Wire up a new component's `_index.scss` and register it in a theme's entry point19- Add or change a component's dependencies20- Add box-shadow, border-radius, or other visual properties2122Not for variable declarations (use `manage-scss-variables`) or design system foundation modules like spacing/color-system/typography (use `manage-scss-modules`).2324## Inputs2526| Input | Required | Description |27|-------|----------|-------------|28| **Component name** | Yes | kebab-case (e.g., `chip`, `button`, `info-bar`) |29| **Changes** | Yes | Description of structural or visual changes, or "scaffold" for new components |30| **Target themes** | No | Which themes to update: `all`, or a list like `default, fluent`. Default: **ask the user** |31| **Scope** | No | `layout`, `theme`, `module`, `register`, or `all`. Default: inferred from changes. |32| **Dependencies** | No | Other components this depends on (e.g., `icon`, `button`) |3334## Procedure3536### Step 1: Classify the changes3738- **Structural properties** → `_layout.scss`: display, flex, grid, padding, margin, gap, position, overflow, box-sizing, font metrics39- **Visual properties** → `_theme.scss`: color, background, border-color, box-shadow, opacity, outline, text-decoration40- **Wiring** → `_index.scss`: dependencies, variable forwarding, mixin exposure41- **Registration** → theme `index.scss`: `@forward` + `@include` in entry point4243For new components, all four are needed.4445### Step 2: Apply layout and theme to core4647Edit `packages/core/scss/components/{component}/_layout.scss` and/or `_theme.scss`.4849**Layout mixin** (`kendo-{component}--layout-base`):50```scss51@mixin kendo-{component}--layout-base() {52 .k-{component} {53 // structural properties referencing $kendo-{component}-* variables54 }55}56```5758**Theme mixin** (`kendo-{component}--theme-base`):59```scss60@mixin kendo-{component}--theme-base() {61 .k-{component} {62 // visual properties referencing $kendo-{component}-* variables63 }64}65```6667**Rules:**68- Never assign concrete values in core — only reference `$kendo-{component}-*` variables69- Keep the mixin names unchanged (`--layout-base`, `--theme-base`)70- New CSS properties that need customization require new variables (use `manage-scss-variables` skill first)71- State selectors: `.k-{component}.k-hover`, `.k-{component}.k-selected`, etc.72- For new components, use templates from [../_shared/file-templates.md](../_shared/file-templates.md)7374### Step 3: Apply layout and theme to targeted themes7576Most themes delegate directly to core and don't need changes:7778```scss79// packages/{theme}/scss/{component}/_layout.scss80@mixin kendo-{component}--layout() {81 @include kendo-{component}--layout-base();82}83```8485Only edit theme-specific layout/theme files when:86- A theme needs to **override** core's structure (rare)87- A theme adds **extra selectors** not in core88- A theme has **theme-specific** visual tweaks beyond variables8990For new components, use templates from [../_shared/file-templates.md](../_shared/file-templates.md).9192### Step 4: Create or update `_index.scss`9394For each theme in the **target themes** list, create or edit `packages/{theme}/scss/{component}/_index.scss`:9596```scss97// Dependencies98@use "../core/_index.scss" as *;99100// Component101@forward "./_variables.scss";102@use "./_layout.scss" as *;103@use "./_theme.scss" as *;104105// Expose106@mixin kendo-{component}--styles() {107 @include import-once( "{component}" ) {108 @include core-styles();109 @include kendo-{component}--layout();110 @include kendo-{component}--theme();111 }112}113```114115If the component has **dependencies** on other components, add them after core:116117```scss118// Dependencies119@use "../core/_index.scss" as *;120@use "../icon/_index.scss" as *;121@use "../button/_index.scss" as *;122```123124### Step 5: Register in theme entry point (new components only)125126Edit `packages/{theme}/scss/index.scss` for each targeted theme:1271281. **Add `@forward`** — in the existing `@forward` section, preserving the dependency-based order used in the file (do not reorder alphabetically):129 ```scss130 @forward "./{component}/_index.scss";131 ```1321332. **Add `@include`** — inside `@mixin kendo-theme--styles()`, in the appropriate category group:134 ```scss135 @include kendo-{component}--styles();136 ```137138### Step 6: Validate139140```bash141npm run lint:styles 2>&1142npm run sass 2>&1143```144145## Gotchas146147- **Core changes propagate automatically** — most themes call `@include kendo-{component}--layout-base()`, so changes to core affect all themes.148- **New CSS properties need variables** — don't hardcode values in core. Add a variable via `manage-scss-variables` first, then reference it here.149- **State classes, not pseudo-classes** — use `.k-{component}.k-hover` (class applied by JS), not `.k-{component}:hover` (CSS pseudo).150- **BEM naming** — sub-elements: `.k-{component}-{element}`, modifiers: `.k-{component}-{modifier}`.151- **Component names in `@include import-once("...")` must be unique** across the entire theme.152- **`@forward` must come before any `@use` of the same module** — SCSS module system requirement.153- **Order matters in `index.scss`** — dependencies must be `@include`d before the components that use them.154- Check `packages/{theme}/scss/index.scss` to verify the registration location — components should be added in dependency order within the appropriate category group.155- **`backdrop-filter`/`filter` on a container traps `position: fixed` descendants** — per the Filter Effects spec, applying `backdrop-filter` (or `filter`) directly to an element creates a CSS containing block for that element's `position: fixed`/`absolute` descendants. If the element also has `overflow: hidden` (common on `k-` root containers), any inline-declared Popup/Dialog/Tooltip nested inside it (rather than portaled to `<body>`) gets visually clipped to the container's bounds instead of overlaying the viewport (see kendo-themes#5968, #6096). This is the root cause behind Meridian's translucency/glass effect on components like `.k-card`, `.k-appbar`, `.k-bottom-nav`, `.k-drawer`, `.k-expander`, `.k-pager`. **Fix pattern**: move `backdrop-filter` off the real element onto a content-less `::before` pseudo-element (`content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;`) — a pseudo-element has no descendants, so it can carry the filter without trapping anything. If the base selector has no default `position`, add `position: relative` (scoped with `:not()` around any modifier classes that already set `position: fixed`/`sticky`, e.g. `.k-appbar:not(.k-appbar-fixed):not(.k-appbar-sticky)`) so the pseudo sizes correctly. Do **not** use `isolation: isolate` as a shortcut — it can create unrelated stacking-context regressions for siblings. Before reusing an element's `::before`/`::after` for this, check it isn't already used for something else (e.g. `.k-toolbar`'s pseudo-elements are already used for spacer/scroll-fade effects — see kendo-themes#6121 — so that one needs a different approach).