Follow this coding tutorial to learn about the new Stream Chat theming API and understand how to customize your Stream chat web app with CSS.
Customizing Your Chat Application
Creating a chat UI that seamlessly integrates with the rest of your application's design can elevate your user experience. An extensive theming system that allows you to inject your brand’s appearance into the chat UI and lets you do small UI tweaks can significantly speed up this process.
New Theming API
We’ve rebuilt our theming API focusing on customization. That meant creating a well-designed CSS variable system that lets you customize the chat UI without writing custom CSS code, but we also restructured all of the components, so if you have to write custom code, it’s easier.
Apart from the improved customization, the new version also comes with a refreshed design (light and dark themes) and right-to-left layout support.
Chat UI - light theme
Chat UI - dark theme
Chat UI - right-to-left layout
The new API is available from stream-chat-angular version 4 and stream-chat-react version 10.
Setup
To follow along with the coding examples, start with our Angular tutorial or React tutorial but don’t create any custom components.
Coding
In this tutorial, we will start with an out-of-the-box chat UI that comes standard with our React and Angular SDK. We will then customize it by writing only CSS code. Note that the tutorial will use SCSS, but you can follow along using CSS as well.
This is what we start with:
Channel list and message list components - before
Message component - before
And this is the end result:
Channel list and message list component - after
Message component - after
Global Variables
Every app and brand has certain styles and colors that help customers easily identify and associate the product with the company. These styles usually include colors, fonts, shapes, etc., and would be rather difficult to hardcode for every single element.
Global variables come in here and allow us to define a single style that can be reused by components throughout the app.
Global variables are CSS variables that can be grouped into the following categories:
- Colors
- Typography
- Spacing and sizing (these variables allow you to change the whitespace inside chat UI)
- Border radiuses
The full list of these variables can be found on the Angular global variables page and React global variables page inside the SDK documentation.
In this part of the tutorial, we’ll use global variables to change the application's color palette and typography.
Colors
Using the color global variables will make creating our custom color palette for the chat UI really straightforward. This tutorial will use the Radix UI color system to find harmonious color combinations. You can use your own colors, but if you’re using Radix UI make sure to install it:
1npm install @radix-ui/colors
or
1yarn add @radix-ui/colors
Import the selected color combination into your stylesheet:
12@import "~@radix-ui/colors/sage.css"; @import "~@radix-ui/colors/mint.css";
Once that’s done, we can override the default theme colors using the .str-chat
selector:
12345678910111213141516171819.str-chat { // Neutral colors for backgrounds, borders, texts --str-chat__background-color: var(--sage1); --str-chat__secondary-background-color: var(--sage2); --str-chat__surface-color: var(--sage5); --str-chat__secondary-surface-color: var(--sage4); --str-chat__tertiary-surface-color: var(--sage3); --str-chat__text-color: var(--sage12); --str-chat__text-low-emphasis-color: var(--sage11); --str-chat__disabled-color: var(--sage8); --str-chat__on-primary-color: var(--sage12); // Vibrant colors to emphasize UI elements --str-chat__primary-color: var(--mint7); --str-chat__primary-color-low-emphasis: var(--mint5); --str-chat__active-primary-color: var(--mint10); --str-chat__primary-surface-color: var(--mint4); --str-chat__primary-surface-color-low-emphasis: var(--mint2); }
The documentation contains a description for each variable and lists the components that use it, so it’s easier to find the variables we want to override.
For example, the --str-chat__primary-color
variable sets the color of the avatar component and links inside messages (among others). You can see that these components have been updated. It’s also possible to set the colors of these components separately, as we’ll see in the component variables section later.
Let’s see the result:
Color scheme - before
Color scheme - after
Typography
In this step, we’ll customize the font of the chat UI.
For this example, we’ll use Roboto font. Here is the import for that:
1@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;500&display=swap");
Next, set the --str-chat__font-family
CSS variable to change the font throughout the chat UI:
1--str-chat__font-family: "Roboto", sans-serif;
If you want to customize the typography further, there are CSS variables for all the different typography configurations (font family, size, and weight) used by the chat components.
Component Variables
Global variables are a great way to inject your brand design and customize the overall appearance of the chat UI. However, sometimes, we want to have more fine-grained control over parts of the chat application - that’s when component variables can help.
In this part of the tutorial, we’ll customize the avatar, channel preview, and message input components.
Avatar Customization
Let’s update the shape and colors of the avatar component:
123--str-chat__avatar-border-radius: 20%; --str-chat__avatar-background-color: var(--mint11); --str-chat__avatar-color: var(--sage2);
Avatar - before
Avatar - after
The full list of these variables can be found on the Angular component variables page and React component variables page inside the SDK documentation.
In general, components have the following variables:
- Background color
- Text color
- Border and border radius
- Box shadow
Channel Preview customization
Let’s see another example and customize the borders of the channel preview component:
1--str-chat__channel-preview-border-block-end: 1px solid var(--sage5);
Channel preview - before (left), channel preview - after (right)
Message Input Customization
Next, we’ll customize the message input component:
123456--str-chat__message-textarea-border-block-start: none; --str-chat__message-textarea-border-block-end: none; --str-chat__message-textarea-border-inline-start: none; --str-chat__message-textarea-border-inline-end: none; --str-chat__message-input-border-block-start: 1px solid var(--sage5); --str-chat__message-input-background-color: var(--sage2);
Message input - before
Message input - after
Message Component - A Complex Example
Global and component variables are the easiest way to customize the chat components' typography, colors, borders, and shadows. However, more complex UI changes still require custom CSS code.
In this next section, we’ll customize the message component.
Writing Custom CSS Code - Message Layout
CSS cascade layers can make overriding CSS rules defined by the SDK significantly easier.
Let’s create a layer called defaults
for the rules defined by the SDK.
Import for Angular:
123@layer defaults { @import '~stream-chat-angular/src/assets/styles/v2/scss/index.scss'; }
Import for React (paste this import inside your root stylesheet, and remove any other stream-chat-react CSS import you might have):
123@layer defaults { @import '~stream-chat-react/dist/scss/v2/index.scss'; }
We can add another layer, overrides
, for our custom CSS code:
123@layer overrides { // Custom CSS code }
Since the overrides
layer was defined later, it’ll automatically have a higher priority and overrides the rules inside the defaults
layer regardless of selector specificity.
Now that we set up cascade layers, let’s list the changes necessary to implement the desired design:
Message component - currently
Message component - desired design
- Message is full-width
- The message bubble is removed
- The sender avatar is displayed at the top of the message
- Message reactions moved to the bottom of the message text
- GIFs and links have a border
- Message reactions have different colors
Additionally, messages sent by the current user have these changes:
- The message is aligned to the left
- The sender avatar is displayed
At first, we’ll create the layout changes related to all messages:
12345678910111213141516171819202122232425262728293031323334353637@layer overrides { // Custom message layout .str-chat__message { // Display the avatar at the top of the message .str-chat__message-sender-avatar { align-self: flex-start; } .str-chat__message-inner { // Display reactions under the message grid-template-areas: "message-bubble options" "reactions reactions"; // Make message bubble full width .str-chat__message-bubble { max-width: 100%; align-self: center; min-height: var(--str-chat__message-options-button-size); display: flex; align-items: center; // Padding added for the border displayed for links and GIFs // Quoted message padding for indentation .str-chat__message-attachment--card, .str-chat__quoted-message-preview { padding-inline-start: 0.5rem; } } } .str-chat__message-text, .str-chat__quoted-message-bubble { padding: 0; } } }
Next, we’ll move on to the changes related to the messages sent by the current user:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950@layer overrides { .str-chat__message.str-chat__message--me { // Align message to left grid-template-areas: "avatar message" ". replies" ". metadata"; justify-items: start; grid-template-columns: auto 1fr; column-gap: 0.5rem; // Flip message options .str-chat__message-options { flex-direction: row-reverse; } // Don't hide the chat user's avatar .str-chat__message-sender-avatar { display: block; } // Align reactions selector to left .str-chat__message-reactions-container { justify-content: flex-start; } // Align message reactions to left .str-chat__message-reaction-selector { inset-inline-end: unset; inset-inline-start: 0; } // Align system messages center &.str-chat__message--system { grid-template-columns: 1fr; } } // Flip margins .str-chat__li:hover { .str-chat__message--me .str-chat__message-inner { margin-inline-end: 0; } } .str-chat__message--me .str-chat__message-inner { margin-inline-start: 0; margin-inline-end: calc(var(--str-chat__message-options-button-size) * 3); } }
Component variables
Not all changes require custom code. Let’s adjust the theming of the message.
Remove the message bubble:
123456.str-chat { --str-chat__message-bubble-background-color: transparent; --str-chat__own-message-bubble-background-color: transparent; --str-chat__quoted-message-bubble-background-color: transparent; --str-chat__deleted-message-background-color: transparent; }
Add the border to links and GIFs:
1--str-chat__card-attachment-border-inline-start: 3px solid var(--sage4);
Message reactions color:
12--str-chat__message-reaction-background-color: var(--sage4); --str-chat__own-message-reaction-background-color: var(--mint5);
With these changes, we’ve completed the customization of the chat UI:
Message component - end result
Chat UI - end result
Interactive Playground
You can easily experiment with the new theming capabilities with our interactive examples. Below is the React example, and you can find the Angular version here.
Where To Go From Here?
If you want to know more about the new theming API, check out these cool features as well:
- How to use and customize the dark and light themes for Angular and React.
- How to create your own themes with the Angular and React SDKs.
- For advanced customization, it’s possible to only use the layout rules from the SDK and apply your own look-and-feel. You can read more about this topic in our Angular and React advanced customization guides.
If you have an existing chat project, you can follow the Angular theme installation guide or React theme installation guide for more information.
If you’re interested in Stream chat, you can activate your free 30-day trial or check out our maker account.