Theming Guide
AS Community widgets are styled using CSS custom properties (design tokens) inside a Shadow DOM. This guide explains how to apply tenant-specific themes correctly.
How Shadow DOM Affects Styling
All asc-* components render inside a Shadow DOM. This means:
- Light-DOM stylesheets (i.e., a
<style>block on the host page) cannot style elements inside the shadow root. - CSS custom properties do pierce the shadow boundary — they are inherited by shadow DOM children.
❌ What does NOT work
<!-- These styles cannot reach inside the shadow root -->
<style>
asc-comment-widget .c-comment-widget {
background: red;
}
</style>✅ What DOES work
CSS custom properties set on the host element are visible inside the shadow root:
<style>
asc-comment-widget {
--asc-color-interactive: #e30613;
}
</style>But the recommended approach is to use the theme-url attribute or tenantConfig.theme — both inject overrides via adoptedStyleSheets (see below).
Recommended Approach: theme-url Attribute
Point the widget at a theme.overrides.json file:
<asc-comment-widget
article-id="my-article"
tenant-id="my-tenant"
api-base-url="https://api.example.com"
theme-url="/themes/my-tenant.json"
>
</asc-comment-widget>The JSON file is a flat map of CSS custom property names to values:
{
"--asc-color-interactive": "#e30613",
"--asc-color-interactive-hover": "#b0040e",
"--asc-color-brand-600": "#e30613",
"--asc-font-family-body": "'Arial', sans-serif"
}Alternative: tenantConfig.theme
If you're already loading the full tenant config, include theme directly:
const widget = document.querySelector('asc-comment-widget');
widget.tenantConfig = {
id: 'welt',
api: { baseUrl: 'https://api.welt.de', tenantId: 'welt' },
branding: { displayName: 'WELT' },
theme: {
'--asc-color-interactive': '#e30613',
'--asc-color-brand-600': '#e30613',
},
};How adoptedStyleSheets Works Internally
When a theme is applied (via theme-url or tenantConfig.theme), the widget:
- Creates a
CSSStyleSheetwith:host { --var: value; ... }rules. - Appends it to
shadowRoot.adoptedStyleSheetsafter Lit's static styles.
Because later entries in adoptedStyleSheets win in cascade order, tenant overrides always take priority over component defaults — without touching any style attribute on the host element.
shadowRoot.adoptedStyleSheets = [
...litStaticStyles, // component defaults
tenantThemeSheet, // tenant overrides — wins
]Semantic Token Reference
These are the tokens to override for visual customization. All defaults reference base scale tokens.
Text Colors
| Token | Default |
|---|---|
--asc-color-text-primary | var(--asc-color-neutral-900) |
--asc-color-text-secondary | var(--asc-color-neutral-600) |
--asc-color-text-tertiary | var(--asc-color-neutral-400) |
--asc-color-text-disabled | var(--asc-color-neutral-300) |
--asc-color-text-inverse | var(--asc-color-neutral-0) |
--asc-color-text-link | var(--asc-color-brand-600) |
--asc-color-text-link-hover | var(--asc-color-brand-800) |
Background Colors
| Token | Default |
|---|---|
--asc-color-bg-surface | var(--asc-color-neutral-0) |
--asc-color-bg-subtle | var(--asc-color-neutral-50) |
--asc-color-bg-muted | var(--asc-color-neutral-100) |
--asc-color-bg-overlay | var(--asc-color-neutral-200) |
Interactive (Buttons, Vote Controls, Focus)
| Token | Default |
|---|---|
--asc-color-interactive | var(--asc-color-brand-600) |
--asc-color-interactive-hover | var(--asc-color-brand-700) |
--asc-color-interactive-active | var(--asc-color-brand-800) |
--asc-color-interactive-subtle | var(--asc-color-brand-50) |
Borders
| Token | Default |
|---|---|
--asc-color-border | var(--asc-color-neutral-200) |
--asc-color-border-strong | var(--asc-color-neutral-400) |
--asc-color-border-focus | var(--asc-color-brand-500) |
Status
| Token | Default |
|---|---|
--asc-color-status-error | var(--asc-color-error) |
--asc-color-status-error-bg | var(--asc-color-error-light) |
--asc-color-status-warning | var(--asc-color-warning) |
--asc-color-status-warning-bg | var(--asc-color-warning-light) |
--asc-color-status-success | var(--asc-color-success) |
--asc-color-status-success-bg | var(--asc-color-success-light) |
Typography
| Token | Default |
|---|---|
--asc-font-family-body | var(--asc-font-family-sans) |
--asc-font-family-heading | var(--asc-font-family-sans) |
Spacing & Shape
| Token | Default |
|---|---|
--asc-component-padding-sm | var(--asc-spacing-2) var(--asc-spacing-3) |
--asc-component-padding-md | var(--asc-spacing-3) var(--asc-spacing-4) |
--asc-component-padding-lg | var(--asc-spacing-4) var(--asc-spacing-6) |
--asc-component-radius | var(--asc-border-radius-md) |
--asc-focus-ring | 0 0 0 2px var(--asc-color-border-focus) |
Base Token Overrides
You can also override base scale tokens directly. Common overrides:
{
"--asc-color-brand-600": "#e30613",
"--asc-color-brand-700": "#b0040e",
"--asc-color-brand-50": "#fff0f0",
"--asc-font-family-sans": "'Helvetica Neue', Arial, sans-serif"
}Base tokens are: neutral scale (--asc-color-neutral-*), brand scale (--asc-color-brand-*), status colors, spacing (--asc-spacing-*), border radius, font families, font sizes, font weights, line heights, shadows, transitions.
theme.overrides.json Format
The file served at theme-url must be valid JSON — a flat object where every key starts with --:
{
"--asc-color-interactive": "#e30613",
"--asc-color-interactive-hover": "#b0040e",
"--asc-color-brand-600": "#e30613",
"--asc-font-family-body": "'Arial', sans-serif",
"--asc-component-radius": "0"
}Keys not starting with -- are silently ignored.
Component-Level CSS Variables
In addition to semantic tokens, each component exposes its own --asc-c-[component]-* variables. These let you fine-tune a single component without changing the global semantic tokens.
Set them the same way as semantic tokens — in your theme.overrides.json or tenantConfig.theme:
{
"--asc-c-comment-form-submit-bg": "#e30613",
"--asc-c-comment-widget-max-width": "60rem"
}asc-comment-widget
| Variable | Fallback | Description |
|---|---|---|
--asc-c-comment-widget-title-color | var(--asc-color-text-primary) | Widget title text color |
--asc-c-comment-widget-title-font-size | var(--asc-font-size-lg) | Widget title font size |
--asc-c-comment-widget-title-font-weight | var(--asc-font-weight-semibold) | Widget title font weight |
--asc-c-comment-widget-sort-btn-color | var(--asc-color-text-secondary) | Sort button text color |
--asc-c-comment-widget-sort-btn-active-color | var(--asc-color-text-primary) | Active sort button text color |
--asc-c-comment-widget-sort-btn-active-bg | var(--asc-color-bg-muted) | Active sort button background |
--asc-c-comment-widget-sort-btn-active-border-color | var(--asc-color-border) | Active sort button border color |
--asc-c-comment-widget-max-width | 48rem | Max width of the widget container |
asc-comment-item
| Variable | Fallback | Description |
|---|---|---|
--asc-c-comment-item-author-color | var(--asc-color-text-primary) | Author display name color |
--asc-c-comment-item-content-color | var(--asc-color-text-primary) | Comment body text color |
--asc-c-comment-item-content-deleted-color | var(--asc-color-text-tertiary) | Deleted comment placeholder color |
--asc-c-comment-item-timestamp-color | var(--asc-color-text-tertiary) | Relative timestamp color |
--asc-c-comment-item-edited-badge-color | var(--asc-color-text-tertiary) | "(edited)" badge color |
--asc-c-comment-item-action-btn-color | var(--asc-color-text-secondary) | Reply/edit/delete button color |
--asc-c-comment-item-action-btn-hover-color | var(--asc-color-text-primary) | Action button hover color |
--asc-c-comment-item-action-btn-danger-color | var(--asc-color-status-error) | Delete button color |
--asc-c-comment-item-thread-line-color | var(--asc-color-border) | Vertical thread indent line color |
--asc-c-comment-item-thread-line-hover-color | var(--asc-color-border-strong) | Thread line hover color |
asc-comment-form
| Variable | Fallback | Description |
|---|---|---|
--asc-c-comment-form-submit-bg | var(--asc-color-interactive) | Submit button background |
--asc-c-comment-form-submit-hover-bg | var(--asc-color-interactive-hover) | Submit button hover background |
--asc-c-comment-form-submit-color | var(--asc-color-text-inverse) | Submit button text color |
--asc-c-comment-form-submit-radius | var(--asc-border-radius-md) | Submit button border radius |
--asc-c-comment-form-textarea-bg | var(--asc-color-bg-surface) | Textarea background color |
--asc-c-comment-form-textarea-color | var(--asc-color-text-primary) | Textarea text color |
--asc-c-comment-form-textarea-border-color | var(--asc-color-border) | Textarea border color |
--asc-c-comment-form-textarea-focus-border-color | var(--asc-color-border-focus) | Textarea focus ring border color |
--asc-c-comment-form-textarea-radius | var(--asc-border-radius-md) | Textarea border radius |
--asc-c-comment-form-cancel-color | var(--asc-color-text-secondary) | Cancel button text color |
--asc-c-comment-form-cancel-border-color | var(--asc-color-border) | Cancel button border color |
--asc-c-comment-form-char-count-color | var(--asc-color-text-tertiary) | Character count indicator color |
asc-vote-buttons
| Variable | Fallback | Description |
|---|---|---|
--asc-c-vote-buttons-btn-color | var(--asc-color-text-secondary) | Vote button icon/text color |
--asc-c-vote-buttons-btn-active-color | var(--asc-color-interactive) | Active (voted) button color |
--asc-c-vote-buttons-btn-hover-bg | var(--asc-color-bg-muted) | Vote button hover background |
--asc-c-vote-buttons-btn-hover-color | var(--asc-color-text-primary) | Vote button hover text/icon color |
--asc-c-vote-buttons-btn-radius | var(--asc-border-radius-md) | Vote button border radius |
asc-comment-list
| Variable | Fallback | Description |
|---|---|---|
--asc-c-comment-list-empty-color | var(--asc-color-text-tertiary) | Empty state text color |
--asc-c-comment-list-skeleton-bg | var(--asc-color-bg-muted) | Skeleton block background color |
--asc-c-comment-list-load-more-color | var(--asc-color-text-secondary) | "Load more" button text color |
--asc-c-comment-list-load-more-border-color | var(--asc-color-border) | "Load more" button border color |
asc-reply-list
| Variable | Fallback | Description |
|---|---|---|
--asc-c-reply-list-border-color | var(--asc-color-border) | Left-border color on the reply indent container |
--asc-c-reply-list-load-btn-color | var(--asc-color-interactive) | "N replies" toggle button color |
--asc-c-reply-list-load-btn-hover-color | var(--asc-color-interactive-hover) | "N replies" toggle button hover color |
--asc-c-reply-list-load-more-color | var(--asc-color-text-secondary) | "Load more replies" button color |