How to configure the GLPI login screen with per-entity CSS

Customize the GLPI login screen with the native per-entity CSS, without editing the core or installing a theme plugin. See where the real fields live (enable_custom_css and custom_css_code), how to recolor via GLPI 11 Tabler tokens, why color needs !important and the inheritance trap that makes the login theme vanish if you apply it to the wrong entity.

In this article7 sections

Customizing the GLPI login screen is the most frequent branding request we get in production sustaining - and almost everyone starts wrong, editing the core or installing a theme plugin. The clean path already exists in GLPI: per-entity CSS, a native field that survives upgrades and allows a rollback in seconds. This guide shows where the real fields are (enable_custom_css and custom_css_code), why color does not take without !important, and the entity inheritance trap that makes the login theme disappear even with the CSS saved.

Why per-entity CSS (and not a theme plugin or the core)

Editing core files works for one version and breaks at the next upgrade - the patch is lost and you end up hunting for what changed. A theme plugin works, but it ties the look to the plugin's update cycle and compatibility (in the move to GLPI 11, third-party themes were among the first to break). Per-entity CSS is native, versionable in your own change control and reversible by pasting the previous CSS. For visual identity - colors, logo, login background - it gives more control than any plugin, because you can reach any selector in the interface.

ApproachSurvives upgradeRollbackScope
Editing the core (CSS/SCSS)No (patch is lost)Manual and riskyGlobal
Theme pluginDepends on the pluginUninstall the pluginGlobal
Per-entity CSS (native)YesPaste the previous CSS and savePer entity, with inheritance

Where to configure it in GLPI

Open the entity form at Administration > Entities > [your entity] and find the interface customization section. Two fields matter:

  • Enable CSS customization (enable_custom_css) - a dropdown with inheritance (inherit from the parent, or force enabled/disabled on the current entity).
  • Custom CSS (custom_css_code) - the editor where the CSS is pasted.

The first gotcha lives here: while enable_custom_css is not active, the editor shows blocked with the notice "Custom CSS is disabled" and nothing is applied - you paste the CSS, save, reload and "it does not work". Enable the dropdown first. Save and reload the login page to validate.

Ready-made CSS: recolor the login by brand

The GLPI 11 front-end uses Tabler (on top of Bootstrap 5), so the clean way to recolor is to override the --tblr-* design tokens instead of hunting selector by selector. The example below applies a brand palette (red and gold), handles the background and covers the several body classes the login screen uses between GLPI 10 and 11:

/* Brand login - paste into the entity's custom_css_code.
   GLPI 11 uses Tabler: override the --tblr-* tokens for the primary color. */
:root {
  --brand-500: #b11123;
  --brand-700: #7f0e18;
  --brand-gold: #d4a017;
  --tblr-primary: var(--brand-500);
  --tblr-primary-rgb: 177, 17, 35;
}

/* The login screen changes body class between versions - cover both. */
body.page-login,
body.welcome-anonymous,
body[class*="login"] {
  min-height: 100vh;
  background-color: #140104 !important;
  background-image:
    linear-gradient(145deg, rgba(16,0,0,.74) 2%, rgba(127,14,24,.56) 60%, rgba(212,160,23,.34) 100%),
    url("/front/logos/login-bg.jpg") !important; /* host locally, avoid an external URL */
  background-size: cover !important;
  background-position: center !important;
  background-attachment: fixed !important;
}

/* GLPI colors win by specificity: you need !important. */
body[class*="login"] .btn-primary {
  border: 1px solid var(--brand-gold) !important;
  background: linear-gradient(180deg, var(--brand-500), var(--brand-700)) !important;
  color: #fff !important;
}

/* The login footer is .copyright (not an obvious id/class). */
body[class*="login"] .copyright { color: #fff6da !important; }

/* fixed is heavy on mobile: switch to scroll on the phone. */
@media (max-width: 767.98px) {
  body[class*="login"] { background-attachment: scroll !important; }
}

The inheritance trap: why the login has no theme

Here is the detail that only shows when you operate: the login screen runs before any authentication, so there is no active entity at that moment. GLPI resolves the pre-login look from the root entity (id 0). If you applied the CSS to a child entity - the client's, for instance - the internal dashboard does get the brand, but the login page stays default, because it never "enters" that entity. The practical rule we adopt: login theming goes on the root entity; per-client customization that only needs to appear after login can live on the child entity, inherited downward. Since the field has inheritance, what you put on the root cascades to every child unless one overrides it.

Production checklist

  1. Version the previous CSS before any change (save the field text).
  2. Apply the login theme on the root entity; post-login customization can go on the child entity.
  3. Enable enable_custom_css before pasting - otherwise the editor stays blocked.
  4. Host the background image locally (a Document in GLPI or a file served by the host itself); an external URL breaks via CSP, mixed-content or unavailability.
  5. Test with a technician and a requester profile, on desktop and mobile.
  6. Check the form and button contrast (accessibility); keep the rollback ready.

Field traps

Three things cost us time at clients and became an internal FAQ. First: color without !important does not take - the Tabler stylesheet loads with high specificity, and your override needs to win. Second: a background image by external URL is fragile; in an environment with a strict Content-Security-Policy or no internet egress, the wallpaper simply fails to load and the login goes black - host the file on the server itself. Third: do not confuse per-entity customization with GLPI's global CSS (Setup > General); both exist, and mixing them turns into a precedence headache. Document which layer carries which rule.

Next step

Brand standardization in GLPI is routine in our operation - from login to the internal theme, with controlled rollback. If you want your client's estate to carry the right identity without touching the core, talk to the team.


Reviewed by the NexTool Solutions team.

Frequently Asked Questions

GLPI has a native per-entity CSS field. In Administration > Entities > [entity], enable 'Enable CSS customization' (enable_custom_css) and paste the CSS in the custom_css_code editor. No need to edit the core or install a theme plugin. For the login, apply the CSS on the root entity, because the login screen runs before there is an active entity.

No. Per-entity CSS is native to GLPI 10 and 11. It is more robust than a theme plugin because it survives upgrades, allows a rollback by pasting the previous CSS, and reaches any selector in the interface, without depending on a third-party plugin's update cycle.

Three common causes: enable_custom_css was not turned on (the editor stays blocked with 'Custom CSS is disabled'); the CSS was applied to a child entity, but the login runs with no active entity and uses the root entity; or the color rules lack !important and lose to the Tabler stylesheet. Enable the dropdown, use the root entity and add !important.

Yes. The enable_custom_css and custom_css_code fields exist in GLPI 10 and 11. In GLPI 11 the front-end uses Tabler on top of Bootstrap 5, so the clean way to recolor is to override the --tblr-* tokens (such as --tblr-primary) instead of hunting selectors one by one.

Yes, via background-image in the entity's CSS. But host the image locally (a Document in GLPI or a file on the host itself); an external URL is fragile and can be blocked by Content-Security-Policy, mixed-content or lack of internet egress, leaving the login without a background.

Yes. The enable_custom_css field has inheritance: what you set on the root entity cascades to every child unless one overrides it. That is why the login theme goes on the root (to apply before login) and per-client customization can live on the child entity, applied after authentication.

Need help?