Skip to content

CSS displacement API variable fallback broken for anonymous users #762

@jjroelofs

Description

@jjroelofs

Summary

The Drupal displacement API sets --drupal-displace-offset-top to an empty string "" for anonymous users, not undefined. This breaks CSS var() fallbacks in calc() expressions, causing fixed headers to overlap content.

Steps to reproduce

  1. Enable "Fixed Header on Mobile" in theme settings
  2. Log out (view as anonymous user)
  3. Visit any page on mobile viewport
  4. Observe the fixed header overlaps page content

Example Project

Reproducible on any DXPR Theme installation with fixed header enabled.

What is the current bug behavior?

For anonymous users, body padding is 0px instead of the header height. The CSS rule matches but produces invalid CSS:

calc(40px + "") → invalid → ignored → 0px

What is the expected correct behavior?

Body should have padding-top equal to the header height (e.g., 40px) to prevent fixed header from overlapping content.

Relevant logs and/or screenshots

DevTools evidence:

User Type --drupal-displace-offset-top Body Padding
Anonymous "" (empty string) 0px ❌
Admin "83px" 40px ✓

Screenshots: https://github.com/dxpr/dxpr_theme/tree/pr-760-review-screenshots/pr-760-screenshots

Possible fixes

All calc() usages with displacement API variables:

File Line Code Selector Context Status
scss/components/dxpr-theme-header--mobile.scss 290 calc(var(--dxt-setting-header-mobile-height) + var(--drupal-displace-offset-top, 0)) &:has(#navbar.header-mobile-fixed) ❌ BROKEN
scss/components/dxpr-theme-header--top.scss 53 calc(var(--drupal-displace-offset-top, 0) + 30px) &.dxpr-theme-header--overlay ❌ BROKEN
features/sooper-header/header-theme-settings-css.inc 70 calc($header_top_height_var + var(--drupal-displace-offset-top, 0px)) .body--dxpr-theme-nav-desktop.body--dxpr-theme-header-fixed ❌ BROKEN
scss/components/dxpr-theme-header--mobile.scss 280 calc(var(--drupal-displace-offset-top, 0) - 1px) &.gin--vertical-toolbar, &.gin--horizontal-toolbar, etc. ✓ Safe
scss/components/dxpr-theme-header--mobile.scss 285 calc(var(--drupal-displace-offset-top, 0) - 6px) &.gin--navigation ✓ Safe
scss/components/dxpr-theme-header--top.scss 329 calc(var(--drupal-displace-offset-top, 0) - 1px) .gin--vertical-toolbar ✓ Safe
scss/components/dxpr-theme-header--top.scss 346 calc(var(--drupal-displace-offset-top, 0) - 1px) .gin--classic-toolbar, .gin--core-navigation, etc. ✓ Safe
scss/components/dxpr-theme-header--top.scss 354 calc(var(--drupal-displace-offset-top, 0) - 6px) .gin--navigation ✓ Safe
scss/base/layout.scss 55 calc(100vw - var(--drupal-displace-offset-left, 0)) body.toolbar-tray-open ✓ Safe
scss/dxpr-theme.admin.themesettings.scss 34 calc(var(--dxt-setting-header-top-height, 100px) + var(--drupal-displace-offset-top, 0px)) html:has(#system-theme-settings) ✓ Safe (admin)
scss/dxpr-theme.admin.themesettings.scss 100 calc(var(--drupal-displace-offset-right, 0) - var(--dxt-admin-sidebar-width)) #system-theme-settings ✓ Safe (admin)
scss/dxpr-theme.admin.themesettings.scss 153 calc(var(--drupal-displace-offset-right, 0) - var(--dxt-admin-sidebar-width)) #system-theme-settings ✓ Safe (admin)
scss/dxpr-theme.admin.themesettings.scss 218 calc(var(--drupal-displace-offset-right, 0) - var(--dxt-admin-sidebar-width)) #system-theme-settings ✓ Safe (admin)
scss/dxpr-theme.admin.themesettings.scss 919 calc(var(--drupal-displace-offset-top, 0px) + 80px) #system-theme-settings ✓ Safe (admin)

JS fallback exists but doesn't work:

js/dist/header/dxpr-theme-header.js:90-94 attempts to set --drupal-displace-offset-top: 0px but:

  • Only runs inside resize event handler, not on initial page load
  • Only runs when #dxpr-theme-main-menu .nav exists

Recommended fix pattern:

// Instead of calc() with displacement variable for all users:
// Split into toolbar vs non-toolbar contexts

// Anonymous/regular users - no toolbar
&:has(#navbar.header-mobile-fixed):not(.toolbar-horizontal, .toolbar-vertical, .toolbar-fixed) {
  padding-top: var(--dxt-setting-header-mobile-height) !important;
}

// Admin users with toolbar - displacement API returns valid value
&:has(#navbar.header-mobile-fixed):is(.toolbar-horizontal, .toolbar-vertical, .toolbar-fixed) {
  padding-top: calc(var(--dxt-setting-header-mobile-height) + var(--drupal-displace-offset-top)) !important;
}

Related: PR #760, PR #678, Issue #759, Issue #677

Metadata

Metadata

Assignees

Labels

8.xbugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions