---
title: "Widget customisation - Chat Thing Documentation"
canonical_url: "https://chatthing.ai/docs/widget-customisation"
last_updated: "2026-07-20T15:03:01.140Z"
meta:
  description: "Customise the chat widget's appearance to fit in with your website's design."
  "og:description": "Customise the chat widget's appearance to fit in with your website's design."
  "og:title": "Widget customisation"
  "twitter:description": "Customise the chat widget's appearance to fit in with your website's design."
  "twitter:title": "Widget customisation"
---

**Bots**

# Widget customisation

Customise how the chat widget looks and behaves on your website.

## Quick presets

Copy these configurations for common styles:

### Minimal light theme

```
window.chatThingConfig = {
  theme: "light",
  colour: {
    widgetColour: "#ffffff",
    primaryColour: "#3b82f6",
  },
};
```

### Branded colour

Replace `#YOUR_COLOUR` with your brand colour:

```
window.chatThingConfig = {
  colour: {
    widgetColour: "#YOUR_COLOUR",
    primaryColour: "#YOUR_COLOUR",
  },
};
```

### Auto-open after delay

Open the chat automatically after 5 seconds:

```
window.chatThingConfig = {
  autoOpenDelay: 5000,
};
```

### Welcome message bubble

Show a message above the widget button:

```
window.chatThingConfig = {
  firstMessage: "👋 Need help? Ask me anything!",
  messagePreviewDelay: 3,
};
```

### Custom widget icon

```
window.chatThingConfig = {
  icon: {
    widgetIcon: "https://your-site.com/chat-icon.png",
  },
};
```

## Available options

| Option | Type | Description |
| --- | --- | --- |
| `theme` | `"dark"` or `"light"` | Chat interface theme |
| `locale` | `"de"`, `"es"`, `"fr"`, etc. | Interface language |
| `autoOpenDelay` | number (ms) | Auto-open after delay |
| `firstMessage` | string | Welcome bubble text |
| `messagePreviewDelay` | number (seconds) | Delay before showing bubble |
| `initialQuestion` | string | Send this question when opened |
| `closeChatButton` | boolean | Show the in-window close (X) button (defaults to `true`) |
| `mobileFullscreen` | boolean | Open full-screen on small viewports (defaults to `true`; ignored when you supply a custom `css.window`) |
| `position` | `"bottom-right"` or `"bottom-left"` | Which corner the widget, window and teaser anchor to (defaults to `"bottom-right"`) |
| `zIndex` | number | Base stacking order for the widget, window and teaser (defaults to a very high value) |
| `pulse` | object | Optional attention pulse outline on the trigger: `{ enabled, color, speed }` (off by default; respects reduced motion) |
| `launcherLabel` | string | Optional text pill shown beside the trigger (e.g. "Chat with us"); style it via `css.launcherLabel` |
| `resize` | boolean | Let users drag-resize the chat window; the size persists across reloads (off by default; ignored on mobile and with a custom `css.window`) |
| `unreadBadge` | object | Optional unread notification badge on the trigger: `{ enabled, color }` (off by default). Reserved for an upcoming human-handover signal — it stays hidden until the chat reports unread messages, so enabling it today has no visible effect yet. |

## Full CSS control

Defining the following global configuration structure before the chat widget script is loaded will allow you to override all of the CSS we add into interface elements within your website. Feel free to take the following CSS rules and adapt them as you see fit.

### CSS overrides

```
<script>
window.chatThingConfig = {
  css: {
    /* css applied to the widget trigger button */
    widget: \`position: fixed;
z-index: 999;
height: 60px;
width: 60px;
border-radius: 100%;
bottom: 20px;
right: 20px;
background: rgb(17 24 39);
color: rgb(255, 255, 255);
box-shadow: 0px 4px 19px rgba(0,0,0,0.2);
border: none;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
overflow: hidden;
padding: 0px;\`,
    /* css applied to the chat window */
    window: \`position: fixed;
z-index: 999;
bottom: 100px;
right: 20px;
width: calc(100vw - 40px);
height: calc(100vh - 120px);
max-width: 400px;
max-height: 600px;
background: white;
border-radius: 8px;
background: rgb(17 24 39);
box-shadow: 0px 4px 19px rgba(0,0,0,0.2);
border: 1px solid rgba(255,255,255,0.1);
display: none;
overflow: hidden;\`,
    /* css applied to the iframe within the chat window */
    iframe: \`height: 100%;
width: 100%;
border: 0;\`,
    /* css applied to the message preview container, this positions the preview message if configured */
    messagePreviewContainer: \`position: fixed;
z-index: 999;
bottom: 100px;
right: 20px;
transform: translateX(350px);
max-width: 300px;
display: flex;
flex-direction: column;
align-items: end;
gap: 10px;
margin-left: 20px;
transition: transform 0.2s ease-in-out;\`,
    /* css applied to the message preview popover */
    messagePreviewBox: \`border-radius: 8px;
background: #1f2937;
color: #d1d5dc;
box-shadow: 0px 4px 19px rgba(0,0,0,0.2);
padding: 15px;
display: flex;
gap: 15px;
cursor: pointer;\`,
    /* css applied to the text in the message preview popover */
    messagePreviewText: \`margin: 2.5px 0;
font-family: Outfit, sans-serif;\`,
    /* css applied to the message preview close button */
    messagePreviewCloseButton: \`background: #b0acac;
padding: 0;
margin: 0;
border: unset;
line-height: 0;
border-radius: 100%;
padding: 3px;
cursor: pointer;
opacity: 0;
visibility: hidden;
transition: visibility 0.1s linear, opacity 0.1s linear;\`,
    /* css applied to the message preview close button icon */
    messagePreviewCloseIcon: \`width: 15px;
aspect-ratio: 1;
color: white;\`,
    /* css applied message preview assistant icon wrapper */
    messagePreviewIconWrapper: \`background: rgb(17 24 39);
border-radius: 100%;
overflow: hidden;
height: 25px;
aspect-ratio: 1;\`,
    /* css applied to the message preview icon image */
    messagePreviewIconImg: \`color: white;
padding: 5px;\`,
    /* css applied to the widget assistant icon image */
    customAssistantIcon: \`width:60px;
height:60px;\`,
    /* css applied to the widget assistant icon image */
    bubbleCustomAssistantIcon: \`width:25px;
height:25px;\`,
  },
  svg: {
    /* svg icon for the widget button */
    widget: \`<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" style="height: 40px; color: white;"><path stroke-linecap="round" stroke-linejoin="round" d="M8.625 12a.375.375 0 11-.75 0 .375.375 0 01.75 0zm0 0H8.25m4.125 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zm0 0H12m4.125 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zm0 0h-.375M21 12c0 4.556-4.03 8.25-9 8.25a9.764 9.764 0 01-2.555-.337A5.972 5.972 0 015.41 20.97a5.969 5.969 0 01-.474-.065 4.48 4.48 0 00.978-2.025c.09-.457-.133-.901-.467-1.226C3.93 16.178 3 14.189 3 12c0-4.556 4.03-8.25 9-8.25s9 3.694 9 8.25z" /></svg>\`,
    close: \`<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" style="height: 30px; color: white;"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"></path></svg>\`
  },
  icon: {
    /* path to a remote image for the widget button, takes precedence over the svg.widget property */
    widgetIcon: "https://cdn.example.com/widget-icon.png",
  }
};
</script>
```

## Other settings

In addition to overriding the default configuration shown above, you can also configure other settings via our **window.chatThingConfig** global.

```
export type TLocale = "de" | "es" | "fr" | "it" | "jp" | "cn" | "el";

export interface IChatThingConfig {
  /** locale for the chat interface, we currently support English, Spanish, French, German, Japanese, Chinese & Greek */
  locale?: TLocale;
  /** an alternative to setting the **id** attribute on the chat widget script tag */
  botId?: string;
  /** an initial question which will be sent to your bot when the chat widget is opened */
  initialQuestion?: string;
  /** will cause the chat window to automatically show after N ms (1000ms = 1second) */
  autoOpenDelay?: number;
  /** css overrides for all the interface elements we add to your site, see above for our defaults */
  css?: {
    widget?: string;
    window?: string;
    iframe?: string;
    messagePreviewContainer?: string;
    messagePreviewBox?: string;
    messagePreviewText?: string;
    messagePreviewCloseButton?: string;
    messagePreviewCloseIcon?: string;
    messagePreviewIconWrapper?: string;
    messagePreviewIconImg?: string;
    customAssistantIcon?: string;
    bubbleCustomAssistantIcon?: string;
  };
  /** override our default icons, these should be provided as inline svg content */
  svg?: {
    widget?: string;
    close?: string;
  };
  /** css colour values for interface elements, your css overrides will take precedence over these */
  colour?: {
    primaryColour?: string;
    widgetColour?: string;
    widgetColourInverted?: string;
  };
  /** provide a path to an asset for the widget button, this takes precedence over the svg icon */
  icon?: {
    widgetIcon?: string;
  };
  /** the message shown in a chat bubble above the widget button */
  firstMessage?: string;
  /** the time in seconds to wait before showing the first message in a chat bubble */
  messagePreviewDelay?: number;
  /** theme applied to the chat interface, this isn't always relevant if you choose override our default css */
  theme?: "dark" | "light";
  url?: string;
  /** show the close (X) button inside the chat window header, set to false to hide it (defaults to true) */
  closeChatButton?: boolean;
  /** open the chat window full-screen on small viewports (defaults to true; ignored when a custom css.window is supplied) */
  mobileFullscreen?: boolean;
  /** which corner the widget, window and teaser anchor to (defaults to "bottom-right") */
  position?: "bottom-right" | "bottom-left";
  /** base stacking order for the widget, window and teaser (defaults to a very high value) */
  zIndex?: number;
  /** optional attention pulse outline on the trigger while the chat is closed */
  pulse?: {
    /** turn the pulse on (defaults to off) */
    enabled?: boolean;
    /** the outline colour (defaults to the primary colour) */
    color?: string;
    /** one pulse cycle duration in seconds (defaults to 2) */
    speed?: number;
  };
  /** optional text pill shown beside the trigger; style it via css.launcherLabel */
  launcherLabel?: string;
  /** let users drag-resize the chat window; size persists across reloads (off by default) */
  resize?: boolean;
  /** optional unread notification badge on the trigger (off by default). Reserved
   * for an upcoming human-handover signal — stays hidden until the chat reports
   * unread messages, so it has no visible effect yet. */
  unreadBadge?: {
    /** turn the badge on (defaults to off) */
    enabled?: boolean;
    /** the badge background colour (defaults to a notification red) */
    color?: string;
  };
}
```