Styling and Theming
Relevant source files
The following files were used as context for generating this wiki page:
The hdrify application employs a modern, minimalist design aesthetic characterized by a "glass-morphism" interface, smooth animations, and a sophisticated color palette. The entire frontend is built with vanilla HTML, CSS, and JavaScript, eschewing larger frameworks for a lightweight and fast user experience.
The styling is primarily defined in static/style.css and is tightly coupled with the application's state, which is managed by static/script.js. This document outlines the core principles of the design system, component styling, and the dynamic nature of the UI.
Sources: README.md:3-4, static/style.css, static/script.js
Core Principles
The visual identity of hdrify is built on a few key principles: a clean layout, modern typography, a constrained color palette, and subtle effects.
Layout and Structure
The main layout is centered and constrained to a maximum width of 600px by the .container class, ensuring readability on large screens. The structure is defined in static/index.html and consists of a header, a main content area (.main-area), a controls section, and an examples section.
This diagram shows the basic DOM structure of the main page.
Sources: static/style.css:13-16, static/index.html:10-80
Typography
The application uses the SF Pro Display font stack, a common choice for modern interfaces, with fallbacks to standard system fonts. The base font size and line height create a comfortable reading experience.
- Font Family:
'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif - Base Color:
#1f2937(a dark slate gray) - Line Height:
1.6
Sources: static/style.css:8-12, README.md:20
Color Palette
The color scheme is sophisticated and minimal, relying on shades of gray for text, backgrounds, and UI elements. This creates a neutral canvas that allows the processed images to stand out.
| Color | Hex | Usage |
|---|---|---|
| Primary Text | #1f2937 | Headings, hover states |
| Secondary Text | #374151 | Body text, button backgrounds |
| Muted Text | #6b7280 | Descriptions, labels, spinner |
| Disabled | #9ca3af | Disabled button text, dragover border |
| Border/BG | #e5e7eb | Borders, slider track, disabled bg |
| White | #ffffff | Main background, button text |
| Error | #dc2626 | Error message text |
Sources: static/style.css
Component Styling
The UI is composed of several distinct components, each with specific styles for different interaction states.
Upload Area
The .upload area is the initial point of interaction. It's styled as a large, clickable drop zone with a dashed border. Its appearance changes on hover and during a drag-and-drop operation to provide clear visual feedback.
- Default State: A 1px solid border (
#e5e7eb). - Hover State: The border color changes to
#cbd5e1. - Dragover State: The border color darkens to
#9ca3af. This state is controlled by adding the.dragoverclass via JavaScript.
Sources: static/style.css:60-76, static/script.js:63-66
Image Display and Processing
Once an image is selected, the .image-display element appears. It contains the result image and a .processing-overlay. The overlay, which contains an animated .spinner, is shown during backend processing to indicate activity.
The spinner animation is a simple CSS keyframe rotation:
.spinner {
width: 48px;
height: 48px;
border: 4px solid #e5e7eb;
border-top: 4px solid #6b7280;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
Sources: static/style.css:95-121, static/script.js:203-206
Controls
The .controls section contains the HDR slider and action buttons.
- HDR Slider: The
#hdrSlideris a custom-styled range input. The thumb and track are styled for a consistent look across browsers. - Buttons: Buttons share a base
.btnclass..reset-btn: Transparent background with a border..download-btn: Solid background. It has a distinct disabled state (lighter background, no pointer events) when no download is available, controlled by the absence of anhrefattribute.
Sources: static/style.css:123-188, static/index.html:48-57
Glass-morphism Effect
The .examples section features a "glass-morphism" effect, which creates a frosted-glass look over the page background. This is achieved using a semi-transparent background color and the backdrop-filter property.
.examples {
background: rgba(255, 255, 255, 0.7);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 16px;
padding: 2rem;
}
Sources: static/style.css:223-231, README.md:10, 22
Dynamic Styling and State Management
Styling is not static; it changes based on user interaction and application state. The HDRify class in static/script.js manages these state changes by manipulating DOM element styles and classes.
The following diagram illustrates the flow from user interaction to visual change.
This sequence shows how JavaScript orchestrates visual state changes, which are then animated smoothly by CSS.
Sources: static/script.js:70-78, static/script.js:180-196
UI State Transitions
The application transitions between several key visual states, managed primarily by the transitionToImageView() and reset() methods in script.js.
| State | Description | Key CSS / JS Actions |
|---|---|---|
| Initial | The page has loaded, showing the upload area. | .upload is display: flex. .imageDisplay and .controls are display: none. |
| Dragover | User is dragging a file over the upload area. | uploadArea.classList.add('dragover') which triggers .upload.dragover styles. |
| Processing | An image has been uploaded and is being processed. | resultImage is blurred, .processingOverlay is shown. resultImage.style.filter = 'blur(50px)'. |
| Display | The processed image is displayed with controls. | .upload is hidden. resultImage is sharp, .processingOverlay is hidden. .controls are visible. |
| Reset | The user has clicked the reset button. | .imageDisplay and .controls are hidden, .upload is shown. All transitions are animated via CSS opacity. |
Sources: static/script.js, static/style.css
The transition from the upload view to the image view is a carefully orchestrated fade and blur effect.
- The
.uploadAreaopacity is set to0. - After 150ms, its display is set to
none, and.imageDisplayand.controlsare shown. - The
resultImageis initially shown with a strong blur (filter: blur(50px)) and low opacity. - When the processed image is ready, the blur is removed and opacity is set to
1, creating a "blur-to-sharp" transition.
Sources: static/script.js:180-196, static/script.js:235-239
Responsiveness and Accessibility
The design is responsive and includes considerations for accessibility.
Responsive Design
A media query for screens smaller than 640px adjusts the layout for mobile devices. Key changes include:
- Reduced body padding.
- Smaller
h1font size. - The
.controlssection stacks vertically (flex-direction: column). - The
.example-gridswitches to a single-column layout.
Sources: static/style.css:262-306
Accessibility
Accessibility is addressed through several means:
- Semantic HTML: Use of
<header>,<main>,<section>, and<footer>. - ARIA Roles:
role="button"on the uploaddiv,role="status"on the processing overlay, andaria-live="polite"on dynamic value displays. - Keyboard Navigation: The upload area is focusable and can be activated with
EnterorSpace. TheEscapekey can be used to reset the view. - Focus Styles: Custom
outlinestyles are provided for focused buttons and inputs to ensure visibility.
button:focus,
input[type='range']:focus,
a.btn:focus {
outline: 2px solid #6b7280;
outline-offset: 2px;
}
Sources: static/index.html:27, 34, 48, static/script.js:40-45, 119-123, static/style.css:309-314, README.md:14, 24
Conclusion
The styling and theming of hdrify are a core part of its identity as a modern web application. By combining vanilla web technologies with contemporary design patterns like glass-morphism and smooth, state-driven animations, the application provides an intuitive and visually pleasing user experience. The architecture intentionally separates structure (HTML), presentation (CSS), and behavior (JS), while ensuring they work in concert to create dynamic and responsive visual states.