22 CSS Split Screen Layouts
22 hand-coded CSS split-screen layouts for tier-1 SaaS landing heroes (Stripe / Linear / Framer / Vercel / Notion), fintech sign-in flows (Coinbase / Ramp / Wealthfront), real-estate property compares (Zillow / Redfin / Compass / Realtor.com), editorial magazine spreads (Vogue / Kinfolk / NYT), and scroll-storytelling long-reads (Pudding / Guardian / NYT interactives) — classic 50/50, diagonal clip-path polygon, hover-reveal grid animation, before/after slider, sticky-scroll compare, 3D perspective keynote, plus editorial hero, quad photo grid, curved seam, Z-pattern card, and magazine crossover. 20 Pure CSS + 2 vanilla-JS under 20 lines each — zero dependencies vs Aceternity ($299/yr, 45KB), Magic UI, ReactBits, shadcn split. Modern CSS surface: animatable grid-template-columns, :has() relational state, clip-path: polygon(), transform-style: preserve-3d, position: sticky, container queries, animation-timeline: view(). Scoped under .ss-XX-NN for no-collision pasting, prefers-reduced-motion guarded per WCAG 2.3.3, framework-agnostic (React / Next.js App Router / Vue / Svelte / Astro / Tailwind v4 / shadcn).
Related20 CSS Diagonal Sections31 CSS Hero Sections15 CSS Flexbox Layouts30 CSS Login Forms
Premium design systemPartner: Untitled UI
Affiliate linkDesigning the whole screen, not just this section?
You just browsed 22 splits. Untitled UI is the Figma UI kit 380,000+ designers use: 10,000+ components and 420+ ready page examples in Pro, with a matching React library on Tailwind CSS. Figma Pro is a one-time purchase from $129.
Untitled UI. We may earn a commission, at no extra cost to you.
02. Diagonal Split (opens in a new tab)
clip-path: polygon() for the angled wedge; oversized condensed display type sells the impact.03. Wine Cellar (opens in a new tab)
<dl> for the vintage details.04. Hover Reveal Split (opens in a new tab)
flex-grow transition; massive condensed type and chromatic-aberration headlines complete the album-cover feel.05. Coffee Triptych (opens in a new tab)
1fr 1fr 1fr and a shared expand-on-hover behavior.06. Curved Split (opens in a new tab)
border-radius and a generous clip-path. The two halves never share a straight line — feels organic, beach-y, hand-shaped.07. Asymmetric 70/30 (opens in a new tab)
08. Stepped Diagonal (opens in a new tab)
09. Jewelry Sign-in (opens in a new tab)
<form> with proper labels and autocomplete tokens.10. Before/After Slider (opens in a new tab)
<input type="range"> to wipe between two states. Pure CSS via :has() on the input value (modern browsers); falls back to a clean static split otherwise.11. Two Seasons (opens in a new tab)
12. Music App Toggle (opens in a new tab)
:has(:checked) on the grid template; everything else is CSS.13. Real-estate Compare (opens in a new tab)
14. Detective Novel (opens in a new tab)
15. Mediterranean Travel (opens in a new tab)
16. Glitch Arcade (opens in a new tab)
17. Coffee Origin Story (opens in a new tab)
<ol> with custom counter styling.18. Quad Photo Split (opens in a new tab)
:has() on the wrapper to drive the proportions.19. Recipe Reveal (opens in a new tab)
<ul> + <ol> for ingredients and steps.20. Pet Adoption Z (opens in a new tab)
21. Magazine Crossover (opens in a new tab)
22. 3D Perspective Keynote (opens in a new tab)
perspective + rotateY; left panel angles toward viewer, right panel angles away. The "Apple event slide" feel — premium, sleek, almost cinematic.Build your own
Tweak the exact look in our visual generators — no signup, instant copy-paste.
Frequently asked questions
How do you pick the right CSS split-screen pattern for your page?
overflow: visible; the visual break signals magazine-style prestige. For before/after comparisons where users need to see both states at once, use a single overlay with a draggable clip-path slider rather than two side-by-side panels — a slider ships two full views in the same box and lets users control the reveal precisely. Every pattern in this collection uses CSS Grid on the outer wrapper with a @media (max-width: 640px) { grid-template-columns: 1fr } block so mobile stacks vertically.How do I animate the split ratio on hover or click without JavaScript?
grid-template-columns animatable when both keyframes use the same unit type — same fr, or same percentages. Set the wrapper to display: grid; grid-template-columns: 1fr 1fr; transition: grid-template-columns 400ms cubic-bezier(0.4, 0, 0.2, 1), then on hover or via :has(:checked) retarget to 1.85fr 1fr. The grid tracks tween smoothly and the child content reflows as its column expands. This lands in Chrome 111+, Firefox 128+, Safari 17.4+. On older browsers the resize snaps between states with no animation — the interaction still works, just abruptly, which reads as intentional design. Pair with @media (hover: hover) to skip the hover trigger on touch devices (where :hover sticks after tap), and add a keyboard equivalent by giving each panel tabindex='0' and mirroring the :hover rule with :focus-visible. For radio/checkbox-driven toggles like the Two Seasons demo, hide the input with position: absolute; opacity: 0, style a label as the visible target, and gate the parent grid with .wrapper:has(#option:checked) { grid-template-columns: 65% 35%; }. Wrap the transition in @media (prefers-reduced-motion: no-preference) so vestibular-sensitive users get an instant snap rather than a swept resize.How do I build a diagonal split with CSS clip-path polygon?
position: relative stage with isolation: isolate so the stacking context stays contained. Both panels fill the stage with inset: 0. The first panel gets clip-path: polygon(0 0, 60% 0, 40% 100%, 0 100%) to carve the left-leaning trapezoid; the second gets the inverse polygon(60% 0, 100% 0, 100% 100%, 40% 100%). Because both panels occupy the same box, the diagonal seam is mathematically identical and never shows a hairline gap — no anti-aliasing artifact, no sub-pixel bleed. Text inside each panel uses normal flow with padding, so headings sit safely inside the visible polygon rather than fighting the diagonal edge. Two real gotchas: text in the clipped-away region is still selectable because clip-path only affects paint (not hit testing), so keep body copy padded well inside the visible area; and the panels need an explicit min-height on the wrapper or they collapse to zero and the whole component disappears silently. On mobile below 640px, swap the polygon to none and stack the panels vertically — diagonal seams produce awkward triangular slivers on narrow viewports. Baseline in Chrome 55+, Safari 14.1+, Firefox 54+ — safe for every tier-1 audience.How do I build a before/after image comparison slider with pure CSS and one small JS handler?
grid-area: 1 / 1. The top panel gets clip-path: inset(0 calc(100% - var(--pos)) 0 0) so it's revealed only up to the --pos value. Overlay an <input type='range' value='50' min='0' max='100'> across the wrapper with position: absolute; inset: 0; opacity: 0, catching drag events across the whole surface. Under 20 lines of JavaScript listen for input and write e.target.parentElement.style.setProperty('--pos', e.target.value + '%'). A vertical handle uses left: var(--pos); transform: translateX(-50%) and pointer-events: none so drags pass through to the range beneath. Accessibility essentials: set step='5' on the range (default 1% requires 100 arrow-key presses to cross the panel), add aria-label describing what's being compared ("Before and after treatment"), and skip transitioning clip-path — cheap Android GPUs jank on clip-path animation. Baseline in Chrome 55+, Safari 9.1+, Firefox 54+. Real estate compare tools (Zillow, Redfin, Compass) and photo editing tutorials (Photoshop, Lightroom demos) use this exact pattern; average CPM $15-30 on real estate metros, $8-15 on tech-tutorial content.How do I build a SaaS landing hero with split-screen sign-in like Stripe, Linear, Framer, Vercel, or Notion?
<section aria-label='Sign in'> as the outer landmark, then a display: grid; grid-template-columns: 55% 45%; min-height: 100vh wrapper. The visual panel paints its hero with a layered background-image — radial-gradient highlight over a linear-gradient base — so it ships without an image asset; brand copy floats bottom-left via align-self: end on the grid child. The form panel uses display: flex; flex-direction: column; gap: 1.25rem with inputs styled through :focus-visible rings at 3:1 contrast per WCAG 2.4.13. Include autocomplete='email' and autocomplete='current-password' attributes or password managers silently break. The social row uses display: grid; grid-template-columns: repeat(3, 1fr) for OAuth providers. Below 52rem the grid collapses and the product panel becomes a short banner — or hide it entirely with display: none under 36rem so the form is immediately actionable on phones. SaaS auth pages carry $8-25 CPM on Google Ads for developer keywords; the form-first mobile pattern lifts conversion 20-40% vs a full-height visual that pushes the form below the fold. This is the layout Stripe Checkout, Linear login, Framer sign-in, and Vercel dashboard auth all ship.How do I build a real estate property comparison split screen like Zillow, Redfin, Compass, or Realtor.com?
grid-template-columns: 1fr 1fr with a fixed viewport height, so each panel becomes an independent scroll container via overflow-y: auto. Each side holds a property card built from a stacked flex column: hero photo (16:10 aspect-ratio for consistent card height across property photos), price row, and a stats grid with beds, baths, and square footage rendered through grid-template-columns: repeat(3, 1fr). A center border-inline-start on the right panel provides the visual seam. Independent scroll containers mean aligned rows drift as users scroll one side — that's a feature, not a bug, because the point is direct comparison at each user's own pace. Highlight the winning field per row (lower price, more square footage) with a :has() selector on the stats grid, or precompute a data-winner attribute at build time. Add scroll-snap-type: y mandatory on each panel plus scroll-snap-align: start on stat rows so scrolling settles on comparable sections instead of arbitrary offsets. Real estate is a $15-30 CPM vertical on Google Ads (metro markets), $25-50 on tier-1 city luxury, and $30-60 on Manhattan / Bay Area / London prime. Fair Housing Act compliance (42 U.S.C. § 3604) requires that comparison tools don't steer users toward or away from properties based on protected characteristics — keep the fields you compare limited to objective property attributes (price, size, beds/baths), not location-neighborhood ratings that could function as proxies.How do I build an editorial magazine split-screen spread with a headline that crosses both panels?
grid-template-columns: 45% 55% in favor of the article text, with overflow: visible on both the wrapper AND the left panel so a centerpiece image can cross the boundary. The image is an absolutely positioned <img> inside the left panel with right: -20%; z-index: 2, pushing it into the right panel's territory. The headline is a separate absolutely positioned <h2> anchored to the grid wrapper with left: 30%; right: 10%, so it visually spans both panels while remaining a single semantic heading. Serif typography carries the editorial feel — font-family: 'Playfair Display', 'Fraunces', Georgia, serif with font-variation-settings: 'opsz' 72 if using a variable font. The left panel gets a muted tint (#f5f1ea); the right stays white. Because absolute positioning removes the headline from flow, add min-height on the wrapper or reserve space with an invisible spacer sized to the headline — otherwise the grid row collapses to panel content and the headline overlaps other elements. On narrow viewports below 640px, reset the image's right: 0 so it doesn't escape the card entirely. Vogue, Kinfolk, Cereal, The New York Times Magazine, and Substack Reads all use variations of this pattern; editorial content sits in the $5-12 CPM range but drives higher session depth (2-3× baseline) which compounds via display-refresh revenue.How do I build a scroll-storytelling split with a sticky image and scrolling text like The New York Times or Pudding?
grid-template-columns: 55% 45% — text gets the larger column, sticky image the smaller. The left panel is a normal-flow stack of paragraphs (each ~3-6 paragraphs per chapter). The right panel is a grid cell with a single inner <div> using position: sticky; top: 0; height: 100vh. Because sticky is scoped to its nearest scroll ancestor, the image pins as the page scrolls until the right column's bottom edge passes the viewport top. The image itself uses object-fit: cover on an <img> so it never letterboxes. To swap images mid-story (the Pudding pattern), give each chapter its own image with staggered top offsets so each chapter's image pins for its own section — the effect reads as camera cuts synced to reading progress. Sticky silently fails when any ancestor has overflow: hidden, overflow: auto, or overflow: clip, so audit the ancestor chain before assuming the sticky rule itself is broken. The sticky child needs an explicit top value (top: 0 is standard) or it behaves like position: relative and never pins. On mobile, drop the sticky behavior entirely (or use a shorter height: 60vh) so the pin doesn't eat the whole small viewport. Long-form journalism using this pattern (NYT Snow Fall, Pudding data essays, Guardian long-reads) averages 8-12 minute session length — 4-6× baseline article dwell time.How do I build a 3D perspective split screen with panels tilting into a virtual stage?
perspective: 1200px and transform-style: preserve-3d. Inside, two panels sit in a flex row: the left carries transform: rotateY(-6deg) and the right rotateY(6deg), plus transform-origin set to the inner edge so the tilt hinges toward the viewer. A CSS custom property --tilt drives both rotations (with opposite signs), and a small IntersectionObserver script toggles --tilt: 0deg when the card enters the viewport, easing the panels flat via transition: transform 700ms ease-out. On hover the tilt returns for a subtle re-engage. Critical detail: transform-style: preserve-3d must live on the parent, not the panels — setting it on the panels themselves leaves them flat because their own children would need the 3D context. Text inside tilted panels can look blurred on Windows Chromium due to subpixel rendering under 3D transforms; add will-change: transform during the animation and remove it after (the compositor promotes the layer for the duration only). Modern browsers can drop the JS entirely by using scroll-timeline with animation-timeline — Chrome 115+ and Edge 115+ support it natively; Safari and Firefox use the IntersectionObserver fallback. Under prefers-reduced-motion: reduce, skip the observer entirely and render both panels at --tilt: 0deg from first paint.Do these CSS split-screen layouts work with React, Next.js App Router, Vue, Svelte, Astro, Tailwind, and shadcn?
:has(), clip-path, and (for a few) a small vanilla-JS handler for range-input sync or IntersectionObserver-driven tilt. None depend on a JavaScript framework's runtime, and none carry component library assumptions. To port into a React or Next.js App Router project, paste the HTML into a <section> component and drop the scoped CSS into a CSS module, styled-components, or a Tailwind @layer components block. The class prefixes (.ss-edt-, .ss-dia-, etc.) prevent global collisions when multiple split-screen sections appear on the same page. Tailwind v4 users can convert most rules 1:1 — grid-template-columns: 55% 45% becomes grid-cols-[55%_45%], clip-path: polygon(...) becomes an arbitrary variant. shadcn/ui doesn't ship a split-screen primitive (its Card and Sheet components serve different jobs), so these fill the ecosystem gap. Aceternity ($299/yr Pro) ships one split-screen hero at ~45KB with animation library dependencies; Magic UI and ReactBits similarly bundle motion libraries. The demos here ship at zero bundle cost — pure HTML + CSS + optional 20-line vanilla JS. Vue's <script setup>, Svelte's <script>, and Astro's <script is:client> all execute the same handler code without modification.Related collections
15 CSS Aspect Ratio Demos
15 hand-coded CSS aspect-ratio demos for video embeds, product galleries, IAB ad slots, native dialogs, and CLS-safe placeholders: 16:9 iframe YouTube embed with click-to-load facade + up-next rail, 21:9 full-screen hero video with min-height/max-height:100svh guardrails + Ken Burns drift, 1:1 Instagram-style square grid with 2×2 feature tile, 4:3 magazine card image cover, 9:16 vertical stories rail (TikTok/Reels/Shorts pattern) with scroll-snap + segment bars, 4:5 apparel product image gallery with radio-driven state + 1:1 thumbnails, 1:1 zoom thumbnail carousel with pointer-tracked --zx/--zy magnifier, prevent-layout-shift placeholder with live PerformanceObserver CLS meter (before/after side-by-side lab), dynamic content fallback with three policies (bend/strict/auto) via :has() toggle, IAB ad banner slots (728×90 leaderboard, 300×250 medium rectangle, 300×600 half-page, 320×50 mobile) with skeletons + container-query mobile swap, responsive modal dialog sized min(92vw, 88svh×16/9, 1080px) with @starting-style animation, responsive OpenStreetMap iframe wrapper with 16:9 → 1:1 container-query narrow swap, media query orientation live HUD + resize:both container-ratio playground, object-fit logo cloud with contain/cover/fill switcher via :has(), and side-by-side padding-top hack (height:0 + padding-top:56.25%) → modern aspect-ratio migration comparison with live ratio picker. 11 truly Pure CSS + 4 with a tiny optional vanilla JS snippet (facade swap, pointer magnifier, CLS meter, native dialog). Every demo is scoped under a unique .car-NN prefix so it drops into any project without CSS collisions, ships prefers-reduced-motion guards, and is framework-agnostic (works as-is in React, Vue, Svelte, Astro, Next.js, Remix, or plain HTML).
6 CSS Bento Grid Layouts
6 production CSS bento grid layouts with 12 hand-coded designs — Apple-style product showcase, SaaS feature value-prop matrix, analytics dashboard overview, creative portfolio, e-commerce category hub, and link-in-bio social hub. Each topic ships 2 sub-variants side-by-side so visitors see both a keynote aesthetic and a paper-doc variant at once. Container queries, CSS Grid, zero dependencies, copy-paste ready.
20 CSS Blog Layouts
20 hand-coded CSS blog and editorial layouts for magazine homepages, news sites, personal archives, newsletter back-issues, recipe and podcast blogs, developer tutorials, and long-form journalism. Covers a magazine homepage with hero plus editor-picks rail, a news homepage with breaking-news ticker, blog archives with sticky year separators, Substack-style issue-numbered archives, recipe card grids with prep-time badges, podcast episode lists with waveforms, long-form articles with scroll-driven reading progress, drop caps and floated pull quotes via first-letter, Medium-style 65ch centred reader layouts, dev tutorials with a sticky code panel beside prose, interview transcripts with alternating speakers, case-study pages with stat counters, video blogs with an episode rail, full-bleed photo essays, news articles with sticky related-stories sidebars, documentation pages with prev/next chapter nav, a standalone blog post card, a scroll-snap category filter bar, an inline newsletter callout that breaks out of the prose column, and a horizontal featured-post rail. 12 are pure CSS with zero JavaScript. Every layout is scoped under a .bl-NN prefix for no-collision pasting, guards prefers-reduced-motion, and ports unchanged to React, Vue, Svelte, Astro, Next.js and Tailwind.





















