SW Shopware 6 Beginner

DfDarkMode – Dark Mode for Shopware 6.7

Install and configure dark mode: browser detection, header toggle and a preference saved in the customer account.

Updated Module version 1.0.0

Overview

DfDarkMode adds a complete dark mode to the Shopware 6.7 storefront. The plugin sets the data-bs-theme attribute on the page’s root html tag: your CSS variables declared under [data-bs-theme="dark"] activate automatically, without any change to your theme.

  • Automatic detection of the browser’s prefers-color-scheme setting (Auto mode)
  • Header toggle: a button cycling through Auto → Light → Dark
  • Customer preference: visual selector on the account profile page
  • Dual persistence: cookie for guests, customer custom field for logged-in accounts
  • Anti-FOUC: the theme is applied before the page renders — no white flash
  • Login sync: the account preference is restored automatically on sign-in

Requirements

  • Shopware 6.7.0 or higher
  • A theme whose colors are defined via CSS variables under [data-bs-theme="dark"] (Bootstrap 5.3 convention)

The plugin does not ship a dark palette: it only drives the data-bs-theme attribute. Your dark mode CSS must already exist in the theme.

Installation

  1. Copy the DfDarkMode folder into custom/plugins/ of your Shopware installation.
  2. Run the following commands:
bin/console plugin:refresh
bin/console plugin:install --activate DfDarkMode
bin/console theme:compile

Once the theme is compiled, the toggle button appears in the storefront header and the “Appearance” card shows up on the customer account profile page.

In a development environment, use bin/console theme:compile --active-only or the storefront watcher for hot recompilation.

How it works

The three modes

  • Auto (default): follows the browser or operating system setting. If the user switches their OS to dark, the storefront follows in real time.
  • Light: forces light mode regardless of the browser.
  • Dark: forces dark mode regardless of the browser.

Preference priority order

  1. Logged-in customer: the account’s df_dark_mode_preference custom field takes precedence over everything.
  2. Guest: the df-dark-mode cookie (1 year lifetime).
  3. No preference: Auto mode.

Anti-FOUC

An inline script placed in the head tag reads the cookie and applies data-bs-theme before the browser paints the page. Result: no light background flash when loading in dark mode, even on slow connections.

Login sync

When a customer signs in, their saved preference is copied to the cookie. The anti-FOUC script therefore has the right value from the very next page, on all their devices.

Customer-facing usage

Header button

The button shows an icon matching the active mode: monitor (Auto), sun (Light) or moon (Dark). Each click moves to the next mode. The change is applied instantly with a smooth transition and saved in the background.

Account profile page

Under My account → Profile, an “Appearance” card offers three clickable tiles (Auto, Light, Dark). The selection is saved to the customer account and a confirmation message is displayed. Keyboard navigation (Enter / Space) is supported.

Customization

Moving the header button

By default the toggle is injected into the base_header_actions_wishlist block. To place it elsewhere, override the base template in your theme and include the component in the block of your choice:

{% sw_extends '@Storefront/storefront/base.html.twig' %}

{% block base_header_actions_search %}
    {{ parent() }}
    {% sw_include '@Storefront/storefront/component/dark-mode-toggle.html.twig' %}
{% endblock %}

Reacting to theme changes in JavaScript

The plugin dispatches the df-dark-mode-changed event on document at every change:

document.addEventListener('df-dark-mode-changed', (e) => {
    console.log(e.detail.preference);    // 'auto', 'light' or 'dark'
    console.log(e.detail.resolvedTheme); // 'light' or 'dark'
});

Useful for reloading a map, a chart or any third-party component that does not read CSS variables.

Texts and translations

All labels are Shopware snippets (prefix df-dark-mode.) editable in the administration under Settings → Snippets. The plugin ships French, English and German.

Technical reference

Custom field

On installation the plugin creates a df_dark_mode custom field set containing the df_dark_mode_preference field (select: auto / light / dark) attached to the customer entity. It is visible and editable in the administration on the customer detail page.

AJAX route

POST /df-dark-mode/save with the mode parameter (auto / light / dark). Sets the cookie and, if a customer is logged in, updates their custom field. JSON response.

Name: df-dark-mode · Values: auto / light / dark · Lifetime: 365 days · SameSite=Lax. Strictly functional cookie: it contains no personal data and no tracking identifier.

Uninstall

bin/console plugin:deactivate DfDarkMode
bin/console plugin:uninstall DfDarkMode

On uninstall, the custom field set and customer preferences are removed, unless the “keep user data” option is checked.

Troubleshooting

The button does not appear in the header

Make sure the theme was recompiled (bin/console theme:compile) and clear the cache (bin/console cache:clear). If your theme heavily overrides the base_header_actions_wishlist block, move the component include to another block (see Customization).

Dark mode activates but colors do not change

The plugin does set data-bs-theme="dark" (verifiable in the browser inspector) but your CSS does not define variables under this selector. Add your dark variables to the [data-bs-theme="dark"] block of your theme.

White flash on load

Make sure no other plugin overrides the base_head block without calling {{ parent() }}, which would remove the anti-FOUC script.

The preference is not kept across devices

Only logged-in customers benefit from multi-device sync through their account. For guests, the preference is local to the browser (cookie).

Changelog

1.0.0

  • Initial release: browser detection, header toggle, customer account preference, anti-FOUC, login sync, FR/EN/DE snippets.
Was this page helpful?

Still stuck? Contact support