ワンクリックで
frontend-page-layout
Use when creating page layouts, handling height calculations, or structuring page components with flex/grid
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Use when creating page layouts, handling height calculations, or structuring page components with flex/grid
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Use when deploying Cloudflare Workers, managing R2 storage, or working with Cloudflare infrastructure
Use when working with ANTD components, theme tokens, icons, forms, or feedback components (message/notification/modal)
Use when adding, referencing, or serving static assets (images, fonts, videos, 3D models) through the R2 CDN pipeline with type-safe imports
Use when writing or reviewing JavaScript/TypeScript code for style patterns like concise arrows, inline handlers, expression formatting, or when tempted to use eslint-disable
Use when working with environment variables in frontend code
Use when creating or modifying keyboard shortcuts/hotkeys in frontend code
| name | frontend-page-layout |
| description | Use when creating page layouts, handling height calculations, or structuring page components with flex/grid |
This skill defines layout structure patterns for page components to ensure consistent height calculations and prevent overflow issues.
The application uses a two-tier layout system:
__root.tsx) - Minimal, just renders <Outlet />_protected.tsx) - Handles authentication and provides sized containerKey Pattern:
// _protected.tsx:56
<div style={{ height: "calc(100vh - 48px)" }}>
<Outlet />
</div>
This creates a container that fills the viewport minus the 48px global Nav.
Page components receive a pre-sized container from the protected layout.
CRITICAL RULE: Pages MUST use height: 100%, NEVER recalculate viewport.
// ✅ CORRECT - Page component
export const Page_Example = () => {
return (
<div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
{/* Page content */}
</div>
);
};
// ❌ WRONG - Recalculating viewport
export const Page_Example = () => {
return (
<div style={{ height: "calc(100vh - 44px)", display: "flex", flexDirection: "column" }}>
{/* This WILL cause overflow! */}
</div>
);
};
// ✅ Page container - inherit from parent
<div style={{ height: "100%" }}>
// ✅ Main content area - grow to fill remaining space
<div style={{ flex: 1, overflow: "hidden" }}>
// ✅ Fixed-height secondary nav
<div style={{ height: 44 }}>
// ❌ NEVER do this in page components
<div style={{ height: "calc(100vh - 44px)" }}>
<div style={{ height: "calc(100vh - 48px)" }}>
<div style={{ height: "100vh" }}>
// ❌ NEVER hardcode pixel heights matching viewport calculations
<div style={{ height: "1032px" }}> // Viewport-derived value
Single Source of Truth:
Nav.tsx:80)calc(100vh - 48px) (defined in _protected.tsx:56)height: 100% (inherit from container)Why This Matters:
If the Nav height changes to 50px:
_protected.tsx only → All pages automatically adjustcalc(100vh - 48px) → Must update every page manuallyCommon pattern for pages with secondary navigation:
export const Page_Example = () => {
return (
<div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
{/* Fixed-height secondary nav */}
<SecondaryNav height={44} />
{/* Main content - fills remaining space */}
<div style={{ flex: 1, overflow: "hidden" }}>
<PanelGroup direction="horizontal">
{/* Panels handle their own sizing */}
</PanelGroup>
</div>
</div>
);
};
Key Elements:
height: 100% + flex columnflex: 1 + overflow: hiddenBorders add to element dimensions. Use box-sizing: border-box (usually already global).
// ✅ Border included in height calculation
<div style={{
height: 44,
borderBottom: `1px solid ${token.colorBorder}`,
boxSizing: "border-box" // Usually global, explicit here for clarity
}}>
// ❌ Border adds 1px to height
<div style={{
height: 44,
borderBottom: `1px solid ${token.colorBorder}`,
boxSizing: "content-box" // Avoid this
}}>
File: spark/frontend/my-vite-app/src/pages/Page_Set/Page_Set.tsx
export const Page_Set = () => {
return (
<Provider_Page_Set>
{/* ✅ height: 100% - inherits from _protected container */}
<div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
{/* Fixed-height secondary nav (44px) */}
<PageSet_Nav setId={setId} />
{/* Main content fills remaining space */}
<div style={{ flex: 1, overflow: "hidden" }}>
<PanelGroup direction="horizontal">{/* Resizable panels */}</PanelGroup>
</div>
</div>
</Provider_Page_Set>
);
};
export const Page_Bad = () => {
return (
// ❌ WRONG - Recalculating viewport height
<div style={{ height: "calc(100vh - 44px)", display: "flex", flexDirection: "column" }}>
<SecondaryNav />
<MainContent />
</div>
);
};
Why This Breaks:
_protected.tsx provides calc(100vh - 48px) containercalc(100vh - 44px) = 4px overflow// ❌ DON'T recalculate viewport
<div style={{ height: "calc(100vh - 44px)" }}>
// ✅ DO inherit from parent
<div style={{ height: "100%" }}>
// ❌ DON'T hardcode viewport-based heights
<div style={{ height: "1032px" }}> // Someone calculated viewport - 48px
// ✅ DO use relative heights
<div style={{ height: "100%" }}>
// ❌ DON'T forget overflow handling
<div style={{ flex: 1 }}>
<PanelGroup> {/* May overflow container */}
// ✅ DO constrain overflow
<div style={{ flex: 1, overflow: "hidden" }}>
<PanelGroup> {/* Contained within bounds */}
// ❌ DON'T mix calculation strategies
<div style={{ height: "calc(100vh - 48px)" }}>
<div style={{ height: "100%" }}> {/* Which 100%? Confusing! */}
// ✅ DO use consistent relative heights
<div style={{ height: "100%" }}>
<div style={{ flex: 1 }}> {/* Clear hierarchy */}
If you see unexpected vertical scroll:
Check page container height:
height: 100%calc(100vh - Xpx) → Replace with 100%Check parent layout:
_protected.tsx should provide sized containerCheck borders:
box-sizing: border-box should be globalCheck nested content:
flex: 1 + overflow: hidden for main content// Column layout with fixed header + flexible content
<div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
<Header height={44} />
<Content flex={1} overflow="hidden" />
</div>
// Row layout with sidebar + main area
<div style={{ height: "100%", display: "flex", flexDirection: "row" }}>
<Sidebar width={250} />
<Main flex={1} overflow="auto" />
</div>
<div
style={{
height: "100%",
display: "grid",
gridTemplateRows: "44px 1fr", // Fixed header + flexible content
}}
>
<Header />
<Content />
</div>
When creating a new page component:
height: 100% (not viewport calculations)display: flex with flexDirection: columnflex: 1 + overflow: hiddencalc(100vh - Xpx) anywhere in page component