App Suite UI (latest)
All versions
Imprint
All versions
Imprint
  • Feature Catalog
    • General
      • Getting around
      • Search and notifications
      • Settings and appearance
      • Signing in
      • Account and security
      • Onboarding and devices
      • Working with content
      • Sharing and delegation
      • Storage, plans and feedback
      • Progressive Web App
      • Feedback
      • Upsell
      • Triggers
    • Mail
      • Reading and organizing
      • Attachments
      • Writing and sending
      • Security and trust
      • Accounts and automation
      • Signatures and templates
      • Working with the other apps
      • BIMI
    • Calendar
      • Seeing your day
      • Appointments
      • People and invitations
      • Calendars and subscriptions
      • Rooms and resources
      • Video meetings
      • Search, print and transfer
    • Address Book
      • Contacts
      • Address books
      • Finding people
      • Lists and the other apps
    • Tasks
      • Tasks
      • Task lists and delegation
      • Working with the other apps
    • Drive
      • Working with files
      • Finding and arranging
      • Sharing
      • Storages and capacity
      • Working with the other apps
      • OpenCloud Drive Integration
    • Portal
    • Enterprise and Provider Edition
    • Compliance

      • Accessibility
      • Accessibility Conformance Report
      • Data protection
  • Upgrade Guide
    • Everything new since 7.10.6
    • From 7.10.6 to 8.35
    • From 8.35 to 8.47
    • From 8.47 to 8.55
    • Breaking changes and requirements
  • Deployment Guide

    • Configuration
    • Settings list
    • Login page
    • What's New dialog
    • Mail assets
    • Mail rendering and security
    • All messages folder
    • Unseen messages folder
    • Theming
    • Authentication
    • Browser support
  • Customize & Extend
    • Manifests
    • Toolbars and menus
    • Portal widget
    • Sign In
    • Internationalization
  • Architecture
    • Core UI service

Theming / Dynamic Theming

The dynamic theme plugin allows to have custom colors and logo without creating a real theme for each possible color combination. The only available information which can be used to select a theme is the domain name, i.e. the brand.

Installation

The theme generator consists of the single package open-xchange-dynamic-theme, which is installed on the OX middleware.

Enabling the Plugin

The plugin is enabled or disabled by the capability dynamic-theme, e.g. in a file /opt/open-xchange/etc/dynamic-theme.properties set

com.openexchange.capability.dynamic-theme=true

When using the plugin, the actual theme should be the built-in default theme. To prevent all users from changing it and hide the theme selector in the preferences, set the property io.ox/core//theme to read-only. To do this, change the file /opt/open-xchange/etc/meta/appsuite.yaml as follows:

io.ox/core//theme:
    protected: true

If some users won't use dynamic themes, this approach won't work. Instead, the theme selector can be disabled an enabled by controlling the list of available themes. The theme selector is hidden if the list is empty. To be able to do that with the config, the entire list of themes needs to be specified as a single JSON value, e.g. by changing the file /opt/open-xchange/etc/settings/appsuite.properties as follows:

io.ox/core/settingOptions//themes={"default":"Default Theme"}

Then, to hide the theme selector for users with a dynamic theme, use the config to change the value to {}.

Specifying a Theme

The package installs the file /opt/open-xchange/etc/settings/open-xchange-dynamic-theme.properties, which contains the global defaults for the custom theme settings. Any of the settings contained in that file can be changed per-context or at any other granularity supported by the config. The individual settings are as follows:

VariableDefaultDark/LightDescription
mainColor#283f73darkThe main highlight color. Setting only this variable might already be enough.
linkColorsame as mainColordarkText color for links and border-less buttons.
toolbarColorsame as mainColordarkText color for links and border-less buttons in toolbars.
logoURL/lightURL of the logo in the top left corner of the top bar.
logoURL/darksame as logoURL/lightURL of the logo in the top left corner of the top bar when dark mode is enabled.
logoWidth60Width of the logo as number of pixels or any CSS length unit. Set to auto to use the native width of the image. For best display on high-resolution screens, it is recommended to use a bigger image and specify a smaller size here.
logoHeightautoOptional height of the logo as number of pixels or any CSS length unit. The maximum value is 64. Leave as auto to scale according to the specified width while preserving the aspect ratio. For best display on high-resolution screens, it is recommended to use a bigger image and specify either auto or a smaller size here.
topbarColor#fffdarkText color for icons in the top bar.
topbarBackgroundsame as mainColordarkBackground color of the top bar.
topbarHoverrgba(0, 0, 0, 0.3)darkBackground of an item in the top bar when it has the keyboard focus, the mouse hovers it, or it is active.
topbarSelected#ffflightBackground color of selected item in mobile menu
listSelected#dddlightBackground of selected items in the list view when the list view does not have the keyboard focus.
listHover#f7f7f7lightBackground of a not selected item in the list view when the mouse hovers over it.
listSelectedFocussame as mainColordarkBackground color of selected items in the list view when the list view has the keyboard focus.
folderBackground#f5f5f5lightBackground color of left the side panel.
folderSelectedrgba(0, 0, 0, 0.1)lightBackground of a selected item in the side panel when the side panel does not have the keyboard focus.
folderHoverrgba(0, 0, 0, 0.05)lightBackground color of a not selected item in the side panel when the mouse hovers over it.
folderSelectedFocussame as mainColordarkBackground color of a selected item in the side panel when the side panel has the keyboard focus.
mailDetailCSSempty string ''Custom CSS string, which changes the styling of the mail iframe. Example: 'body { background: green !important } h1 { color: red}'

In the configuration file, each variable name must be preceded by 'io.ox/dynamic-theme//'. When referring to the value of other variables on the right side of the equals sign, (like in the default value of linkColor) the variable names must be preceded by '@io-ox-dynamic-theme-'. headerLogo and logoURL can be relative (to /appsuite/), or absolute. When using absolute URLs to point to different hosts, use the form //hostname/path to keep the protocol (HTTP or HTTPS) and avoid any unnecessary security warnings.

The colors can be any CSS color, as long as the restriction of the "Dark/Light" column are respected. Colors marked "dark" specify dark backgrounds with white text/icons. If the specified color is too light, accessibility will suffer. Similarly for colors labeled "light".

Advanced Theme Configuration

The theming system now supports advanced configuration options through theme overrides. These can be configured per theme using the setting path io.ox/core/theming/themes/{themeName}/override:

Brand Theme Renaming

Set a custom title for themes using the title property:

io.ox/core/theming/themes/white/override:
  title: "ACME Corporation"
  themeColor: "#0066cc"
  variables:
    primary-color: "#0066cc"
    accent-color: "#0066cc"

Dark Appearance

Variables under variables apply to both appearances. Because the shared dark palette is layered on top of a theme, a value set there is replaced when the user goes dark — that is what makes a light theme's background stop being white at night. Variables that should apply to the dark rendering go under variables.dark, which is applied last and wins:

io.ox/core/theming/themes/white/override:
  variables:
    background: "#fdfdfd"
    dark:
      background: "#0d0d0d"
      text: "#e0e0e0"

The same dark key works under the io.ox/core/theming/themes/{themeName}/variables setting.

Two further properties set the desktop behind the app in dark, alongside background and themeColor for light:

PropertyDescription
darkBackgroundDesktop background (color, gradient or image) in dark appearance.
darkThemeColorBrowser theme color (address bar tint) in dark appearance.

Note that dynamic theming (the io.ox/dynamic-theme plugin) does not apply in dark appearance: its colors are light-mode choices, and the dark rendering falls back to the stock palette. Use variables.dark above to brand the dark side.

Font Configuration

For loading custom fonts, use the customFonts array with full @font-face CSS blocks:

io.ox/core/theming/themes/white/override:
  customFonts:
    - '@font-face {
         font-family: "CustomFont";
         src: url("/themes/fonts/custom-regular.woff2") format("woff2");
         font-weight: 400;
         font-style: normal;
         font-display: swap;
       }'
    - '@font-face {
         font-family: "CustomFont";
         src: url("/themes/fonts/custom-bold.woff2") format("woff2");
         font-weight: 700;
         font-style: normal;
         font-display: swap;
       }'
  variables:
    font-family: "CustomFont, sans-serif"
    font-family-base: "CustomFont, sans-serif"

The customFonts array accepts complete @font-face CSS declarations as strings, allowing for full control over fonts.

Core Theming Settings

Appearance (light / dark / auto)

Light and dark are a setting of their own, independent of the theme. Every theme is rendered in both, so a user keeps their background when they switch. There is no separate "Dark" theme any more.

io.ox/core//theming/appearance=auto

Or using YAML configuration:

io.ox/core:
  theming/appearance: "auto"

Available values:

  • "light" (default) — always the light rendering
  • "dark" — always the dark rendering
  • "auto" — follows the operating system's light/dark preference

Forcing one appearance. Mark the setting as protected in meta/appsuite.yaml, and users get your value with no control to change it:

io.ox/core//theming/appearance:
  protected: true

Turning the choice off entirely. Users then stay on whatever theming/appearance says:

io.ox/core//theming/appearanceEnabled=false

Note this is a separate switch from theming/picker/enabled: which backgrounds you offer and whether your users may go dark are different policies, so locking the theme catalogue no longer takes dark mode with it. To hide the control in the settings UI while leaving the setting itself in place, add APPEARANCE to disabledSettingsSections.

Compatibility. Before this release dark was a theme, so theming/blocklist: ["dark"] was how a deployment kept dark mode away. That still works and still disables the appearance control. Set theming/appearanceEnabled explicitly to override it either way.

A branded Dark theme keeps working. Configuration written against the retired theme -- io.ox/core/theming/themes/dark/variables, and the variables inside its override -- is still read, and applied to White in dark appearance. That is where the migration puts anyone who had the Dark theme, so a branded deployment sees what it saw before. It is deliberately not applied to the other themes: this configuration is often a whole corporate identity, and over a photograph or Solarized's palette it would collide rather than brand.

On White it wins over the shared dark palette and over what the theme says about itself in dark, and loses to theming/themes/white/variables's own dark key, which is the more specific instruction. Nothing needs to change on upgrade, but that per-theme variables.dark is the spelling to move to -- and the one to use for branding the dark side of any other theme.

Migration from theming/defaultDarkMode

theming/defaultDarkMode is deprecated and superseded by theming/appearance. It is still honored: a user with no stored theme in a defaultDarkMode: "dark" deployment is migrated to appearance: "dark" once, as is a user who had selected the Dark theme. The migration never overwrites an appearance that is already set, so adopting theming/appearance takes effect immediately and you can then drop the old key.

On mobile the theme setting is unchanged and still offers Light theme / Dark theme / Use system setting. theming/appearance applies to the desktop UI only.

Favicons

Favicons can usually be customized in one of the following ways:

  • Override existing icons in /themes/default/**
  • Use custom plugin code to replace or add icons
  • Provide a custom index.html that references custom icons — not recommended, because index.html may change over time
  • Use configuration — the simplest approach

To customize the favicon or Apple touch icon, add the relevant settings to as-config.yaml in App Suite Middleware. These settings can also be defined per hostname.

Configuration options

  • icons.favicon: Defines a custom SVG favicon (rel="icon"). If this option is not set and SVG favicons are enabled, ./favicon.svg is used.
  • icons.faviconIco: Defines a custom ICO favicon (rel="icon"). This option is only used if disableSVGFavicon is set to true.
  • icons.appleTouchIcon: Defines a custom Apple touch icon (rel="apple-touch-icon").
  • disableSVGFavicon: If set to true, SVG favicons are disabled and ICO favicon handling is used instead. The default is false.

Icon paths can be specified in different forms, for example as a relative path such as ./example.svg, as an absolute path such as /example.svg, or as a full URL such as https://example.org/example.svg.

To use an ICO favicon, set icons.faviconIco and enable disableSVGFavicon: true.

Example configuration

my-customer:
  host: portal.example.org
  icons:
    favicon: https://example.org/favicon.svg
    appleTouchIcon: https://example.org/apple-touch-icon.png
  disableSVGFavicon: false

Example using an ICO favicon

my-customer:
  host: portal.example.com
  icons:
    faviconIco: /themes/custom/favicon.ico
    appleTouchIcon: /themes/custom/apple-touch-icon.png
  disableSVGFavicon: true
Last Updated: 10/7/26, 2:41 PM
Prev
Unseen messages folder
Next
Authentication