When creating web galleries for art collections, web designers often face a variety of formidable challenges: the collections of artworks exhibit highly variable aspect ratios, often including hundreds, if not thousands, of images, hence rendering manual arrangement impractical. Additionally, achieving responsive design across devices while preserving visual balance introduces an insurmountable layer of complexity.
The Partitioned Container Bands System addresses these challenges by dividing pages into intelligent bands that can be partitioned according to compositional rules. First, the system automatically selects and positions images based on aspect ratio compatibility. A subsequent optimisation phase then further refines partition dimensions in order to minimise distortion, supporting both horizontal and vertical band orientations, which ensures efficient space utilisation regardless of device sizes. The outcome is an automated layout engine that transforms collections of chaotic images into harmonious and responsive galleries.
Play with the Interactive Demo on this link
Traditional grid layouts represent the most straightforward approach to organising image galleries, but their simplicity comes at a significant cost: fixed-size cells force images into predetermined dimensions, resulting in aggressive cropping that can destroy composition, remove critical visual elements, or distort the intended framing of the artist. What should be a showcase becomes a Bed of Procrustes, where artworks are mutilated to fit arbitrary constraints.
The masonry layout, popularised by Pinterest, attempts to address these limitations by allowing variable heights within columnar structures. While this preserves aspect ratios, it introduces new problems: the inherent vertical bias creates a waterfall effect where images flow exclusively downward. This architecture particularly disadvantages landscape-oriented artworksβpanoramic photographs, wide paintings, and horizontal compositions are compressed into narrow columns, diminishing their visual impact and violating their natural proportions.
Furthermore, both approaches fail to create meaningful visual relationships between adjacent images. They treat each artwork as an isolated unit rather than part of a cohesive gallery experience. What is needed is a layout system that respects both the individual integrity of each image and the collective harmony of the galleryβone that can accommodate diverse aspect ratios while maintaining visual flow in multiple directions and creating deliberate compositional relationships between neighbouring artworks.
The Partitioned Container Band system is built on four foundational principles:
Unlike traditional layouts that force arbitrary crops, the system respects natural proportions of each image while applying mathematical soft-clipping to extreme ratios. This approach prevents both excessive pan-and-scanning of ultra-wide panoramas and dominating vertical scrolls from tall images, achieving visual balance without destroying compositional integrity.
The system implements an importance-based allocation strategy. High-priority images (scored β₯10) receive prominent placement in main panels with optimal sizing, while lower-scored images intelligently fill complementary spaces. This creates deliberate focal points and supporting elements, mimicking the thoughtful arrangement of a curated gallery rather than a mechanical grid.
Beyond simple breakpoints, the system employs a virtual column mechanism that fundamentally restructures layouts across devices. A 4-column desktop gallery does not merely compress to mobileβit regenerates with entirely different band arrangements, orientations, and partitioning rules optimised for each screen dimension.
When viewport changes occurβwhether from device rotation, window resizing, or split-screen activationβthe system performs complete layout regeneration rather than naive scaling. Bands are re-evaluated, images are re-selected for optimal fit, and partitioning rules are reapplied, ensuring every state maintains the same level of visual sophistication as the initial render.
The Partitioned Container Band system introduces a fundamentally new approach to gallery layout through four interconnected mechanisms that work in concert to create harmonious, responsive image arrangements.
At its core, the system divides the gallery into discrete horizontal or vertical bandsβthink of them as intelligent rows that can adapt their internal structure. Each band maintains a consistent height (or width when vertical) and can host multiple images through internal partitioning. Unlike rigid grid rows, these bands are living containers that understand their content and can optimise their dimensions accordingly. A single gallery might contain dozens of bands, each potentially following different organisational rules while maintaining overall cohesion.
Within each band, a sophisticated rule system governs how space is divided. Nine primary rules (labelled A through I, plus O for single images) define patterns ranging from simple two-panel splits to complex five-panel arrangements. Rule A might divide a band into main and subsidiary panels, while Rule E1 creates a 2Γ2 grid within the band's sub-panel. The system intelligently selects rules based on available images and their characteristicsβa highly important panoramic photo might trigger Rule O for full-width display, while a collection of portraits could invoke Rule G's L-shaped arrangement. This rule-based approach ensures visual variety while maintaining structural logic.
Rather than forcing images into predetermined slots, the system actively selects images whose aspect ratios best match the spaces created by partitioning. Using tolerance bands (Β±20%, Β±33%, and Β±50% ratio matching), the algorithm searches for optimal image-to-space partnerships. A 16:9 partition seeks landscape images, while a 9:16 space pulls from portrait-oriented content. This bidirectional matchingβspaces finding images and images finding spacesβensures minimal distortion and maximum visual impact. When perfect matches aren't available, the system gracefully degrades to the best available option.
After initial placement, a sophisticated post-processing pipeline refines the layout through several optimisation passes. Underfilled bands are merged or repositioned, empty panels are eliminated with their siblings expanding to compensate, and resize handles between panels are fine-tuned using hill-climbing algorithms to minimise aspect ratio distortion. The system even reorders certain band configurations for better visual flowβmoving single-image bands to create breathing room or combining sparse arrangements into denser, more engaging compositions. This isn't mere cleanup; it's an intelligent refinement process that elevates a mechanical layout into an aesthetically considered gallery.
Together, these four systems create a layout engine that thinks like a curatorβunderstanding not just the technical requirements of responsive design, but the artistic demands of presenting visual content in its best light.
Container Bands form the fundamental building blocks of the layout systemβflexible strips that can orient either horizontally or vertically to contain one or more images. Each band operates as an independent layout unit with three core properties: height, orientation, and a governing partitioning rule.
Every Container Band follows a hierarchical two-panel structure:
The Main Panel serves as the primary focal area, exclusively reserved for high-importance images (epic score β₯ 10). This panel remains unpartitioned, ensuring the featured image receives maximum visual impact without subdivision. In the DOM, it carries the class
The Sub-Panel acts as a flexible companion space designed for filler images. Unlike the main panel, it can be subdivided according to the partitioning rule of the bandβsplit into two, three, or even four sections. When Rule O is applied, the sub-panel merges entirely with the main panel, creating a single, undivided space for showcasing a particularly important image.
Bands intelligently switch between horizontal and vertical orientations based on their position in the column layout. The
Band dimensions are not fixedβthey adapt based on their collective aspect ratios of the content. A band containing a panoramic main image naturally expands its height, while one featuring a tall portrait may compress. This breathing behaviour ensures each band provides appropriate space for its contents while maintaining harmony with neighbouring bands.
While bands maintain a fixed width spanning two columns (or one column when vertical), their height adapts dynamically based on the aspect ratio of the main image. The
The system employs nine distinct partitioning rules that determine how space within each band is divided. Each rule creates a specific geometric pattern optimised for different combinations of image aspect ratios and importance levels.
The simplest yet most impactful rule, Rule O eliminates all partitioning to create a single, uninterrupted space. Reserved for images with exceptional importance scores (β₯80) or extreme landscape orientations (aspect ratio β₯1.5), this rule allows marquee pieces to command full band width. The resulting showcase panel is ideal for panoramic photographs, cinematic stills, or artwork demanding undivided attention.
The foundational partitioning rule splits a band into two equal-priority panels: main (A) and sub (B). This creates a simple side-by-side arrangement where both images receive substantial space. The split ratio dynamically adjusts based on the main image's aspect ratioβa 16:9 main image might claim 60% of the band width, leaving 40% for the sub panel. This rule serves as both a primary layout option and a fallback when complex rules cannot find suitable filler images.
These rules maintain the main panel while dividing the sub-panel into two vertical sections. The vertical split creates a natural hierarchy: one prominent image paired with two supporting images in a tower formation. This arrangement excels when the main image is landscape-oriented and the fillers are portraits or squares.
Divides the sub-panel into a 2Γ2 grid by first creating two columns, then splitting each column horizontally. The resulting four panels (B, C, D, E) can accommodate diverse aspect ratiosβvertical images in each column work particularly well. The resize handles allow fine-tuning: the column ratio (BD:CE) and individual row ratios within each column (B:D and C:E) can be adjusted independently, creating layouts like 60-40 column split with 70-30 row divisions.
The inverse of E1, this rule creates two rows first, then divides each row into two panels. This produces a more horizontally-oriented 2Γ2 grid where landscape images naturally fit. The hierarchy differs from E1βimages flow left-to-right, top-to-bottom rather than in columns. Like E1, three resize handles control the overall row ratio (BC:DE) and column ratios within each row.
Creates an asymmetric four-panel arrangement with panel B occupying the entire top row while C and D share the bottom row. This top-heavy composition works excellently when the main image pairs with one important landscape filler (B) and two smaller square or portrait images below. The resize system allows adjusting both the row height ratio (B:CD) and the bottom row's internal division (C:D).
Inverts F1's structureβpanels B and C share the top row while D commands the entire bottom row. This arrangement suits situations where the main image works best with two smaller companions above and one substantial landscape image below. The three-way resize control maintains flexibility in both row heights and top-row column distribution.
A sophisticated three-panel arrangement where B and D stack vertically in one column while C occupies the full height of the other column. The
The simplest three-panel layout arranges B and C side-by-side in the sub-panel area, creating three images in a clean horizontal row. Unlike other rules, this maintains equal heights across all panels, making it ideal for collections of images with similar aspect ratios. The single resize handle adjusts the B:C ratio, allowing fine-tuning of the relative emphasis between the two filler images.
Each rule includes intelligent fallback logicβif the system cannot find appropriate filler images for a complex rule, it gracefully downgrades to simpler arrangements, ensuring every band receives optimal treatment regardless of available image inventory.
The Partitioned Container Band system employs a sophisticated classification scheme that considers both image importance and geometric properties to orchestrate optimal placements throughout the gallery.
Images designated as βepicβ (importance score β₯ 10) form the structural backbone of the gallery layout. These high-priority images exclusively occupy main panels, ensuring they receive prominent placement and maximum visual impact. The system processes epic images first, treating each as a seed around which an entire band is constructed.
For ultra-epic images (score β₯ 80), the system applies special handling: these marquee pieces preferentially receive Rule O (full-band display) or rules that minimise subdivision (A, I). The algorithm even modifies its rule selection based on epic statusβa score-90 panoramic image might bypass complex rules entirely in favour of an uninterrupted showcase, while a score-50 image could anchor a more intricate five-panel arrangement.
Images scoring below 10 serve as intelligent filler content, but βlesserβ doesn't mean unimportantβthese images provide visual rhythm, context, and breathing room that make the epic images shine. The system maintains these images in a separate pool, drawing from them based on geometric compatibility rather than display order.
When epic images run low, the system promotes lesser images dynamically:
Beyond simple wide/tall classifications, the system employs nuanced aspect ratio analysis for placement decisions:
The classification system includes special logic for problematic scenarios:
The Partitioned Container Band system relies on a JavaScript implementation that translates the conceptual partitioning rules into tangible gallery layouts. This section examines the core classes, algorithms, and data structures that manage the arrangement of images according to the rules described in previous sections.
The implementation balances several competing demands: maintaining clean separation between layout logic and DOM manipulation, providing programmatic control over panel proportions during layout generation, and supporting flexible rule-based partitioning combined with the resize handle system. The following sections detail how these capabilities are implemented through the system's class structure and algorithms.
The
class PartitionedBand {
// Core properties
ord = undefined // Band ordinal (position in gallery)
mainPanel = document.createElement('bandpanel') // Primary image container
subPanel = document.createElement('bandpanel') // Partitionable filler space
#images = [] // Private array of assigned images
picturePanels = [] // All panels that can hold images
panelLetters = [] // Panel identifiers (A, B, C, D, E)
// Resize system
resizeHandles = {} // Handle ID -> handle object mapping
resizeFactors = {} // Handle ID -> split ratio (0.0-1.0)
// Calculated dimensions
mainPanelWidthPerc = 0 // Main panel width as percentage
mainPanelWidth = 0 // Main panel width in pixels
height = 0 // Band height in pixels
subPanelWidthPerc = {} // Letter -> width percentage mapping
subPanelHeightPerc = {} // Letter -> height percentage mapping
rule = '' // Active partitioning rule (A-I, O)
#isThreeCol = false // Three-column layout indicator
}The class constructs a nested DOM hierarchy that mirrors the logical panel structure. At the root, each band contains either one panel (Rule O) or two panels (main + sub). The sub-panel may contain additional intermediate containers that themselves hold leaf panels:
#createLeafPanel(panel) {
let r = document.createElement('bandpanel')
r.className = 'leaf'
r.setAttribute('panel', panel) // Panel letter identifier
return r
}
#createIntermediatePanel() {
let r = document.createElement('bandpanel')
return r // No 'leaf' class - this will contain other panels
}For complex rules like E1, the DOM structure becomes deeply nested. The band contains main and sub panels, the sub panel contains two intermediate column containers, and each column contains two leaf panelsβcreating a precise 2Γ2 grid while maintaining logical groupings.
The constructor's switch statement dynamically builds the appropriate panel structure for each rule. Here's how Rule E1 constructs its 2Γ2 grid:
case 'E1':
// Create four leaf panels
panelB = this.#createLeafPanel('B')
panelC = this.#createLeafPanel('C')
panelD = this.#createLeafPanel('D')
panelE = this.#createLeafPanel('E')
// Create intermediate containers for columns
panelBD = this.#createIntermediatePanel()
panelCE = this.#createIntermediatePanel()
setColRow(panelBD, 1, 2) // 1 column, 2 rows
setColRow(panelCE, 1, 2) // 1 column, 2 rows
// Build the hierarchy
setColRow(this.subPanel, 2, 1) // 2 columns, 1 row
panelBD.appendChild(panelB)
panelBD.appendChild(panelD)
panelCE.appendChild(panelC)
panelCE.appendChild(panelE)
this.subPanel.appendChild(panelBD)
this.subPanel.appendChild(panelCE)
// Register panels for image assignment
this.#addPicturePanel(panelB, 'B')
this.#addPicturePanel(panelD, 'D')
this.#addPicturePanel(panelC, 'C')
this.#addPicturePanel(panelE, 'E')Perhaps the most sophisticated aspect of the class is the resize handle system, which enables fine-tuning of panel proportions after initial calculation:
#createResizeHandle(panelA, panelB) {
const handleId = `${panelA.getAttribute('panel')}-${panelB.getAttribute('panel')}`
this.resizeFactors[handleId] = 0.5 // Initial 50-50 split
return {
setRatio: (ratio) => {
this.resizeFactors[handleId] = coerceIn(ratio, 0.05, 0.95)
this.#updatePanelSizes(panelA, panelB, handleId)
},
getRatio: () => this.resizeFactors[handleId],
adjustRatio: (delta) => {
const currentRatio = this.resizeFactors[handleId]
const newRatio = coerceIn(currentRatio + delta, 0.05, 0.95)
this.resizeFactors[handleId] = newRatio
this.#updatePanelSizes(panelA, panelB, handleId)
return newRatio
}
}
}Each handle maintains a ratio between 0.05 and 0.95, preventing complete panel collapse while allowing significant adjustment. The
if (isHorizontal) {
const cols = parentGrid.style.gridTemplateColumns.split(' ')
cols[indexA] = `${ratio}fr`
cols[indexB] = `${1 - ratio}fr`
parentGrid.style.gridTemplateColumns = cols.join(' ')
}This architecture enables the optimisation phase to programmatically adjust hundreds of panel boundaries, iteratively reducing aspect ratio distortion across the entire gallery.
The system employs sophisticated mathematical transformations to handle the wide spectrum of aspect ratios found in real-world image collections. From extreme panoramas to towering vertical shots, these functions ensure that no single image can dominate or disrupt the gallery's visual balance.
At the core of ratio processing lies
function clipfun(x0) {
const clip_p = 0.444
const clip_p1 = Math.sqrt(1.0 - 2.0 * clip_p)
const clip_lim = 1.0 / (1.0 + clip_p1)
let x = x0 * (1.0 + clip_p1) / 2.0
let t = 0.5 * clip_p1
if (Math.abs(x0) >= clip_lim) return 0.5 * Math.sign(x0)
let y0 = (x < -t) ?
((x*x + x + 0.25) / clip_p - 0.5) :
(x > t) ?
(-(x*x - x + 0.25) / clip_p + 0.5) :
(x * 2.0 * clip_lim)
return y0 // returns -0.5 .. 0.5
}The magic number
For the mathematical structure of the function, please refer to section 7.2.
The
function clippedImageDim(rawRatio) {
let workDim = (rawRatio < 1.0) ? (1/rawRatio) : rawRatio
let clippedDim = clipfun(workDim / 4)
return (rawRatio < 1.0) ? (0.25/clippedDim) : (4*clippedDim)
}This function performs a crucial three-step transformation:
The division by 4 establishes that a 1:1 aspect ratio represents the βnormalβ maximumβanything beyond this gets increasingly compressed. For example:
This preprocessing serves multiple optimisation goals:
This mathematical foundation ensures that whether a gallery contains standard 3:2 photographs or experimental 21:9 artistic pieces, the layout algorithm can accommodate them all while maintaining visual coherence and mathematical stability.
The system's ability to create visually balanced galleries hinges on intelligent band height calculation. Each band must provide enough vertical space for its images while maintaining harmony with neighbouring bandsβtoo tall and it wastes space, too short and images become cramped.
The core height calculation employs a deceptively simple formula that produces sophisticated results:
#heightfun(imgRatio) {
const MAX = 0.5 * (4/3) * INTERNAL_WIDTH
const MIN = 0.5 / (4/3) * INTERNAL_WIDTH
return coerceIn(1 / (2*imgRatio) * INTERNAL_WIDTH, MIN, MAX)
}Breaking down the formula
The factor of 2 ensures that the main panel, which typically occupies 40-60% of the band width, displays its image without distortion. This creates a balanced starting point that the sub-panels can work with.
The MIN and MAX constants establish critical boundaries:
const MAX = 0.5 * (4/3) * INTERNAL_WIDTH // 512 pixels const MIN = 0.5 / (4/3) * INTERNAL_WIDTH // 288 pixels
These constraints, based on the classic 4:3 aspect ratio, serve multiple purposes:
The height calculation creates an inverse relationship with the main image's aspect ratio, producing intuitive results:
For Rule O (single image display), the height calculation abandons the standard formula entirely:
if ('O' == this.rule) {
this.height = Math.round(INTERNAL_WIDTH / mainImageRatio)|0
}This allows showcase images to display at their natural aspect ratio without any height constraints, creating full-width presentations that can span vertically as needed.
When
The beauty of this system lies in its simplicityβa single formula with two constraints produces band heights that feel natural across an enormous range of image types, from ultra-wide cinematics to towering phone screenshots, while maintaining the visual coherence essential for professional gallery presentation.
After establishing the overall height of the band, the system must determine how to divide the internal space between main and sub-panels, then further partition sub-panels according to their rules. This multi-stage sizing process ensures each image receives appropriate space while maintaining the structural integrity of the band.
The
adjustBandPartitioning() {
let mainImageRatio = this.#images[0].ratio
// Calculate band height based on main image
if ('O' == this.rule) {
this.height = Math.round(INTERNAL_WIDTH / mainImageRatio)|0
} else {
this.height = Math.round(this.#heightfun(mainImageRatio))|0
}
// Calculate main panel width
let widthPx = ('O' == this.rule) ? INTERNAL_WIDTH : this.height * mainImageRatio
this.mainPanelWidth = widthPx
// Determine panel percentages based on orientation
if (!this.isVertical()) {
this.mainPanelWidthPerc = widthPx / INTERNAL_WIDTH * 100
// Calculate sub-panel dimensions...
} else {
// Vertical orientation uses width percentages as heights
let heightPx = ('O' == this.rule) ? INTERNAL_WIDTH : INT_WIDTH_VERT / mainImageRatio
this.mainPanelWidthPerc = heightPx / INTERNAL_WIDTH * 100
// Calculate sub-panel dimensions...
}
}This method executes a careful dance: first determining the band's overall dimensions, then calculating how much space the main panel requires, and finally distributing the remaining space among sub-panels.
The percentage distribution follows rule-specific patterns. For horizontal bands:
// Rule A, B: Simple split this.subPanelWidthPerc.B = 1.0 - (widthPx / INTERNAL_WIDTH) this.subPanelWidthPerc.C = this.subPanelWidthPerc.B // Rule E1, E2: Half-width columns this.subPanelWidthPerc.B = (1.0 - (widthPx / INTERNAL_WIDTH)) / 2 this.subPanelWidthPerc.C = this.subPanelWidthPerc.B this.subPanelWidthPerc.D = this.subPanelWidthPerc.B this.subPanelWidthPerc.E = this.subPanelWidthPerc.B // Rule F1: Full width B, half widths C and D this.subPanelWidthPerc.B = 1.0 - (widthPx / INTERNAL_WIDTH) this.subPanelWidthPerc.C = this.subPanelWidthPerc.B / 2 this.subPanelWidthPerc.D = this.subPanelWidthPerc.B / 2
Each rule implements a specific space distribution philosophy:
When
if (this.isVertical()) {
// Width percentages actually control heights
let heightPx = INT_WIDTH_VERT / mainImageRatio
this.mainPanelWidthPerc = heightPx / INTERNAL_WIDTH * 100
// Sub-panel "heights" (stored in width percentages)
this.subPanelHeightPerc.B = 1.0 - (heightPx / INTERNAL_WIDTH)
// Fixed widths for vertical bands
this.subPanelWidthPerc.B = INT_WIDTH_VERT // 384 pixels
}This orientation swap maintains conceptual clarityβthe
For complex rules, the system maintains percentages at multiple levels:
// Rule E1 in horizontal mode // First level: How much of band width goes to sub-panel let subPanelTotalWidth = 1.0 - (widthPx / INTERNAL_WIDTH) // Second level: How sub-panel width divides between columns this.subPanelWidthPerc.B = subPanelTotalWidth / 2 // Left column this.subPanelWidthPerc.D = subPanelTotalWidth / 2 // Left column this.subPanelWidthPerc.C = subPanelTotalWidth / 2 // Right column this.subPanelWidthPerc.E = subPanelTotalWidth / 2 // Right column // Third level: How each column divides vertically (handled by resize system) this.subPanelHeightPerc.B = 0.5 // Top of left column this.subPanelHeightPerc.D = 0.5 // Bottom of left column
The initial calculations from
By separating the initial calculation from later optimisation, the system ensures every band starts with sensible proportions even if optimisation is skipped or fails. This layered approach creates robust layouts that degrade gracefully under adverse conditions while enabling sophisticated improvements when conditions allow.
The rendering algorithm transforms a collection of classified images into a complete gallery layout through a sophisticated multi-pass process. Unlike traditional gallery systems that simply flow images into a grid, this algorithm thinks compositionallyβconsidering each band as a designed unit while maintaining overall gallery coherence. The process balances randomness for visual variety with deterministic rules for structural integrity.
The
function renderGallery(images) {
const gallery = document.getElementById(ELEM_ID)
const shuffled = shuffle([...images])
const important = shuffled.filter(img => (img.epic|0) >= 10)
let lesser = shuffled.filter(img => (img.epic|0) < 10)
while (important.length > 0) {
let vert = mustBeVertical(BAND_COUNT)
let fillers = []
let rule = ''
// Process main images, with endgame scenarios handling
let main
if (lesser.length == 0 && important.length > 1) {
// Ran out of lesser images, putting important images starting from narrowest
important.sort((a, b) => a.ratio - b.ratio)
main = important.shift()
} else {
// Ordinary case: just select one from the important
main = important.pop()
}
// ... rule selection and band creation ...
BAND_COUNT++
}
}The algorithm maintains two dynamic pools throughout execution:
The shuffling ensures visual varietyβthe same image set produces different layouts on each render while maintaining quality standards. When the lesser pool depletes, the algorithm adapts by sorting remaining important images by aspect ratio, processing narrow images first to leave wide images for simpler layouts at the end.
Each iteration follows a structured process:
The algorithm generates rule candidates based on the aspect ratio of the main image:
// For highly epic images (β₯ 80)
let ruleSet
if (isHighlyEpic) {
let checkRatio = (vert) ? (1.0 / main.ratio) : main.ratio
if (checkRatio >= 1.5)
ruleSet = ['O']; // Ultra-wide images get full display
else if (checkRatio >= 1.3)
ruleSet = shuffle(['A', 'I']); // Wide images get simple splits
else if (checkRatio <= 0.75)
ruleSet = shuffle(['F1', 'F2']); // Tall images get L-shapes
else
ruleSet = shuffle(['F1', 'F2', 'I']); // Moderate ratios get options
// Append E1 and E2 at the last, if the main image is squarish
if (9/10 <= main.ratio && main.ratio <= 10/9) {
if (rnd() >= 0.5) { ruleSet.push('E2'); ruleSet.push('E1') }
else { ruleSet.push('E1'); ruleSet.push('E2') }
}
}This importance-based routing ensures marquee pieces receive appropriate presentation:
The E1/E2 rules receive special treatment in the selection order. By appending these complex rules last, the system tries simpler arrangements first, only falling back to 5-panel layouts when simpler rules fail to find suitable images. Square main images specifically trigger E1/E2 consideration because their neutral aspect ratio works well with grid-based subdivisions.
Vertical bands operate under modified rule sets:
if (vert) {
// Exclude rules that don't work vertically
ruleSet = shuffle(['A', 'F1', 'F2', 'G']); // No 'B' or 'I'
}Rules B and I, which create side-by-side arrangements, are excluded from vertical bands where stacked arrangements make more visual sense.
When all rule attempts fail, the algorithm employs a final safety valve:
>if (!ruleFound) {
rule = 'A'
band = makeBandClass(rule)
// Attempt to find any compatible image for panel B
let sub = subs.filter(it => (4/5) <= it.ratio && it.ratio <= (5/4)).randomPick();
if (!sub) sub = subs.filter(it => (3/4) <= it.ratio && it.ratio <= (4/3)).randomPick();
if (!sub) sub = subs.filter(it => (2/3) <= it.ratio && it.ratio <= (3/2)).randomPick();
band.putImages(sub ? [main, sub] : [main])
}This ensures every important image receives some placement, even if it means creating an underfilled band that will be cleaned up during post-processing.
For each rule attempt, the algorithm searches for compatible filler images:
for (let i = 0; i < needed; i++) {
let panelIndex = i + 1;
let panel = band.panelLetters[panelIndex];
// Calculate target aspect ratio for this panel
let panelW = INTERNAL_WIDTH * band.subPanelWidthPerc[panel]
let panelH = band.height * band.subPanelHeightPerc[panel]
let panelRatio = panelW / panelH
// Search for matching images in tolerance bands
let imgBin = (lesser.length > 0) ? lesser : important
let chosen = imgBin.filter(it =>
(4/5) < (it.ratio / panelRatio) && (it.ratio / panelRatio) < (5/4)
).randomPick();
if (!chosen) chosen = imgBin.filter(it =>
(3/4) < (it.ratio / panelRatio) && (it.ratio / panelRatio) < (4/3)
).randomPick();
if (!chosen) chosen = imgBin.filter(it =>
(2/3) < (it.ratio / panelRatio) && (it.ratio / panelRatio) < (3/2)
).randomPick();
if (!chosen) break; // Abort this rule attempt
fillers.push(chosen)
imgBin.removeElem(chosen)
}Searching for filler images that matches aspect ratio of the panel ensures minimal distortion after the images are being placed.
Once a valid rule and image combination is found, layout optimisation is performed before the final HTML element is made:
const allImages = [main, ...fillers] band.putImages(allImages) band.adjustBandPartitioning() // Recalculate with actual images band.adjustForEvenFit() // Optimise panel proportions gallery.appendChild(band.makeHTMLelement())
The algorithm includes a crucial sustainability mechanism:
if (important.length == 0 && lesser.length > 0) {
let img = lesser.randomPop()
important.push(img) // Promote a lesser image to continue
}This ensures the gallery utilises all available images rather than leaving a pool of unused lesser images, maintaining visual density throughout the layout.
The elegance of the main rendering function lies in its adaptabilityβit handles collections ranging from 10 carefully curated images to 1000+ mixed archives, producing coherent layouts that respect both individual image characteristics and collective visual flow.
After initial band construction, the system employs mathematical optimisation to refine panel proportions, minimising the visual distortion that occurs when images don't perfectly match their allocated spaces. This phase transforms adequate layouts into polished compositions through iterative refinement.
The system quantifies layout quality using Root Mean Square (RMS) error, which measures the aggregate distortion across all panels in a band:
calculateRMSError() {
let totalSquaredError = 0
let panelCount = 0
// Calculate error for main panel (A)
const mainPanelWidth = this.mainPanelWidth
const mainPanelHeight = this.height
totalSquaredError += this.#calculatePanelError(0, mainPanelWidth, mainPanelHeight)
panelCount++
// Calculate error for sub panels
for (let i = 1; i < this.picturePanels.length; i++) {
const panelLetter = this.panelLetters[i]
const panelWidth = INTERNAL_WIDTH * this.subPanelWidthPerc[panelLetter]
const panelHeight = this.height * this.subPanelHeightPerc[panelLetter]
totalSquaredError += this.#calculatePanelError(i, panelWidth, panelHeight)
panelCount++
}
return Math.sqrt(totalSquaredError / panelCount)
}The individual panel error calculation squares the difference between image and panel aspect ratios:
#calculatePanelError(panelIndex, panelWidth, panelHeight) {
if (!this.#images[panelIndex]) return 0
const imageRatio = this.#images[panelIndex].ratio
const panelRatio = panelWidth / panelHeight
const error = Math.abs(imageRatio - panelRatio)
return error * error // Squared error for RMS calculation
}Squaring the errors serves two purposes: it penalises large mismatches more severely than small ones, and it ensures all errors contribute positively to the total regardless of whether panels are too wide or too tall.
The
adjustForEvenFit() {
const MAX_ITERATIONS = 50
const STEP_SIZE = 0.02 // 2% adjustment per step
const MIN_IMPROVEMENT = 0.001 // Stop if improvement is less than this
let currentError = this.calculateRMSError()
let bestError = currentError
for (let iteration = 0; iteration < MAX_ITERATIONS; iteration++) {
let improved = false
// Try adjusting each resize handle
for (const handleId in this.resizeHandles) {
const handle = this.resizeHandles[handleId]
const originalRatio = handle.getRatio()
// Try increasing the ratio
handle.setRatio(originalRatio + STEP_SIZE)
let newError = this.calculateRMSError()
if (newError < bestError - MIN_IMPROVEMENT) {
bestError = newError
improved = true
} else {
// Try decreasing the ratio
handle.setRatio(originalRatio - STEP_SIZE)
newError = this.calculateRMSError()
if (newError < bestError - MIN_IMPROVEMENT) {
bestError = newError
improved = true
} else {
// No improvement, revert to original
handle.setRatio(originalRatio)
}
}
}
if (!improved) break;
}
return bestError
}The optimisation follows a systematic exploration pattern:
For complex rules with multiple resize handles, the optimisation navigates a multi-dimensional search space. Rule E1, for instance, has three handles:
// E1 resize handles this.resizeHandles['B-D'] // Vertical split in left column this.resizeHandles['C-E'] // Vertical split in right column this.resizeHandles['BD-CE'] // Horizontal split between columns
The algorithm must balance competing demandsβimproving the B:D ratio might worsen the overall column balance. The hill-climbing approach finds local optima where all panels achieve reasonable aspect ratio matches.
Consider a band with a 16:9 main image and three 1:1 filler images using Rule F1:
The 2% step size prevents drastic changes that might create new problems while allowing meaningful improvements. The
This optimisation phase exemplifies the system's attention to detailβnot content with merely functional layouts, it pursues mathematical perfection within the constraints of each band's structure.
While the main rendering loop creates structurally sound layouts, real-world image collections often produce edge casesβunderfilled bands, awkward endings, or height mismatches. The post-processing phase addresses these imperfections through a series of targeted transformations that elevate a mechanical layout into a refined gallery presentation.
The system applies three primary refinement strategies to improve visual flow and eliminate sparse arrangements:
This function identifies all underfilled Rule A bands throughout the gallery and moves them to the end:
function putUnderfilledAtoLast(gallery, bands) {
let underfilled = Array.from(bands).slice(0, -1).filter(it => {
return (it.getAttribute('rule') === 'A' &&
panelsWithImage.length === 1)
})
underfilled.forEach(it => {
gallery.appendChild(it) // Move to end
})
}This reorganisation clusters sparse bands where they can be subsequently merged or refined, maintaining visual density in the main gallery body.
When consecutive Rule A bands each contain only their main image, this function merges them into a single, properly filled band:
function mergeTwoUnderfilledAs(gallery, bands, imgObjs) {
if (penultIsA && lastIsA &&
lastPanelsWithImage.length === 1 &&
penultPanelsWithImage.length === 1) {
// Copy last band's image to penult's empty panel
penultEmptyPanel.style.backgroundImage = lastPicturePanel.style.backgroundImage
// Recalculate panel proportions based on aspect ratios
let img1Ratio = img1RatioRaw / (img1RatioRaw + img2RatioRaw)
let img2Ratio = img2RatioRaw / (img1RatioRaw + img2RatioRaw)
penultMainPanel.style.width = `${img1Ratio * 100}%`
penultEmptyPanel.style.width = `${img2Ratio * 100}%`
// Remove the now-empty last band
gallery.removeChild(last)
}
}This consolidation reduces vertical scrolling while creating more visually satisfying two-image compositions.
This function addresses a common pattern where a full-width showcase image (Rule O) appears as the final band, potentially creating an abrupt ending:
function swapPenultAwithLastO(gallery, bands) {
if (bands.length >= 2) {
const [last, penult] = [bands[bands.length - 1], bands[bands.length - 2]]
const lastIsO = last.getAttribute('rule') === 'O'
const penultHasOneChild = Array.from(penult.children).filter(child =>
child.style.backgroundImage && child.style.backgroundImage !== ''
).length === 1
if (lastIsO && penultIsNotO && penultHasOneChild) {
last.after(penult) // Move penultimate after last
return true
}
}
return false
}By moving the underfilled penultimate band after the showcase image, the gallery gains visual breathing room before its conclusion, creating a more graceful transition to the page end.
Beyond reorganisation, the system includes functions that fundamentally transform problematic bands:
When the last band is an underfilled Rule A, this function converts it to Rule O for a stronger conclusion:
function turnTrailingAintoO(gallery, bands, imgObjs) {
const last = bands[bands.length - 1]
if (lastRule === 'A' && lastPanelWithImage.length == 1) {
// Convert A-panel to O-panel
last.setAttribute('rule', 'O')
mainLeaf.style.width = '100%'
last.querySelector('.sub.leaf').remove() // Remove empty sub-panel
}
}This transformation ensures the gallery ends with a full-width image rather than a half-empty band.
This aggressive cleanup function eliminates any panels that failed to receive images:
function nukeUnderfilledPanel(gallery, bands, imgObjs) {
let noImgPanels = Array.from(document.getElementsByTagName('bandpanel'))
.filter(it => it.className.endsWith('leaf') &&
it.style.backgroundImage.length < 1)
noImgPanels.forEach(panel => {
let previousSibling = panel.previousSibling || panel.nextSibling
// Expand sibling to fill space
if (previousSibling.style.width != '') previousSibling.style.width = '100%'
if (previousSibling.style.height != '') previousSibling.style.height = '100%'
// For vertical bands, adjust height based on image ratio
if (parentNode.getAttribute('dir') == 'v') {
let imageRatio = imgObjs.filter(it => it.ord == imageOrd)[0].ratio
let panelHeight = coerceIn(
Math.round(INT_WIDTH_VERT / imageRatio)|0,
INT_WIDTH_VERT,
clampMax
)
parentNode.style.height = `${panelHeight}px`
}
panel.remove()
})
}This function handles edge cases where vertical bands can create visual inconsistencies at the end of the gallery, particularly in multi-column layouts:
function clipLastVertPanel(gallery, bands, imgObjs) {
if (bands.length >= 2 && COLUMNS > 1) {
const last = bands[bands.length - 1]
if (last.getAttribute('dir') == 'v') {
// Check if this vertical band starts a new row
if ((last.getAttribute('ord')|0) % COLUMNS > 0) {
// Mid-row vertical band: clip to predecessor's height
const penultHeight = parseInt(penult.style.height)
if (lastHeight > penultHeight) {
last.style.height = `${penultHeight}px`
}
} else {
// Row-starting vertical band: convert to horizontal
let imgRatio = imgObj.ratio
// Transform from vertical to horizontal orientation
last.setAttribute('dir', 'h')
let newWidth = parseFloat(getComputedStyle(last).width)
let newHeight = Math.round(newWidth / imgRatio)|0
last.setAttribute('style', `height: ${newHeight}px`)
last.children[0].style.width = '100%'
}
}
}
}The function implements two distinct strategies based on the vertical band's position:
This dual approach ensures vertical bands integrate smoothly into multi-column layouts regardless of their position, eliminating edge cases that could otherwise create jarring visual breaks at the gallery's conclusion.
When galleries span multiple columns, band heights must coordinate across rows to maintain visual alignment:
For two, four, or six column layouts, the system groups bands into rows and normalises heights:
function adjustBandHeightMultiColumn(imgObjs, columns0) {
if (columns0 % 2 == 0) {
let columns = columns0 / 2
for (let i = 0; i < bands.length; i += columns) {
let sameRowBands = [...Array(columns).keys()]
.map(it => bands[i + it])
.filter(it => it !== undefined)
let bandHeights = sameRowBands.map(it => parseInt(it.style.height))
let bandGeomean = Math.round(geomean(bandHeights))|0
sameRowBands.forEach(it => it.style.height = `${bandGeomean}px`)
}
}
}Using geometric mean rather than arithmetic mean prevents extreme heights from skewing the average while maintaining proportional relationships.
Three, five, and seven column layouts require special treatment due to vertical bands:
// Pattern: h1 h1 v h2 h2 (except v can be anywhere)
for (let i = 0; i < bands.length; i += columns) {
// Process upper horizontal bands
let bandGeomeanHi = Math.round(geomean(bandHeightsHi))|0
sameRowBandsHi.forEach(it => it.style.height = `${bandGeomeanHi}px`)
// Process lower horizontal bands
let bandGeomeanLo = Math.round(geomean(bandHeightsLo))|0
sameRowBandsLo.forEach(it => it.style.height = `${bandGeomeanLo}px`)
// Set vertical band height to span both rows plus gap
if (bands[i + hcols] !== undefined)
bands[i + hcols].style.height = `${bandGeomeanHi + bandGeomeanLo + gap}px`
}The geometric mean preserves proportional relationships better than arithmetic mean. For heights [200, 400, 800]:
This mathematical choice ensures that intentionally varied band heights remain visually distinct while achieving overall alignment.
The post-processing phase exemplifies the system's philosophy: mathematical rigour in service of aesthetic excellence. Each optimisation targets specific visual problems, transforming technically correct layouts into galleries that feel curated rather than generated.
The Partitioned Container Band system achieves true responsive design not through media queries or breakpoints, but through mathematical relationships that dynamically reconstruct the entire gallery based on available space. This approach ensures optimal layouts at any viewport width, from mobile phones to ultra-wide displays.
The system determines column count through a simple yet effective formula that scales with viewport width:
function refreshColumnCount() {
let gallery = document.getElementById(ELEM_ID)
let oldColumnCount = COLUMNS
COLUMNS = Math.round(gallery.clientWidth / 384) // 384 is an half of the INTERNAL_WIDTH
if (oldColumnCount != COLUMNS) {
_pack() // Complete gallery regeneration
}
}The formula
Each band spans two logical columns in even-column layouts or varies in odd-column configurations, ensuring bands maintain reasonable proportions across all screen sizes.
Unlike traditional responsive systems that define specific breakpoints via media query, this approach scales continuously:
// Traditional approach (not used): if (width < 960) columns = 2 else if (width < 1344) columns = 3 else columns = 4 // This system's approach: COLUMNS = Math.round(gallery.clientWidth / 384)
This mathematical relationship eliminates jarring layout shifts at arbitrary pixel values, creating smooth transitions as viewports resize.
The system monitors multiple resize triggers:
function attachResizeEvent() {
window.addEventListener('pageshow', refreshColumnCount)
window.addEventListener('load', refreshColumnCount)
window.addEventListener('resize', refreshColumnCount)
}When column count changes, the entire gallery regenerates rather than attempting to reflow existing elements. This complete reconstruction ensures every band receives optimal treatment for the new column configuration.
Vertical bands add visual variety and spatial efficiency, with their placement randomised per row to create organic, non-repetitive layouts:
function mustBeVertical(x) {
// Handle edge cases
if (x < 0) return false;
if (COLUMNS % 2 === 0) return false;
// Special case for single column
if (COLUMNS === 1) return x >= 0;
let modulo = x % COLUMNS
let row = (x / COLUMNS)|0
let thisRowRnd = VERT_INDICES_BY_ROW[row] // Random 0 to (COLUMNS/2-1)
return modulo == thisRowRnd
}This function implements randomised vertical band placement:
Row 1-2: |V| [H] [H]
|V| [H] [H]
Row 3-4: [H] [H] |V|
[H] [H] |V|
Row 5-6: [H] |V| [H]
[H] |V| [H]The randomisation prevents predictable patterns that would make the gallery feel mechanical. Instead of vertical bands always appearing in the same column, they shift positions row by row, creating a more organic visual rhythm. This randomisation is deterministic per sessionβthe same image set produces the same layout until the page reloads.
function mustBeFlipped(x) {
const base = Math.ceil(COLUMNS / 2)
const maxIncrement = Math.floor(COLUMNS / 2)
for (let increment = 0; increment < maxIncrement; increment++) {
const start = base + increment;
if ((x - start) >= 0 && (x - start) % COLUMNS === 0) {
return true
}
}
return false
}This function adds another layer of variation by flipping internal panel arrangements within certain bands, preventing the vertical bands from creating too strong a visual line down any particular column.
The CSS Grid integration has been simplified to treat all columns uniformly, with band spanning handled at the element level:
function _pack() {
let gallery = document.getElementById(ELEM_ID)
gallery.style.setProperty('grid-template-columns', `repeat(${COLUMNS}, 1fr)`)
}
makeHTMLelement() {
const container = document.createElement('band');
if (mustBeVertical(this.ord)) {
container.setAttribute('dir', 'v')
container.style.gridColumn = 'span 1' // Single column
}
else {
container.setAttribute('dir', 'h')
container.style.gridColumn = 'span 2' // Two columns
}
}Both even and odd column layouts use the same
The spanning logic moves from CSS Grid templates to individual band elements. This approach provides several advantages:
The randomised positioning doesn't affect gap calculationsβvertical bands still account for gaps when spanning rows:
// Vertical band height = top row + bottom row + gap
bands[i + hcols].style.height =
`${bandGeomeanHi + bandGeomeanLo + gap}px`The uniform grid approach with randomised vertical positioning creates galleries that feel both structured and organicβmaintaining clear alignment while avoiding the mechanical repetition that makes generated layouts feel artificial.
The visual success of the Partitioned Container Band system rests on rigorous mathematical principles. From aspect ratio calculations to optimisation algorithms, every aesthetic decision has a quantitative foundation that ensures consistent, pleasing results across diverse image collections.
The system's mathematical core revolves around preserving and optimising aspect ratios throughout the layout process:
The fundamental challenge involves mapping images with arbitrary aspect ratios into panels with different proportions. The system quantifies this mapping error:
error = |imageRatio - panelRatio|
For optimisation purposes, this becomes squared error to penalise large mismatches:
squaredError = (imageRatio - panelRatio)Β²
The RMS error aggregates individual panel mismatches into a single quality metric:
RMS = β(Ξ£(squaredErrors) / panelCount)
This metric serves as the optimisation target, with typical values:
When normalising band heights across rows, the system employs geometric mean rather than arithmetic mean:
geomean(heights) = βΏβ(hβ Γ hβ Γ ... Γ hβ)
For heights [300, 400, 533]:
The geometric mean maintains the visual weight relationships between bands while achieving alignment.
The

clipfun(xβ) = {
0.5 Γ sign(xβ) if |xβ| β₯ clip_lim
(xΒ² + x + 0.25)/clip_p - 0.5 if x < -t
-(xΒ² - x + 0.25)/clip_p + 0.5 if x > t
x Γ 2.0 Γ clip_lim if |x| β€ t
}(Visualisation is available at the following link: https://www.desmos.com/calculator/syqd1byzzl)
Where:
The function maintains CΒΉ continuity (continuous first derivative) at transition points:
The magic number
Testing revealed that 0.444 creates the most visually pleasing compression curveβneither too aggressive (losing distinction between ratios) nor too permissive (allowing dominant images).
The system employs multiple optimisation strategies at different stages:
The
for each iteration (max 50):
for each resize handle:
current_error = calculateRMS()
try_ratio = current + 0.02
if (new_error < current_error - 0.001):
accept change
else:
try_ratio = current - 0.02
if (new_error < current_error - 0.001):
accept change
else:
revert
if no improvements:
terminate earlyThe filler selection process uses a tolerance-band greedy approach:
for each panel:
candidates = images.filter(ratio_match Β± 20%)
if (candidates.empty):
candidates = images.filter(ratio_match Β± 33%)
if (candidates.empty):
candidates = images.filter(ratio_match Β± 50%)
selected = candidates.randomPick()
remove selected from poolOverall system complexity for N images:
In practice, the algorithm performs much better:
The system makes deliberate trade-offs:
These mathematical foundations ensure that aesthetic decisionsβhow wide a panel should be, which image fits where, when to clip extreme ratiosβrest on quantifiable principles rather than arbitrary choices.
The flexibility of the Partitioned Container Band system makes it suitable for diverse real-world applications, from personal portfolios to large-scale commercial deployments. This section explores concrete use cases and implementation strategies.
Professional photographers face unique challenges displaying work that spans multiple genres and formats:
The band system excels here by respecting each image's composition while creating cohesive presentations. High-importance shots receive Rule O treatment, while supporting images create context through multi-panel arrangements.
Online retailers struggle with inconsistent product photography:
The system's importance scoring naturally promotes hero images while ensuring all product angles remain visible. The NSFW filtering mechanism can be repurposed for showing alternate product views or colourways.
Modern social platforms must accommodate diverse content types:
The automatic optimisation ensures even poorly-composed user content displays attractively, while the responsive system handles everything from mobile apps to desktop browsers.
Online galleries and showcase artwork with extreme variety:
The mathematical approach of the band system treats all art equally, preventing any single style from dominating while ensuring each piece displays at its best.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="styles.css">
<script src="common.js"></script>
<script src="band.js"></script>
</head>
<body onload="pack('art-gallery', 'collection_2024')">
<div id="site-navbar"></div>
<gallery id="art-gallery"></gallery>
</body>
</html>// Custom importance scoring for e.g. social media platform
function calculateImportance(image) {
let score = 0
score += image.views * 0.1
score += image.likes * 0.5
score += image.featured ? 50 : 0
score += image.aspectRatio > 2.5 ? 20 : 0 // Boost panoramas
return Math.min(100, score)
}
// Custom rule selection
function selectCustomRules(mainImage, availableImages) {
// Prefer symmetric layouts for square images
if (Math.abs(mainImage.ratio - 1.0) < 0.1) {
return ['E1', 'E2', 'I', 'A']
}
// Use simple rules for limited images
if (availableImages.length < 5) {
return ['A', 'B', 'O']
}
return defaultRuleSet
}To fully appreciate innovations of the Partitioned Container Band system, it is instructive to compare it against existing gallery layout approaches. Each alternative has its merits, but also limitations that the band system specifically addresses.
Traditional grid layouts remain the most common gallery solution, using fixed-size cells arranged in rows and columns.
Traditional Grid: Band System: βββββββ¬ββββββ¬ββββββ βββββββββββ¬ββββ¬ββββ β IMG β IMG β IMG β β MAIN βSUBβSUBβ <- Varied heights βββββββΌββββββΌββββββ€ βββββββββββ΄ββββ΄ββββ€ β IMG β IMG β IMG β β WIDE IMG β <- Respects ratio βββββββΌββββββΌββββββ€ βββββ¬ββββββββββββββ€ β IMG β IMG β IMG β βVRTβ MAIN IMG β <- Multiple layouts βββββββ΄ββββββ΄ββββββ βββββ΄ββββββββββββββ
Masonry layouts, popularised by Pinterest, arrange items in columns with variable heights.
Masonry (vertical only): Band System (mixed flow):
βββββββββββββββ βββββββββββ¬ββββββββ
βIMGββIMGββIMGβ β MAIN β SUB β
β ββββββ€β β βββββββββββ΄ββββ¬ββββ€
β ββIMGββ β β MAIN βVRTβ
βββββ€β ββββββ€ βββββ¬ββββ¬ββββββ€ β
βIMGββββββ€βIMGβ βSUBβSUBβMAIN β β
ββββββIMGββββββ βββββ΄ββββ΄ββββββ΄ββββ
βββββ Horizontal relationshipsProfessional galleries often rely on manual curation, where designers hand-place each image.
| Criteria | Grid | Masonry | Manual | PCB (ours) |
|---|---|---|---|---|
| Aspect Ratio Preservation | Poor | Good | Perfect | Excellent |
| Layout Variety | Poor | Fair | Excellent | Good |
| Scalability | Excellent | Excellent | Poor | Excellent |
| Responsive Adaptation | Good | Good | Poor | Excellent |
| Implementation Complexity | Simple | Moderate | N/A | Complex |
| Computational Cost | Minimal | Low | N/A | Moderate |
The Partitioned Container Band system occupies a unique positionβmore intelligent than grids, more controlled than masonry, more scalable than manual curation. It's particularly suited for applications requiring both aesthetic quality and practical automation.
The Partitioned Container Band system represents a significant advancement in automated gallery layout generation, demonstrating that mathematical rigour and aesthetic excellence need not be mutually exclusive.
Through its innovative approach to image layout, the system has achieved several notable goals:
The nine partitioning rules (A through I, plus O) provide a rich vocabulary for visual composition. Each rule serves specific aspect ratio combinations and importance hierarchies, creating layouts that feel designed rather than generated. The system's ability to dynamically select appropriate rules based on available content ensures visual variety without chaos.
Unlike traditional approaches that force images into predetermined frames, the band system respects each image's inherent proportions. Through soft clipping functions and mathematical optimisation, even extreme aspect ratios find appropriate display contexts. The RMS error minimisation ensures that when compromises must be made, they are distributed evenly rather than concentrated in unfortunate crops.
The breakpoint-free responsive design adapts fluidly to any viewport width, from mobile phones to ultra-wide displays. By regenerating layouts rather than simply scaling them, the system ensures optimal image presentation at every screen size. The mathematical foundations keep computational complexity manageable, enabling real-time layout generation even for substantial image collections.
Several broader principles emerge from this implementation:
The system demonstrates that user interface challenges often have mathematical solutions. The aspect ratio matching, error minimisation, and geometric mean calculations prove that quantitative approaches can solve qualitative problems. What appears as an aesthetic judgementββthis layout looks goodββcan be decomposed into measurable criteria and optimised accordingly.
While fully automated, the system provides numerous control points: importance scoring, rule selection preferences, optimisation parameters, and resize handles. This layered approach allows the algorithm to handle the heavy lifting while preserving artistic direction where it matters most. The post-processing phase exemplifies this philosophyβmathematical optimisation followed by aesthetic refinement.
The difference between a functional layout and a polished gallery lies in the details. The post-processing transformationsβmerging underfilled bands, reordering for visual flow, normalisation of heightsβelevate mechanical output into professional presentation. These refinements acknowledge that mathematical optimisation alone cannot capture every nuance of visual design.
The complete implementation is freely available on GitHub under the terms of the MIT Licence, encouraging both use and contribution from the community. The codebase includes:
Suggestions and code contributions are warmly welcomed. Whether you are looking to:
Feel free to fork the repository and submit pull requests. The modular architecture makes it straightforward to extend functionality without disrupting core behaviour.
The Partitioned Container Band system stands as proof that complex visual problems can yield to systematic solutions. By combining mathematical optimisation with aesthetic sensibility, it opens new possibilities for automated layout generation across diverse applications. As image collections continue to grow in size and variety, systems like this become not just useful, but essential tools for managing visual content at scale.
We look forward to seeing how the community adapts and extends this foundation, creating even more sophisticated solutions to the ever-evolving challenges of digital image presentation.
The following diagrams illustrate all partitioning rules with typical aspect ratio assignments and visual arrangements:
βββββββββββββββββββββββββββββββββββ β β β Image A β β (any ratio) β β β βββββββββββββββββββββββββββββββββββ
βββββββββββββββββββ¬ββββββββββββββββ β β β β Image A β Image B β β (main panel) β (sub panel) β β β β βββββββββββββββββββ΄ββββββββββββββββ
βββββββββββββββββββ¬ββββββββββββββββ β β Image B β β βββββββββββββββββ€ β Image A β β β (main panel) β Image C β β β β βββββββββββββββββββ΄ββββββββββββββββ
βββββββββββββββββββ¬ββββββββ¬ββββββββ β β B β C β β βββββββββ€ β β Image A β βββββββββ€ β β D β E β β β β β βββββββββββββββββββ΄ββββββββ΄ββββββββ
βββββββββββββββββββ¬ββββββββββ¬ββββββ β β B β C β β β β β β Image A βββββββ¬ββββ΄ββββββ€ β β D β E β β β β β βββββββββββββββββββ΄ββββββ΄ββββββββββ
βββββββββββββββββββ¬ββββββββββββββββ β β β β β Image B β β Image A βββββββββ¬ββββββββ€ β β C β D β β β β β βββββββββββββββββββ΄ββββββββ΄ββββββββ
βββββββββββββββββββ¬ββββββββ¬ββββββββ β β B β C β β βββββββββ΄ββββββββ€ β Image A β β β β Image D β β β β βββββββββββββββββββ΄ββββββββββββββββ
βββββββββββββββββββ¬ββββββββ¬ββββββββ β β B β β β βββββββββ€ C β β Image A β D β β β β β β βββββββββββββββββββ΄ββββββββ΄ββββββββ Or flipped variant: βββββββββ¬ββββββββ¬ββββββββββββββββββ β β B β β β C βββββββββ€ β β β D β Image A β β β β β βββββββββ΄ββββββββ΄ββββββββββββββββββ
βββββββββββββββββββ¬ββββββββ¬ββββββββ β β β β β Image A β B β C β β β β β βββββββββββββββββββ΄ββββββββ΄ββββββββ
In 3-column layout: βββββββββββ¬ββββββββββ¬ββββ β Band 0 β Band 1 β B β β (H) β (H) β n β βββββββββββΌββββββββββ€ d β β Band 3 β Band 4 β 2 β β (H) β (H) β(V)β βββββββββββ΄ββββββββββ΄ββββ βββββββββββ¬ββββ¬ββββββββββ β Band 0 β B β Band 2 β β (H) β n β (H) β βββββββββββ€ d βββββββββββ β Band 3 β 1 β Band 4 β β (H) β(V)β (H) β βββββββββββ΄ββββ΄ββββββββββ βββββ¬ββββββββββ¬ββββββββββ β B β Band 1 β Band 2 β β n β (H) β (H) β β d βββββββββββΌββββββββββ β 0 β Band 3 β Band 4 β β(V)β (H) β (H) β βββββ΄ββββββββββ΄ββββββββββ
:root {
--gaps: 12px; /* Gap between bands and panels */
}const INTERNAL_WIDTH = 768 // Base unit for layout calculations const clip_p = 0.444 // Clipping function parameter
{
"prefix":"photos", /* prefix for this image collection */
"lastupdate":"2025-06-08 05:51 UTC", /* optional last update */
"arts":[
{"ord":10010, "year":2022, "dim":"1800/2400", "author":"AuthorName", "epic":0},
{"ord":10020, "year":2023, "dim":"4080/3060", "author":"AuthorName", "epic":20},
{"ord":10030, "year":2024, "dim":"[width]/[height]", "author":"AuthorName", "epic":100}
]}