CSS Layout Patterns for CatGo
Split-View Pattern (Trajectory / DOS)
Problem
Need to show a 3D structure viewer alongside a plot panel (side-by-side or stacked), where both halves fill their space equally.
Solution: CSS Grid with 1fr 1fr
Root container (e.g. .trajectory, .structure):
css
.container {
display: flex; /* or grid */
flex-direction: column;
height: var(--height, 100%);
container-type: size; /* enable cqh/cqw for child panes */
position: relative;
overflow: hidden;
}Content area (grid container for split view):
css
.content-area {
display: grid;
flex: 1; /* fills remaining space after controls */
min-height: 0; /* CRITICAL: allows grid to shrink */
}
.horizontal .content-area {
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr;
}
.vertical .content-area {
grid-template-columns: 1fr;
grid-template-rows: 1fr 1fr;
}Children (structure viewer, plot):
css
/* Both children fill their grid cell */
style="height: 100%; min-height: 0"Key Rules
min-height: 0on grid/flex items prevents overflow — without it, content pushes the container larger than its allocationflex: 1on content-area makes it expand to fill available spacecontainer-type: sizeon root enablescqh/cqwunits for panes but also means the element MUST have explicit sizing (intrinsic size = 0)- No fixed
heighton plot components — useResizeObserverorheight: 100%to fill the grid cell
Wrapper Div Pattern: display: contents
Problem
Sometimes you need a wrapper div (e.g. for CSS grid) that should be "invisible" in normal mode — it shouldn't affect layout or introduce extra nesting in the box model.
Solution
css
/* Default: invisible wrapper */
.wrapper {
display: contents;
}
/* When split-view is active, becomes a real grid item */
.container.split > .wrapper {
display: block;
position: relative;
overflow: hidden;
min-height: 0;
min-width: 0;
}Why display: contents?
- Element doesn't generate a box → children render as if directly inside the parent
position: relativeon the wrapper is ignored → absolutely positioned children fall through to the grandparent- Zero layout impact — identical to having no wrapper at all
- Perfect for conditional grid layouts where the wrapper is only needed in split mode
Caveats:
- No
overflow,background,borderon the element (it has no box) - Accessibility: some screen readers may have issues (not relevant for structural wrappers)
Structure.svelte Layout Architecture
.structure (position: relative, container-type: size, height from CSS var)
├── Normal mode: display: block
│ └── .structure-main (display: contents → invisible)
│ ├── Canvas wrapper (height: 100%)
│ ├── Control panes (position: absolute)
│ └── Modals, overlays, etc.
│
├── DOS split mode: display: grid
│ ├── .structure-main (display: block, grid item)
│ │ └── [same children as normal mode]
│ └── .dos-panel (flex column, grid item)
│ ├── .dos-panel-header (flex-shrink: 0)
│ └── .dos-plot-area (flex: 1, min-height: 0)
│ └── DosPlot (height: 100%, ResizeObserver)Trajectory.svelte Layout Architecture
.trajectory (display: flex, flex-direction: column, height: var(--traj-height, 100%))
├── .trajectory-controls (flex-shrink: 0, natural height)
└── .content-area (display: grid, flex: 1, min-height: 0)
├── Structure (style="height: 100%; min-height: 0")
└── ScatterPlot/Histogram (style="height: 100%")