Skip to main content

Header

How does the header is created? What options exist?

 

# Header Background System Documentation

## Overview

The header background system allows dynamic, field-driven header backgrounds on Drupal pages with support for images (media) or gradients, customizable heights, overlays, text positioning, animations, and a parallax scrolling effect.

---

## Drupal Field Configuration

The system reads configuration from the following Drupal node fields:

### Required Fields

| Field Name | Type | Description |
|------------|------|-------------|
| `field_header_activation` | List (text) | Controls whether header is active and what type. Values: `none`, `media`, `gradient` |

### Optional Fields

| Field Name | Type | Description |
|------------|------|-------------|
| `field_header_media` | Media reference | The background image (when activation = `media`) |
| `field_header_gradient` | List (text) | Gradient name from predefined list (when activation = `gradient`) |
| `field_header_text` | Text (formatted) | The headline text to display. Supports token replacement. |
| `field_header_height` | List (text) | Height option: `slim`, `standard`, `statement`, `full` |
| `field_header_overlay` | List (text) | Overlay type: `none`, `black_transparent`, `black_transparent_center`, `white_transparent`, `white_transparent_center` |

---

## Height Options

Heights are defined as: **menu height + visible content area**

| Option | Desktop Visible Area | Mobile Visible Area | Use Case |
|--------|---------------------|---------------------|----------|
| `slim` | 120-200px (14.6dvh) | 100-180px (18dvh) | Minimal headers, breadcrumb-style |
| `standard` | 180-320px (23.6dvh) | 150-280px (28dvh) | Default, balanced appearance |
| `statement` | 300-520px (38.2dvh) | 250-450px (42dvh) | Prominent, impactful headers |
| `full` | 100dvh (full viewport) | 100dvh | Hero-style, full-screen |

**CSS File:** `/css/components/header-heights.css`

---

## Overlay Options

| Value | Effect |
|-------|--------|
| `none` | No overlay |
| `black_transparent` | Uniform 40% black overlay |
| `black_transparent_center` | Radial gradient - darker in center, fading to edges |
| `white_transparent` | Uniform 40% white overlay |
| `white_transparent_center` | Radial gradient - lighter in center, fading to edges |

**CSS File:** `/css/components/header-overlays.css`

---

## Available Gradients

Predefined gradients in `/css/gradients.css` and mapped in `upmarkit_theme.theme`:

- `amethyst-erde`, `aprikose-preussen`, `aprikose-smaragd`
- `flieder-preussen`, `flieder-rubin`
- `heide-rubin`, `heide-smaragd`
- `himmel-erde`, `himmel-himmel-erde`, `himmel-kornblume`, `himmel-rubin`
- `licht-amethyst`, `licht-rubin`, `licht-zinnober`
- `meer-rubin`, `meer-smaragd`, `meer-zinnober`
- `smaragd-aquamarin`, `smaragd-erde`

---

## Parallax Effect

### How It Works

The parallax effect makes the header text scroll slower than the background, creating depth.

**Implementation:** JavaScript-based (`/js/header-parallax.js`)

**Why JavaScript instead of CSS:**
- CSS `position: sticky` is blocked by `clip-path` and `overflow: hidden` on media/image backgrounds
- JavaScript provides consistent behavior for both gradients and media
- Allows smooth, configurable easing effects

### Technical Details

| Setting | Value | Description |
|---------|-------|-------------|
| Parallax Strength | 0.35 | Text moves at 35% of scroll speed |
| Transition | 0.5s | Duration of smooth movement |
| Easing | cubic-bezier(0.22, 0.61, 0.36, 1) | Smooth, lazy deceleration |

### Behavior

1. **Initial State:** Text is vertically centered in the visible area (below menu) via CSS flexbox
2. **On Scroll Down:** Text moves down slower than the page scrolls (parallax effect)
3. **On Scroll Up:** Text smoothly returns to centered position with lazy easing
4. **Boundaries:** Text stays within the header container (overflow: hidden)

---

## Animation Sequence

On page load, header elements animate in sequence:

| Element | Animation | Duration | Delay |
|---------|-----------|----------|-------|
| Background layer | Fade down | 0.35s | 0s |
| Image/Gradient | Fade in | 0.35s | 0.05s |
| Overlay | Fade in | 0.3s | 0.1s |
| Text content | Fade up | 0.5s | 0.15s |

**Defined in:** Inline `<style>` block in `page.html.twig`

---

## File Structure

```
/app/
├── css/
│   ├── components/
│   │   ├── header-heights.css    # Height options + content centering
│   │   └── header-overlays.css   # Overlay styles
│   ├── gradients.css             # Gradient class definitions
│   └── style.css                 # Base styles (compiled Tailwind)
├── js/
│   └── header-parallax.js        # Parallax effect
├── templates/
│   └── page.html.twig            # Header rendering template
├── config/
│   └── header-backgrounds.yml    # Legacy fallback config (deprecated)
├── upmarkit_theme.libraries.yml  # Asset definitions
└── upmarkit_theme.theme          # PHP preprocessing (field → template)
```

---

## PHP Processing Flow

**File:** `upmarkit_theme.theme`

### Function: `upmarkit_theme_preprocess_page()`

1. Checks if current page is a node
2. Reads `field_header_activation` value
3. If `none` or empty → no header background
4. If `media` → reads `field_header_media`, extracts image URL
5. If `gradient` → reads `field_header_gradient`, maps to CSS value
6. Reads other fields (height, overlay, text)
7. Builds `$header_background` array
8. Passes to template as `header_background` variable

### Fallback Behavior

If no node fields are set, the system falls back to `/config/header-backgrounds.yml` for path-based configuration (legacy, to be removed).

---

## Template Structure

**File:** `page.html.twig`

```twig
<section class="header-background [height-class] [has-parallax]">
 
 <!-- Background Layer -->
 <div class="header-bg-layer">
   <!-- Image OR Gradient -->
   <div class="header-bg-image/gradient">...</div>
   
   <!-- Overlay (if set) -->
   <div class="header-bg-overlay [overlay-type]">...</div>
 </div>
 
 <!-- Content Layer -->
 <div class="header-bg-content">
   <div class="site-container">
     <div class="header-bg-headline">
       {{ headline text }}
     </div>
   </div>
 </div>
 
</section>
```

---

## CSS Class Reference

### On `.header-background` section:
- `header-height-slim/standard/statement/full` - Height option
- `has-parallax` - Added for media backgrounds (enables clip-path)

### On `.header-bg-content`:
- Flex container for centering
- `padding-top: var(--header-h)` - Pushes content below sticky menu

### On `.header-bg-headline`:
- Contains the actual text
- Parallax transform applied here via JS

### On `.header-bg-overlay`:
- `header-bg-overlay-black-transparent`
- `header-bg-overlay-black-transparent-center`
- `header-bg-overlay-white-transparent`
- `header-bg-overlay-white-transparent-center`

---

## Key CSS Variables

| Variable | Default | Description |
|----------|---------|-------------|
| `--header-h` | 100px | Menu/header bar height |
| `--header-h-scrolled` | 64px | Menu height when scrolled |

---

## Troubleshooting

### Parallax not working on media/images
- Check that `clip-path` is not being overridden
- Verify JS file is loading (check browser console for errors)

### Text not centered
- Ensure `header-heights.css` is loaded after `style.css` (check library weights)
- Verify `.header-bg-content` has flex centering rules

### Animations not playing
- Check for `prefers-reduced-motion` media query (removed for this implementation)
- Verify inline styles in `page.html.twig` are present

### Gradient not showing
- Check gradient name matches exactly (case-sensitive, use hyphens)
- Verify `_upmarkit_theme_get_gradient_css()` function has the gradient mapped

---

## Future Improvements (Backlog)

1. **Extract inline animations** to separate CSS file for maintainability
2. **Remove legacy YAML fallback** once field-based system is confirmed stable
3. **Add parallax strength field** to allow per-page customization
4. **Add more animation options** (slide-up, zoom, etc.)