Skip to main content
Remark ships two custom elements: <remark-chat-widget> for the floating chat and <remark-qa-activator> for the embedded chat (also known as the inline activator). Both share the same theme system and can be customized at two levels: through widget settings in the Remark dashboard, and through custom CSS targeting Shadow DOM parts and CSS custom properties. Widget settings handle the most common adjustments. Custom CSS picks up where widget settings leave off, giving you control over individual elements.

Widget Settings

Configure colors, typography, spacing, layout, and behavior from the dashboard.

CSS Custom Properties

Override sizing tokens and reference generated color tokens.

Shadow DOM Parts

Target specific elements using the ::part() pseudo-element.

Full Example

A complete example combining tokens and part selectors.

Widget Settings

The Remark dashboard provides visual controls for theming, layout, and behavior across three pages — no CSS required.

Appearance

The Appearance page (Settings > Appearance) is the primary way to theme both widgets. These settings apply to the floating chat and the embedded chat together.
SettingControls
Brand colorPrimary color used to generate the full theme palette
Color schemeLight, dark, or auto (matches the user’s system preference)
Text colorContent and text color
Background colorSurface background color
Button colorColor of the chat input send button and floating activator button background
Border colorBorder and divider color
Online indicatorOnline/available status indicator color
Error colorError and critical state color
Font familyCustom font stack (popular Google Fonts are loaded automatically)
Font sizeBase font size in pixels (minimum 10 px) — all typography scales from this
PaddingInternal spacing (sm, md, lg, or a custom pixel value)
Border roundnessCorner radius (sm, md, lg, or a custom pixel value)
Spacing scaleUnitless multiplier that scales all internal spacing
Each palette color is optional. When a value isn’t provided, the theme system generates an appropriate color from the brand color automatically, with both light and dark mode variants. The Appearance page also includes a Custom CSS field for advanced overrides (see sections 2 and 3 below). Custom rules must target remark-chat-widget or remark-qa-activator in their selectors. The Custom CSS field supports @media, @supports, and other at-rules, so you can write responsive ::part() overrides directly in the dashboard.

Chat Settings

The Chat page (Settings > Features > Chat) controls the floating chat widget’s layout and behavior.
SettingControls
Enable chatShow or hide the floating chat widget
Turn off chat when no experts are onlineAutomatically hide the widget when no experts are available
Allow transfer to humanWhether AI can hand off to a human expert (always or only when online)
Activator styleButton (floating action button) or text bar
PositionLeft, center (text bar only), or right
Enable activator animationShow the icon animation on the button activator

Inline Activator Settings

The Inline Activator page (Settings > Features > Inline Activator) controls the embedded chat.
SettingControls
Enable activatorShow or hide the embedded chat
Activator typeExpert (shows featured expert header) or text-only
Interaction modeInline (conversations stay within the embedded chat) or handoff (opens the floating chat widget)
CSS selectorWhich page element the embedded chat is inserted relative to
Activator positionInsert before or after the selected element
We recommend using widget settings over custom CSS when possible. Settings available in the dashboard have been tested to work cohesively and adapt to light and dark mode automatically.

CSS Custom Properties

The chat widget’s theme system generates CSS custom properties that you can reference in custom CSS rules. These properties are grouped into sizing tokens (which can be overridden directly) and color tokens (which are generated from widget settings).

Sizing and Typography

These properties are set on the widget’s root element — <remark-chat-widget> or <remark-qa-activator>. Override them by targeting that element directly in your CSS, the same way you’d style any other HTML element. They correspond to dashboard settings but can also be overridden in custom CSS when finer control is needed.
VariableDefaultControlsDashboard Setting
--hem16pxBase font size unit — all typography scales as a ratio of this valueFont size
--remark-spacing-multiplier1Unitless multiplier for all spacing tokensSpacing scale
--remark-radii-base0.5remBase border radiusBorder roundness
--remark-fonts-sansSystem font stackFont family for all textFont family
--hem stands for “host em” — it serves the same role as rem but is scoped to the widget’s shadow DOM root rather than the page’s <html> element. This means the widget’s typography scales independently of the host page’s font size. Font sizes are not exposed as individual variables; they are calculated as ratios of --hem (e.g., base text = --hem, small text = calc(var(--hem) * 14 / 16)). To scale all text proportionally, adjust the font size in the dashboard or override --hem in custom CSS.
--hem is already responsive to the host page’s root font size. If your site already adjusts font-size on <html> for different viewports, the widget may scale along with it automatically depending on your configuration.

Colors

Color tokens are generated from the brand color and palette overrides configured in the dashboard. They follow the naming pattern --remark-colors-{name} and have separate light and dark mode values. These tokens are set on an internal element within the shadow DOM. You can reference them in ::part() rules, but to change colors, use the dashboard palette settings rather than overriding variables directly.

Content

VariablePurpose
--remark-colors-content-defaultPrimary text
--remark-colors-content-secondarySecondary text
--remark-colors-content-mutedDe-emphasized text
--remark-colors-content-actionBrand-tinted text meeting contrast requirements

Backgrounds

VariablePurpose
--remark-colors-background-defaultPrimary background
--remark-colors-background-hoverBackground on hover
--remark-colors-background-secondarySecondary background (e.g., alternate message rows)

Borders

VariablePurpose
--remark-colors-border-defaultDefault border
--remark-colors-border-subtleSubtle or secondary border
--remark-colors-border-activeActive or focused border
--remark-colors-border-emphasisEmphasized border

Brand

VariablePurpose
--remark-colors-brand-fillBrand color fill
--remark-colors-brand-on-fillText on brand fill
--remark-colors-brand-subduedSubdued brand tint
--remark-colors-brand-contentBrand color for text
--remark-colors-brand-borderBrand color for borders

Action

These correspond to the Button color override in the dashboard.
VariablePurpose
--remark-colors-action-fillInteractive element fill (send button, floating activator)
--remark-colors-action-on-fillText on action fill
--remark-colors-action-hoverInteractive element fill on hover

Status

VariablePurpose
--remark-colors-online-fillOnline indicator
--remark-colors-online-on-fillText on online indicator
--remark-colors-critical-fillError or critical fill
--remark-colors-critical-on-fillText on critical fill
--remark-colors-critical-contentCritical color for text
--remark-colors-critical-borderCritical color for borders

Elevated Surfaces

VariablePurpose
--remark-colors-elevated-fillElevated surface (cards, dropdowns)
--remark-colors-elevated-hoverElevated surface on hover
--remark-colors-elevated-on-fillText on elevated surfaces

Overlays and Inverse

VariablePurpose
--remark-colors-overlay-fillSemi-transparent overlay
--remark-colors-overlay-emphasis-fillStrong overlay
--remark-colors-inverse-backgroundInverted background
--remark-colors-inverse-contentInverted text

Shadow DOM Parts

Both remark-chat-widget and remark-qa-activator expose internal elements through the part attribute. You can target those elements from outside the shadow tree with the ::part() pseudo-element. Many parts carry scene suffixes so you can style the same structural element differently depending on context. The widget has three scenes: landing (before the conversation starts), chat (active conversation), and paused (conversation active on another device). For example, widget-header matches the header in any scene, while widget-header-landing targets only the landing screen header. Some elements also expose a skeleton token during loading states for styling placeholders.

Floating Activators

These parts control the entry point to the floating chat — the button or text bar that visitors click to open the conversation. They are not present on the embedded chat (inline activator).
PartElement
activator-parentActivator root container
activator-buttonFloating action button activator
activator-button-iconIcon inside button activator
activator-messageFloating message bubble
activator-message-avatarMessage bubble avatar
activator-message-textMessage bubble text
activator-message-dismissMessage dismiss button
activator-text-bar-buttonText bar button
activator-text-bar-badgeUnread badge
activator-text-bar-iconSearch icon
activator-text-bar-placeholderTypewriter or placeholder text
activator-text-bar-send-iconSend icon button
back-to-bottom-buttonScroll-to-bottom button
back-to-bottom-button-unread-badgeUnread badge on scroll button

Shared Parts

The remaining parts are shared by both the floating chat and the embedded chat (inline activator).

Widget Shell

The outermost structural elements that wrap the widget’s header, content area, and footer. Scene suffixes let you style each section differently on the landing screen, during an active conversation, or while paused.
PartElement
parent-containerOutermost shadow DOM container
app-parentWidget root (floating or embedded)
widget-headerHeader slot
widget-header-landingHeader on the landing scene
widget-header-chatHeader during an active conversation
widget-contentMain content slot
widget-content-landingContent on the landing scene
widget-content-chatContent during an active conversation
widget-content-pausedContent on the paused scene
widget-footerFooter slot
widget-footer-landingFooter on the landing scene
widget-footer-chatFooter during an active conversation

Chat Header

The header bar at the top of the chat, showing brand and expert info. Visible once the widget is open (floating) or always visible (embedded). The header-content container carries a scene suffix so you can style the header differently on the landing screen vs. during a conversation.
PartElement
header-contentHeader content container
header-content-landingHeader content on the landing scene
header-content-chatHeader content during an active conversation
chat-header-avatarExpert avatar
chat-header-brand-nameBrand name heading
chat-header-expert-triggerClickable area that opens the expert profile
chat-header-expert-nameExpert name heading
chat-header-taglineExpert tagline

Header Menus

Dropdown menus accessible from the header — including options to mute, request a human, and adjust widget layout. The layout menu is only present in the floating chat. Menu button parts carry scene suffixes (e.g., header-menu-close-button-chat) so you can style them differently on the landing screen vs. during a conversation.
PartElement
header-menuMenu buttons container (scene-suffixed)
header-menu-more-buttonMore options icon button (scene-suffixed)
header-menu-close-buttonMinimize or close button (scene-suffixed)
header-menu-open-chat-buttonOpen chat button, embedded mode (scene-suffixed)
header-menu-layout-buttonLayout menu trigger (scene-suffixed)
more-options-menuMore options menu content
more-options-menu-muteMute or unmute item
more-options-menu-speak-to-humanSpeak to human item
layout-menuLayout menu content
layout-menu-sizeSize radio group
layout-menu-size-defaultDefault size radio
layout-menu-size-expandedExpanded size radio
layout-menu-alignAlignment radio group
layout-menu-align-leftLeft align radio
layout-menu-align-centerCenter align radio
layout-menu-align-rightRight align radio
layout-menu-activatorActivator style group
layout-menu-activator-text-barText bar activator radio
layout-menu-activator-buttonButton activator radio

Expert Intro

An introductory card shown before the conversation starts. Appears on the landing scene in both compact (embedded) and hero (floating) variants, depending on the activator type setting.
PartElement
expert-introIntro container (compact and hero variants)
expert-intro-avatarExpert avatar
expert-intro-nameExpert name heading
expert-intro-taglineExpert tagline

Paused Scene

Shown when the visitor has an active conversation on another device or tab. Displays the matched expert’s avatar, a status message, suggested prompts, and a button to resume the conversation here.
PartElement
introIntro container (scene-suffixed)
intro-avatarExpert avatar (scene-suffixed)
intro-messagePause status message (scene-suffixed)
actionsActions container (scene-suffixed)
move-conversation-buttonResume conversation button (scene-suffixed)

Expert Profile Card

A summary card for the matched expert, displayed after a conversation starts. Includes a photo gallery and a button to open the full profile drawer.
PartElement
expert-profile-cardCard root
expert-profile-card-titleExpert name
expert-profile-card-captionBio or caption
expert-profile-card-buttonView Profile button
expert-profile-card-galleryGallery container
expert-profile-card-gallery-itemIndividual gallery item wrapper
expert-profile-card-gallery-imageGallery image

Expert Profile Drawer

A slide-over panel with the expert’s full profile, including bio and credentials. Opens when the visitor clicks “View Profile” on the expert profile card.
PartElement
expert-profile-drawerDrawer content
expert-profile-drawer-back-buttonBack or close button
expert-profile-drawer-nameExpert name heading
expert-profile-drawer-bioBio markdown container

Welcome Card

A greeting area shown when the chat first opens, before the visitor sends a message. Displays one or more welcome messages from the brand or expert.
PartElement
welcome-cardWelcome area container
welcome-card-messageWelcome message row
welcome-card-message-avatarWelcome message avatar
welcome-card-message-textWelcome message text

Messages

The conversation thread. Expert messages are grouped with an avatar; user messages appear on the opposite side. Each message bubble wraps markdown content.
PartElement
expert-message-groupExpert message group (with avatar)
user-message-groupUser message group container
user-message-bubbleIndividual user message bubble
message-contentMessage text or markdown wrapper
message-linkLink inside markdown
system-messageSystem message root
system-message-contentSystem message text

Typing and Input

The text input area at the bottom of the chat, plus indicators shown while the expert or AI is composing a response.
PartElement
typing-indicatorTyping indicator container
expert-connecting-indicatorExpert connecting state
chat-inputInput form
chat-input-rootInput root container
chat-input-fieldText input textarea
chat-input-send-buttonSend button
chat-input-file-input-containerFile attachment area

Prompts

Suggested questions shown on the landing screen, during a paused conversation, or as conversation starters. Visitors click a prompt to send it as their first message. Individual prompt buttons carry scene suffixes (e.g., prompt-button-landing) so you can style prompts differently by context.
PartElement
prompt-buttonIndividual prompt button (scene-suffixed)
prompt-button-icon-containerIcon wrapper
prompt-button-iconPrompt icon
prompt-button-textPrompt label text
prompt-button-hover-symbolHover accent symbol
scene-promptsPrompts container (scene-suffixed)
conversation-starters-promptsConversation starter prompts container

Product Recommendations

Product cards shown inline when an expert or AI recommends items. Each card links to the product page and displays a thumbnail carousel, name, and price.
PartElement
product-recommendationProduct card root
product-recommendation-thumbnailImage carousel container
product-recommendation-imageProduct thumbnail image
product-recommendation-detailsName and price container
product-recommendation-nameProduct name link
product-recommendation-priceProduct price

Content Previews

Rich previews for URLs shared in the conversation. Open Graph previews display an image, title, and optional price. YouTube links render an embedded video player.
PartElement
content-previewShared root for OG and YouTube previews
content-preview-media-containerMedia wrapper
og-previewOG preview root
og-preview-imageOG image
og-preview-titleOG title
og-preview-priceOG price
youtube-previewYouTube preview root
youtube-preview-videoYouTube iframe
youtube-preview-titleYouTube title

Assistant Indicator

A small tag shown alongside messages to indicate whether the response came from an AI assistant or a human expert.
PartElement
assistant-indicatorAI or Human tag root
assistant-indicator-labelTag label text
The bar at the bottom of the chat, containing terms of service text and Remark branding.
PartElement
chat-footerFooter container
inline-termsTerms of service text
powered-byPowered by container
powered-by-remark-textPowered by text
powered-by-remark-logoRemark logo

Data Collection

Forms and prompts for collecting visitor information (email, name, phone) and feedback (NPS surveys). These appear at specific points during the conversation flow.
PartElement
terms-of-serviceTerms of service consent container
terms-of-service-consent-buttonTOS consent button
terms-of-service-textTOS text content
pii-request-formPII collection form
pii-request-message-bubblePII request message
nps-summary-message-bubbleNPS summary message
nps-request-formNPS feedback form

Skeleton and Loading

Placeholder elements shown while the widget loads. Skeleton elements use a -skeleton suffix (e.g., chat-header-avatar-skeleton) and also carry the skeleton token, so you can target a specific placeholder or style all loading states at once.
PartElement
skeletonApplied alongside -skeleton parts during loading states
chat-header-skeletonHeader skeleton container
chat-header-avatar-skeletonAvatar placeholder
chat-header-expert-name-skeletonExpert name placeholder
chat-header-tagline-skeletonTagline placeholder
loading-dotsAnimated loading dots

Targeting Parts in Your CSS

Use ::part() on the host custom element. Replace the element name with whichever widget you are styling — remark-chat-widget for the floating chat or remark-qa-activator for the embedded chat (inline activator):
/* Floating chat: add a bottom border to the header during a conversation */
remark-chat-widget::part(header-content-chat) {
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--remark-colors-border-subtle);
}

/* Embedded chat: hide the profile card gallery */
remark-qa-activator::part(expert-profile-card-gallery) {
  display: none;
}
A common use case for the embedded chat is adding spacing above or below the widget to separate it from surrounding page content:
/* Add vertical spacing around the embedded chat */
remark-qa-activator {
  margin-block: 2rem;
}
You can use nested media queries to apply different styles at different viewport sizes:
remark-qa-activator {
  @media (min-width: 50rem) {
    --hem: 18px;
  }
}
In this example, the embedded chat uses the default base font size (16 px) on smaller screens and bumps it up on larger viewports.
Some parts are only present in specific UI states. For example, more-options-menu and layout-menu are only rendered while those dropdowns are open, and skeleton parts are only present while the widget is loading.

Full Example

This example shows custom CSS that adjusts sizing tokens and styles individual parts. Colors and font family would typically be set through the dashboard rather than in CSS.
/* Override sizing tokens on both widgets */
remark-chat-widget,
remark-qa-activator {
  --hem: 18px;
  --remark-spacing-multiplier: 1.25;
  --remark-radii-base: 0.75rem;
}

/* Style individual parts (floating chat) */
remark-chat-widget::part(header-content-chat) {
  padding: 1rem 1.25rem;
}

remark-chat-widget::part(chat-header-tagline) {
  color: var(--remark-colors-content-muted);
}

/* Style individual parts (embedded chat) */
remark-qa-activator::part(product-recommendation) {
  border: 1px solid var(--remark-colors-border-subtle);
}

Best Practices

  • Use widget settings first. The dashboard handles colors, typography, spacing, and border radius with built-in dark mode support. Reach for custom CSS only when you need to style a specific element differently.
  • Reference token variables in ::part() rules. When writing custom CSS, use the --remark-colors-* tokens rather than hardcoded color values so your overrides adapt to light and dark mode.
  • Style semantic parts, not layout wrappers. Prefer parts like header-content or product-recommendation over incidental containers.
  • Use scene suffixes for targeted styling. Parts like widget-header, header-menu-close-button, and prompt-button match all scenes. Append a scene name (e.g., widget-header-landing, header-menu-close-button-chat) to scope styles to a specific context.
  • Account for stateful parts. Menu, loading, and prompt parts may only render in specific states. Test your overrides in those states.
  • Check responsive layouts. Header menus, product cards, activators, and input affordances can shift across screen sizes.