Skip to content

How to create a custom SuiteP sub-theme in SuiteCRM 7

Add your own colour scheme beside Dawn, Day, Dusk and Night: the files a SuiteP sub-theme needs, the variable order that makes it work, and how to register it.

Updated · By Muhammad Ilyas, Techholds

How do you create a SuiteP sub-theme in SuiteCRM 7?

A SuiteP sub-theme in SuiteCRM 7 is a folder at themes/SuiteP/css/<Name>/ with its own style.scss and compiled style.css. Copy Dawn's files, set Bootstrap variables before variables.scss and SuiteP variables after it, compile with Sass, register the name in custom/themes/SuiteP/themedef.php, then run Quick Repair and Rebuild.

Steps at a glance

  1. Copy Dawn. Copy themes/SuiteP/css/Dawn/ to themes/SuiteP/css/<YourName>/, choosing a name that is not Dawn, Day, Dusk, Night, Noon, Fonts or Bootstrap.
  2. Add two override files. Create _brand-pre.scss for Bootstrap variables and _brand-post.scss for SuiteP variables, and import them before and after variables.scss in style.scss.
  3. Set your colours. Put $navbar-bg, $sidebar-bg, $primary-btn-bg, $input-bg and the other SuiteP colour variables in _brand-post.scss.
  4. Compile to style.css. Run npx sass --style=compressed on style.scss to produce style.css in the same folder.
  5. Register the sub-theme. Create or extend custom/themes/SuiteP/themedef.php so it requires the core themedef and adds your name to the sub-theme options.
  6. Quick Repair and Rebuild. Run Admin > Repair > Quick Repair and Rebuild, then choose the sub-theme under Profile > Edit > Layout Options > Style.

What a SuiteP sub-theme is

Since SuiteCRM 7.10, the SuiteP theme ships as colour variants called sub-themes: Dawn, Day, Dusk and Night, with a fifth folder, Noon, present from 7.12. Each user picks one under Profile > Edit > Layout Options > Style. Adding your own puts your brand colours in that same list, without replacing or editing any stock file.

A sub-theme is just a folder of SCSS that compiles to one stylesheet. SuiteCRM serves the compiled style.css (through its cache/themes/SuiteP/css/<Name>/ copy) and never reads the .scss files at runtime, so whatever you change, you must recompile.

File in themes/SuiteP/css/<Name>/What it does
style.scssEntry point. Imports the palette, variables, icons and the shared bootstrap and suitep-base partials
style.cssThe compiled result. The only file SuiteCRM serves
color-palette.scssThe raw palette, $color-1 to $color-86
variables.scssBootstrap and SuiteP variables built from the palette
icons.scssIcon colours
select.icoThe drop-down arrow image (absent from Dawn on 7.10 and 7.11, where SuiteP falls back to its own)

The one rule that makes it work: override order

Most failed SuiteP themes compile cleanly and change nothing. The reason is how variables.scss declares things. Its Bootstrap variables are declared `!default`, which means "use this unless something already set it", so your value has to be set before the file is imported. SuiteP's own semantic variables, such as $navbar-bg, $sidebar-bg, $list-view-header-bg, $active-tab-bg and $primary-btn-bg, are plain assignments, so they overwrite anything set earlier and your value has to come after it.

The clean way to honour both is two small files and two extra imports in Dawn's style.scss:

style.scss
@import "color-palette";
@import "brand-pre";   // Bootstrap variables: BEFORE variables.scss
@import "variables";
@import "brand-post";  // SuiteP variables: AFTER variables.scss
@import "icons";
// ...the rest of Dawn's imports, unchanged
_brand-post.scss (example values)
$navbar-bg: #1f3a5f;
$sidebar-bg: #f4f6f8;
$active-tab-bg: #1f3a5f;
$list-view-header-bg: #e8edf3;
$primary-btn-bg: #1f3a5f;
$input-bg: #ffffff;
$input-select-bg: #ffffff;

Two stock defaults catch almost everyone. Dawn tints form inputs and selects mint ($input-bg and $input-select-bg), so a branded theme that does not override them keeps mint edit views. And SuiteP's primary, danger, success and info buttons all take their label colour from $default-btn-color, not from white, so changing a button background without checking that label can make it unreadable.

Compile the stylesheet

Any Dart Sass works. From the SuiteCRM root:

Compile
npx sass --style=compressed themes/SuiteP/css/<Name>/style.scss themes/SuiteP/css/<Name>/style.css

Expect a few hundred deprecation warnings about slash division: they come from SuiteP's own stock SCSS and are harmless. A compressed SuiteP stylesheet is around 545 KB.

Register it so it appears in the picker

SuiteCRM builds its theme list by scanning themes/ and then custom/themes/ for themedef.php. A custom themedef for SuiteP replaces the core one, so custom/themes/SuiteP/themedef.php must begin by requiring the core definition and then add your sub-theme to config_options.sub_themes.options. Those options are nested one level under a group label, and core only fills them when the LBL_SUBTHEMES language string is set, so code defensively:

custom/themes/SuiteP/themedef.php
<?php
if (!defined('sugarEntry') || !sugarEntry) {
    die('Not A Valid Entry Point');
}
global $app_strings;

// Start from the core definition: a custom themedef replaces it wholesale.
require dirname(__FILE__) . '/../../../themes/SuiteP/themedef.php';

if (!isset($themedef['config_options']['sub_themes']['options'])
    || !is_array($themedef['config_options']['sub_themes']['options'])) {
    $themedef['config_options']['sub_themes']['options'] = array();
}
$opts = &$themedef['config_options']['sub_themes']['options'];
$group = key($opts);
if ($group === null) {
    $group = !empty($app_strings['LBL_SUBTHEMES']) ? $app_strings['LBL_SUBTHEMES'] : 'Sub-themes';
    $opts[$group] = array();
}
$opts[$group]['Acme'] = 'Acme';

If the file already exists (another add-on may have registered a sub-theme), add your lines to it rather than replacing it. Then run Admin > Repair > Quick Repair and Rebuild so the theme registry and compiled-CSS cache are rebuilt.

Make it the default for everyone

Which sub-theme a user sees is decided in this order: their own subtheme preference, then the site default in $sugar_config['theme_settings']['SuiteP']['sub_themes'], then Dawn. There is no admin screen for it: Admin > Themes only chooses the theme, and the SuiteP settings page it links to shows the sidebar option but no sub-theme picker (checked on SuiteCRM 7.15.2). Set the site default in config_override.php:

config_override.php
$sugar_config['theme_settings']['SuiteP']['sub_themes'] = 'Acme';

Users who already chose a sub-theme keep their choice until it is changed for them. Be careful scripting that: on SuiteCRM 7.14 and 7.15, calling setPreference() for a user other than the one logged in can overwrite that user's whole preference row, including timezone, date format and currency.

Names you cannot use

  • Dawn, Day, Dusk, Night and Noon: the stock sub-themes.
  • Fonts and Bootstrap: real folders inside themes/SuiteP/css/. Windows and macOS file systems ignore case, so a sub-theme with either name collides with them.

Packaging it for Module Loader

Copying files by hand works for one server. To install through Admin > Module Loader, three manifest details matter, and each has caught out experienced developers:

  • Set 'type' => 'module', not 'theme'. A theme-type package is copied raw and never runs ModuleInstaller, so no install script runs and nothing is recorded for uninstall.
  • acceptable_sugar_versions is checked against $sugar_version, which is 6.5.25 on every SuiteCRM 7 and 8. Put a 7.x pattern there and the package can never install. Use acceptable_suitecrm_versions (7.12 and later) for the real version check.
  • Do not name your scripts scripts/pre_install.php, post_install.php, pre_uninstall.php or post_uninstall.php unless they define the matching function: the upgrade wizard includes those paths a second time and calls a function of that name.

And tell whoever installs it: Disable does not switch a theme off. SuiteCRM has no disable hook and does not delete copied files on Disable, so users keep seeing the theme. Uninstall is the off switch. The install guide covers the full Module Loader flow.

The shortcut

Brandtint builds exactly this package from a logo, for the precise SuiteCRM 7 version you run: the sub-theme folder with the overrides on the correct side of variables.scss, a themedef merge that leaves other sub-themes alone, install and uninstall scripts that restore every user's previous choice, and every text and background pair checked for contrast. Preview it free; pay only to download.

Questions

Where are SuiteCRM 7 sub-theme files stored?

In themes/SuiteP/css/<Name>/, alongside the stock Dawn, Day, Dusk and Night folders. The registration that makes it appear in the picker goes in custom/themes/SuiteP/themedef.php.

Why do my SuiteP variable changes have no effect?

Usually because they are on the wrong side of variables.scss. Bootstrap variables there are !default and must be set before it is imported; SuiteP variables such as $navbar-bg are plain assignments and must be set after it. Also remember SuiteCRM serves only the compiled style.css, so recompile and run Quick Repair and Rebuild after every change.

Does a SuiteP sub-theme work on SuiteCRM 7.10 and 7.11?

Yes. Sub-themes arrived in 7.10. Two differences: Dawn has no select.ico on 7.10 and 7.11, and Module Loader there does not support acceptable_suitecrm_versions, so a version check has to run in a pre-install script instead.

How do I remove a custom sub-theme?

If it was installed as a package, use Uninstall in Module Loader (Disable leaves it active). If you added it by hand, delete its folder and its lines in custom/themes/SuiteP/themedef.php, reset anyone using it, and run Quick Repair and Rebuild.

About the author

Muhammad Ilyas builds Brandtint at Techholds, including the SuiteCRM 7 and SuiteCRM 8 theme packages these guides are written from. Muhammad Ilyas on LinkedIn

Skip the SCSS. Start from your logo.

Brand your theme