Skip to content

Theming ​

Every UI color and shadow in the library is controlled by CSS variables. The light-theme defaults are identical to the previous hard-coded values, so upgrading requires no configuration. To re-skin the component, override the variables instead of patching internal class names.

Quick re-skin ​

Override variables at the document root or in any scope:

css
:root {
  --stack-tab-accent: #4f46e5;
  --stack-tab-accent-active: #4338ca;
  --stack-tab-accent-contrast: #fff;
}

Changing the accent alone updates tab hover, the drag indicator, the scrollbar thumb, the primary badge and context-menu hover.

Dark theme ​

A neutral dark palette is built in and can be activated in three ways:

html
<!-- Common convention in the Element Plus / VueUse ecosystem -->
<html class="dark"></html>

<!-- Explicit theme marker -->
<html data-theme="dark"></html>

<!-- Scoped dark container -->
<div data-theme="dark">
  <vue-stack-tabs />
</div>

The dark block also sets color-scheme: dark, so native scrollbars and form controls follow.

Every theme block (light defaults, size presets, dark) is wrapped in :where(), so it has zero specificity. A plain :root override therefore wins over both the light defaults and the dark values — no :root:root workaround needed:

css
/* Applies to both light and dark */
:root {
  --stack-tab-accent: #4f46e5;
}

/* Dark only */
:root.dark {
  --stack-tab-accent: #818cf8;
  --stack-tab-surface: #0b1120;
  --stack-tab-surface-muted: #172033;
  --stack-tab-border: #263244;
}

Variables ​

Accent ​

VariableLight defaultUsed for
--stack-tab-accent#409effTab hover/active, drag indicator, scrollbar thumb, menu hover
--stack-tab-accent-active#337eccPressed accent
--stack-tab-accent-contrast#ffffffText/icons on accent backgrounds, badge text
--stack-tab-accent-shadow#409effccDrag indicator glow
--stack-tab-menu-hover-bg#409effContext-menu hover background (dark uses pressed accent)
--stack-tab-menu-hover-text#ffffffContext-menu hover text/icons (dark uses #f8fafc)

Surfaces and borders ​

VariableLight defaultUsed for
--stack-tab-surface#fffContent area, active tab, header buttons, context menu, retry buttons
--stack-tab-surface-muted#fafafaInactive tabs, disabled buttons
--stack-tab-overlay#fffGlobal loading overlay
--stack-tab-border#f0f0f0Header bottom border, tab/menu/button borders
--stack-tab-divider#a9a9a9Context-menu divider

Text and icons ​

VariableLight defaultUsed for
--stack-tab-text#4d4d4dTab labels, menu items, iframe retry buttons
--stack-tab-text-strong#000Label of the tab that opened the context menu
--stack-tab-text-disabled#aaaDisabled text and icons
--stack-tab-mask#4d4d4dClose icon, scroll mask buttons, menu icons
--stack-tab-scrollbar#0000001aHorizontal scrollbar

Shadows ​

Shadows use two layers: color layers control opacity, composite layers control geometry. Prefer overriding the composite layer for a complete replacement; override the color layer when only the intensity should change.

VariableLight defaultUsed for
--stack-tab-shadow-color#0009Tab shadows and inset utility classes
--stack-tab-shadow-soft#0000001aSoft context-menu shadow
--stack-tab-shadow-tab-5px 0 5px -5px + 5px 0 5px -5pxActive tab shadow
--stack-tab-shadow-tab-left-5px 0 5px -5px.stack-tab__shadow-left
--stack-tab-shadow-tab-right5px 0 5px -5px.stack-tab__shadow-right
--stack-tab-shadow-menu5px 5px 5pxContext-menu shadow
--stack-tab-shadow-drop0 0 6pxDrag indicator glow
--stack-tab-shadow-inset-topinset 0 5px 5px -5pxContent top scroll shadow
--stack-tab-shadow-inset-bottominset 0 -5px 5px -5pxContent bottom scroll shadow
--stack-tab-shadow-inset-verticalOne at top and bottomContent vertical scroll shadow
--stack-tab-shadow-inset-leftinset 5px 0 5px -5pxContent left scroll shadow
--stack-tab-shadow-inset-rightinset -5px 0 5px -5pxContent right scroll shadow
--stack-tab-shadow-inset-allOne on each sideContent horizontal scroll shadow

The .stack-tab__shadow-inset-* utilities consume the matching --stack-tab-shadow-inset-* composite variable; the dark theme widens their geometry to 12/14px while the color still comes from --stack-tab-shadow-color.

Badge, loading and iframe ​

VariableLight defaultUsed for
--stack-tab-badge-default#ef4f4fDefault badge
--stack-tab-badge-primary#409effPrimary badge
--stack-tab-loading-accent60% of accentLoading spinner (follows the accent)
--stack-tab-iframe-loading-bg#f5f5f5iframe loading background
--stack-tab-iframe-loading-color#999iframe loading text
--stack-tab-iframe-error-bg#ffffffebiframe error background
--stack-tab-iframe-error-color#666iframe error text

Layout and size ​

VariableDefaultUsed for
--stack-tab-font-size14pxTab, context-menu and iframe text size
--stack-tab-head-height40pxTab header height
--stack-tab-context-menu-item-height30pxContext-menu item height
--stack-tab-context-menu-padding8pxContext-menu padding

Three size presets are built in and activated with data-stack-tab-size (scoped containers work too):

html
<html data-stack-tab-size="small"></html>
<!-- normal / large work the same way; variables can also be overridden directly -->

Size presets are wrapped in :where() too, so overriding --stack-tab-font-size (or the other layout variables) on :root wins over the preset.

PresetFont sizeHeader heightMenu item heightMenu padding
small12px32px26px6px
normal14px40px30px8px
large16px48px36px10px

Scoped overrides ​

Variables are declared on :where(:root) (zero specificity); overriding them in any scope only affects that subtree:

css
.side-layout {
  --stack-tab-accent: #10b981;
}

Notes ​

  • Light-theme defaults match the old hard-coded values, so the visual result is unchanged after upgrading.
  • Dark backgrounds swallow black shadows, so the dark theme uses an outline + accent glow + top highlight instead, and raises --stack-tab-border to #334155. Override --stack-tab-shadow-tab / --stack-tab-shadow-menu to make the shadows stronger or softer.
  • These variables are a public API from 2.4.0 on: they are only added, never renamed.
  • Theme selectors use :where() for zero specificity, so a plain :root override applies in both light and dark mode; avoid high-specificity workarounds such as :root:root. :where() is supported in Chrome 88+ / Safari 14+ / Firefox 78+, which is not an extra restriction given the color-mix() (Chrome 111+) already used by the library.

Released under the Apache License.