
CSS Grid Portfolio Layout Example HTML CSS
Published
16 hand-coded CSS portfolio layouts for freelance developers, UX/UI designers, product designers, illustrators, photographers and agency teams: grid galleries, Apple-style bento, native masonry walls, sticky-sidebar splits, hover-overlay grids, horizontal scroll showcases, split screens, dark-mode token systems, single-page dev sites, UX case studies, minimalist indexes, freelancer pricing layouts, 3D card flips, full-screen heroes and sticky app-shells. 14 Pure CSS + 2 tiny JS snippets, WCAG 2.2 AA, modern CSS surface (:has(), @container, scroll-timeline, @supports masonry, oklch()). Scoped under .cpl-NN for no-collision pasting, prefers-reduced-motion guarded, framework-agnostic.
Related31 CSS Hero Sections17 CSS Dashboard Layouts15 CSS Card Grid Layouts

Published

Published

Published

Published

Published

Published

Published

Published

Published

Published

Published

Published

Published

Published

Published

Published
grid-template-rows: masonry (Chrome 121+, Safari 17.4+, Firefox behind flag) plus a grid-auto-flow: dense fallback that looks equally polished in older engines. For freelancer sites that need to convert (a portfolio + services + rate card in one scroll), Demo 12 (Freelance Web Developer Portfolio with Pricing Table) is the reference — testimonials block above a 3-tier pricing table with a featured middle plan is the highest-converting pattern on Awwwards SOTD-winning freelancer sites. For senior UX designers submitting case studies, Demo 10 (UX Case Study Layout) ships the exact 1fr/62ch/1fr content grid that IDEO, Frog Design, and Google Design portfolios use — a reading-width column with room for full-bleed hero imagery breakout. And for developers who want a fast, single-page personal site, Demo 09 (Single-Page Developer Portfolio) is the correct picking pattern — anchor-navigation between hero → work → about → contact, a scroll-timeline hairline progress rail, and full keyboard support out of the box.grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr)) — the auto-fit keyword collapses empty tracks so a 4-column layout on a 1440px canvas becomes 3 columns at 1024px, 2 columns at 640px, and 1 column on mobile without a single @media query. The min(280px, 100%) guard prevents the classic 'overflow on ultra-narrow viewports' bug where minmax(280px, 1fr) alone would force the container to grow past 100% width when the viewport is 260px (iPhone SE landscape). Second, when the gallery lives inside a variable-width container (sidebar-embedded portfolio, dashboard preview, project modal), wrap the gallery in container-type: inline-size then use @container (min-width: 720px) { .card { grid-template-columns: auto 1fr; } } — the card component now reflows based on ITS OWN container width, not the viewport, so it works correctly whether the parent sidebar is expanded or collapsed. This is exactly the recipe Bestfolios, Read.cv, and every 2026 Awwwards SOTD ships in production — no CSS Grid framework, no JS resize listener, no dependencies. See Demos 01 (auto-fit + span-2 featured card), 05 (auto-fit + hover-overlay stagger), 08 (dark-mode auto-fit), and 13 (beginner-friendly auto-fit cards) for the full worked recipes at three complexity levels.<header>, <nav aria-label='Primary'>, <main>, <article> per project card, <footer>. Screen readers surface these in the landmark rotor so keyboard-only users can jump directly to your work. (2) Focus-visible rings on every interactive card (Demos 01, 05, 13, 14) — never :focus alone which fires for mouse users too. Focus rings are at least 2px thick with 3:1 contrast against the card background (WCAG 2.4.13, the Oct 2023 update most 'accessible portfolio' templates predate). (3) Hover = focus parity on every project reveal (Demos 05, 11, 14) — every effect that triggers on :hover also fires on :focus-visible, so keyboard-only users see the same reveal a mouse user does. (4) prefers-reduced-motion: reduce guard on every animation (all 16 demos) — WCAG 2.3.3 (AAA but rapidly becoming a filter). (5) The 3D card-flip demo (Demo 14) uses inert on the back-face so tabbing skips hidden content correctly; the dark-mode demo (Demo 08) uses a real <button aria-pressed> for the toggle. (6) Colour contrast in oklch() tokens hit 4.5:1 on body copy and 3:1 on UI text (WCAG 1.4.3). Every card link has an aria-label when the visible text is only 'View →'. This clears Section 508, AODA, EN 301 549, and the ADA Title III standards in one shot — passing the accessibility filter that eliminates most portfolio templates before human review even begins.<img loading='eager' fetchpriority='high'> on the above-the-fold hero and loading='lazy' on grid images below the fold. LCP under 2.5s on Slow 4G (Google's testing threshold) is achievable when you're not shipping a 400KB Next.js/React runtime just to render an image. INP (Interaction to Next Paint, promoted to a Core Web Vital in March 2024) is 0-4ms on every demo because interactivity is CSS-only: filter tabs use :has() + :checked (Demo 07 accent recolor), project card reveals use :hover / :focus-visible (Demos 05, 11, 14), dark-mode toggle uses data-theme attribute swap (Demo 08, ~15 lines of vanilla JS with zero re-render cost). CLS (Cumulative Layout Shift) is 0 because every image element has aspect-ratio declared (Demos 01, 05, 13, 14 — the aspect-ratio: 4/3 or 1/1 reservation means the layout stops shifting the moment the browser knows the ratio, even before pixels download). Compared to a Next.js portfolio template with 200-400KB of client JS: this collection ships 0KB of runtime JS by default, which is what moves a 'Poor CWV' portfolio into 'Good CWV' territory and lifts you above 70% of freelancer competitors in Google's SERP for '<your name> portfolio', '<your city> designer', and long-tail vertical queries like 'freelance react developer <region>' — the queries that actually convert to leads.class to className, drop the JSX into any server or client component (no 'use client' directive needed for the 14 Pure CSS layouts because they have no interactivity that requires hydration; only Demos 08 dark-mode toggle and 14 card-flip need 'use client', and each ships under 20 lines of vanilla JS). Vue 3 / Nuxt 3: accepts as-is, class attribute is native. Svelte / SvelteKit: accepts as-is, class is native. Astro: drop into any .astro component. Remix: any route module. Solid.js / Qwik: accepts as-is. Compared to premium portfolio templates on ThemeForest, Framer, and Webflow: template sites lock you into a specific framework (Framer's runtime is ~150KB gzipped; Webflow's is ~90KB; ThemeForest React templates typically ship 200KB-1.5MB of framework CSS + JS you can't strip) — and none can be dropped into an existing codebase without a wholesale rewrite of your build pipeline. The hand-coded pattern here totals 4-8KB gzipped per demo when you cherry-pick, and the entire 16-demo collection is under 55KB combined. The .cpl-NN numeric-prefix scoping means all 16 layouts coexist on the gallery page without a single class collision, and the same prefix guarantees you can drop any one demo into a codebase that already uses .portfolio, .grid, .card, .hero, or .gallery classes without renaming a single selector. MIT licensed, no attribution required, no watermark, no signup, no email capture.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 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 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.