Localized Precision: Orchestrating Micro Alignment
While CSS Grid governs the "Macro" skeleton of the page, the Espalier system utilizes Flexbox for the surgical, one-dimensional alignment of items within components. We treat Flexbox as a "Content-Out" engine: a tool where the inherent size of the content—such as the label of a button or the width of an icon—informs its own spatial distribution.
By limiting Flexbox to localized, component-level challenges, we maintain a defensible architecture that prioritizes structural predictability without sacrificing internal flexibility.
The Division of Labor: Why Micro?
From a Startup Strategist’s perspective, over-using Flexbox for page-level layout creates technical debt. Flexbox is fundamentally linear; when forced to manage two dimensions, it requires deeply nested wrappers that obfuscate the DOM.
In Espalier, Flexbox is reserved for:
- Linear Components: Toolbars, navigation bars, and breadcrumbs.
- Alignment-Heavy Units: Centering content within a card or aligning labels with input fields.
- Dynamic Wrapping: Tag lists or carousels where the number of items is unknown.
Intrinsic Responsiveness: The Wrap-and-Grow Pattern
One of the "killer features" of Flexbox in our system is its ability to adapt to available space without media queries. By pairing flex-wrap with flex-grow, we enable components to stack and shift naturally.
/* The 'Every Layout' Stack pattern */
.toolbar {
display: flex;
flex-wrap: wrap;
gap: var(--esp-size-small);
align-items: center;
}
.toolbar-primary-action {
/* Grow to fill space on mobile, but base size is content-driven */
flex: 1 0 auto;
}
This pattern ensures that a search bar and a button group can sit side-by-side on a desktop but stack perfectly on a mobile device, purely through the interaction of content-width and container constraints.
Alignment Consistency: Main vs. Cross Axes
To ensure visual harmony, we utilize standardized alignment roles across all components:
| Engine Role | Property | Strategic Intent |
|---|---|---|
| Distribution | justify-content |
Manages the spacing between items (e.g., space-between for headers). |
| Cross-Alignment | align-items |
Ensures vertical consistency (e.g., baseline for text/icon pairings). |
| Gap Management | gap |
Utilizes our fluid spacing tokens to maintain vertical rhythm. |
Challenge the Assumption: "Grid for Everything"
While Espalier is a "Grid-First" system, a common mistake is attempting to force one-dimensional lists into a Grid. We challenge this. Using Grid for a simple row of buttons adds unnecessary overhead and makes "intrinsic" wrapping significantly harder to maintain.
For a defensible architecture, use Grid for the Scaffolding and Flexbox for the Furniture.
Strategic Implementation in Lit
We utilize Lit’s directive system to apply these micro-alignment rules reactively, ensuring that components like esp-button-group remain flexible for the consumer.
render() {
const alignmentStyles = {
justifyContent: this.centered? 'center' : 'flex-start',
flexDirection: this.vertical? 'column' : 'row'
};
return html`
<div class="micro-trellis" style=${styleMap(alignmentStyles)}>
<slot></slot>
</div>
`;
}