Styling web components

All of the main components in the UIKit (chat, comments, files, messenger, posts) have a default look and feel that should fit in most normal layouts, but if needed you can override and adjust their outer styling using plain CSS.

  wy-messenger {
    flex: 1;

  .my-custom-styles {
    margin: 1rem;

  style="border: 1px solid red;"

Elements that are nested inside the main components can be styled via CSS variables that you add to your stylesheet.

CSS variables

As mentioned above, you can adjust the color and appearance of the UIKit components using CSS custom properties (also known as CSS variables). The simplest way to define them is within a :root { } selector in your stylesheet but you may also define them directly on a component (or on any parent element).

:root {
  /* base theme color */
  --wy-theme-color: red;

wy-messenger {
  /* override inherited font */
  --wy-font-family: monospace;

The font is normally inherited from the container where Weavy is placed, but as seen above, you can easily customize it by specifying a value for the --wy-font-family property.

Color theme

The easiest way to quickly change the entire color theme is with the --wy-theme-color property. When specified, it automatically generates a complete color palette that applies to the specified components.

:root {
  --wy-theme-color: red;
wy-messenger {
  --wy-theme-color: #00ff00;
<wy-messenger style="--wy-theme-color: hsl(95deg, 38%, 62%);"></wy-messenger>

Another alternative is to add a <meta name="theme-color"> element to the <head of your page. When present, it is picked up by Weavy and used to generate a theme (meaning you don't have to set the --wy-theme-color property as it is done automatically).

  <meta name="theme-color" content="#00ff00" />

If you want more precise control of the color theme you can define all color tones in the palette instead of setting the single --wy-theme-color property. The colors shades are named from 0 to 100, similar (but not equal) to lightness of the HSL color model, where 0 is dark and 100 is light.

We recommend generating colors tones using Material Theme Builder to get matching color tones and proper dark mode out of the box. This will usually meet Web color contrast standards to get minimum contrast ratio of 3:1.


Components can scale the size of both the font and the UI. Both are based on the same measurement and is typically defaulted to 16px by the browser if nothing else is specified.

Scaling the UI

Weavy scales the UI based on rem, which is the font-size in the root (usually the <html> node). The rem is typically set by the browser to 16px. You can set the rem for all components or individual components using the --wy-size property.

:root {
  /* Base UI size (2x) */
  --wy-size: 2rem;

wy-messenger {
  /* Individual UI size (1.5x) */
  --wy-size: 24px;

Scaling the font

The font-size is normally inherited from the container where the component is placed or follows any --wy-size you set. You can also define the font-size for all components or individual components using the --wy-font-size property. There are also additional font variables for fine-tuning the font metrics.

:root {
  /* Base font size */
  --wy-font-size: 2rem;

wy-messenger {
  /* Individual font size */
  --wy-font-size: 1.5rem;

wy-chat {
  /* Regular individual font size. Note: this is overridden by any --wy-font-size */
  font-size: 12px;

Read about sizing using ems and rems on MDN

Paddings and gaps

The spacing can be set for paddings inside the components and gaps between elements. All paddings and gaps are defined from the same base units, but might be bigger or smaller depending on where in the components they are used.

:root {
  --wy-padding: 1rem;
  --wy-gap: 12px;

Borders and rounded corners

The border radius of corners can be set using --wy-border-radius. This affects all rounded corners. Use --wy-border to set the width of borders. To override the roundness of avatars, it's possible to also set --wy-avatar-border-radius.

:root {
  --wy-border-radius: 3px;
  --wy-border: .25rem;

Dark mode

Weavy has built in support for dark mode. The dark theme is based on the color tokens recommended for Material Design dark theme. That means it will follow WCAG recommendations and use your defined colors.

To enable dark mode for a component you just have to set the wy-dark class. You can also apply it to parent node to enable dark theme for multiple components.

Example: Dark mode on a single component

<wy-messenger class="wy-dark"></wy-messenger>

Example: Global dark mode

<html class="wy-dark">

Automatic dark mode

To get dark mode to follow the browser or system settings, you can toggle it using a media query script.

function setWeavyDarkMode(e) {
  if (e.matches) {
  } else {

const colorScheme = matchMedia("(prefers-color-scheme: dark)");

// Listen to dark mode changes
colorScheme.addEventListener("change", setWeavyDarkMode);

// Set initial dark mode

Default values

These are the default values for CSS Variables which can be overridden with any desired custom preferences.

:root {
  /* Theme colors */
  --wy-theme-color:                 unset;

  /* Size */
  --wy-size:                        1rem;
  /* Padding */
  --wy-padding:                     .5rem;
  --wy-padding-sm:                  calc(.5  * var(--wy-padding, .5rem));
  --wy-padding-lg:                  calc(1.5 * var(--wy-padding, .5rem));
  /* Gap */
  --wy-gap:                         .5rem;
  --wy-gap-sm:                      calc(.5  * var(--wy-gap, .5rem));
  --wy-gap-lg:                      calc(1.5 * var(--wy-gap, .5rem));

  /* Border */
  --wy-border:                      1px;
  --wy-border-outline:              0;
  --wy-border-radius:               .5rem;
  --wy-border-radius-sm:            calc(var(--wy-border-radius, .5rem) - .25 * var(--wy-padding, .5rem));
  --wy-border-radius-pill:          var(--wy-border-radius, 2.5rem);
  /* Typography */
  --wy-font-family:                 unset;
  --wy-font-size:                   var(--wy-size, 1em);

  --wy-font-weight:                 unset;
  --wy-font-weight-bold:            bolder;

  --wy-line-height:                 1.5;

  --wy-font-size-xxs:               calc(.625 * var(--wy-font-size, 1em)); // ~ 10px
  --wy-font-size-xs:                calc(.75  * var(--wy-font-size, 1em)); // ~ 12px
  --wy-font-size-sm:                calc(.875 * var(--wy-font-size, 1em)); // ~ 14px
  --wy-font-size-lg:                calc(1.25 * var(--wy-font-size, 1em)); // ~ 20px

  --wy-headings-font-size:          1.25em;
  --wy-headings-font-style:         unset;
  --wy-headings-font-family:        var(--wy-font-family, unset);
  --wy-headings-font-weight:        var(--wy-font-weight-bold, bolder);
  --wy-headings-line-height:        var(--wy-line-height, 1.5);

  /* Links */
  --wy-link-decoration:             none;
  --wy-link-hover-decoration:       unset;

  /* Tables */
  --wy-table-cell-padding-x:        var(--wy-gap-sm, calc(.5  * var(--wy-gap, .5rem)));
  --wy-table-cell-padding-y:        var(--wy-padding-sm, calc(.5  * var(--wy-padding, .5rem)));

  /* Opacity */
  --wy-opacity-backdrop:            95%;
  --wy-opacity-muted:               38%;
  --wy-opacity-disabled:            38%;

  /* State layer */
  --wy-opacity-state-hover:         8%;
  --wy-opacity-state-focus:         12%;
  --wy-opacity-state-active:        12%;
  --wy-opacity-state-drag:          16%;

  /* Surface elevation */
  --wy-surface-1-mix:               5%;
  --wy-surface-2-mix:               8%;
  --wy-surface-3-mix:               11%;
  --wy-surface-4-mix:               12%;
  --wy-surface-5-mix:               14%;

  /* Components */
  --wy-appbar-height:               calc(max(1lh, var(--wy-button-size, 2.5rem)) + 2 * var(--wy-padding, .25rem));
  --wy-footerbar-height:            4rem;

  /* Buttons */
  --wy-button-size:                 calc(var(--wy-button-line-height, 1.5) * 1rem + 2 * var(--wy-button-padding-y, var(--wy-padding, .5rem))); 
  --wy-button-padding-x:            calc(var(--wy-padding, .5rem) + 2 * var(--wy-button-padding-y, var(--wy-padding, .5rem)));
  --wy-button-padding-y:            var(--wy-padding, .5rem);
  --wy-button-gap:                  var(--wy-gap-sm, calc(.5 * var(--wy-gap, .5rem)));
  --wy-button-font-family:          var(--wy-font-family, unset);
  --wy-button-font-size:            var(--wy-font-size, 1em);
  --wy-button-font-weight:          var(--wy-font-weight, unset);
  --wy-button-line-height:          var(--wy-line-height, 1.5);
  --wy-button-border-width:         var(--wy-border-outline, 0);
  --wy-button-border-color:         transparent;
  --wy-button-border-radius:        var(--wy-border-radius, 2.5rem);

  /* Inputs */
  --wy-input-padding-y:             var(--wy-padding, .5rem);
  --wy-input-padding-x:             var(--wy-padding-lg, calc(1.5 * var(--wy-padding, .5rem)));
  --wy-input-font-family:           var(--wy-font-family, inherit);
  --wy-input-font-size:             var(--wy-font-size, 1em);
  --wy-input-font-weight:           var(--wy-font-weight, unset);
  --wy-input-line-height:           var(--wy-line-height, 1.5rem);
  --wy-input-border-width:          var(--wy-border, 1px);
  --wy-input-border-radius:         var(--wy-border-radius, .5rem);
  --wy-input-filled-border-radius:  var(--wy-border-radius-pill, var(--wy-border-radius, 2.5rem));
  --wy-input-filled-border-width:   var(--wy-border-outline, 0);
  /* Dropdowns */
  --wy-dropdown-padding-x:          var(--wy-padding-lg, calc(1.5 * var(--wy-padding, .5rem)));
  --wy-dropdown-padding-y:          var(--wy-padding, .5rem);
  --wy-dropdown-gap:                var(--wy-gap, .5rem);
  --wy-dropdown-border-radius:      var(--wy-border-radius, .5rem);
  --wy-dropdown-border-width:       var(--wy-border, 1px);

  /* Items */
  --wy-item-title-font-size:        var(--wy-font-size, 1em);
  --wy-item-title-font-weight:      var(--wy-font-weight, unset);

  /* Avatars */
  --wy-avatar-font-size:            .382em;
  --wy-avatar-font-weight:          var(--wy-font-weight-bold, unset);
  --wy-avatar-border-radius:        var(--wy-border-radius-pill, var(--wy-border-radius, 50%));

  /* Messages */
  --wy-message-padding:             var(--wy-padding-lg, calc(1.5 * var(--wy-padding, .5rem)));