Grid showcasing previous work.
<section class="pfolio">
<h2 class="pfolio__heading">Selected work</h2>
<div class="pfolio__grid pfolio__grid--3 pfolio__grid--hover">
<figure class="pfolio__item"><div style="background:#D9C8F0;" role="img" aria-label="Brand refresh for Northwind"></div><figcaption>Brand refresh</figcaption></figure>
<figure class="pfolio__item"><div style="background:#D9C8F0;" role="img" aria-label="App redesign for Halcyon"></div><figcaption>App redesign</figcaption></figure>
<figure class="pfolio__item"><div style="background:#D9C8F0;" role="img" aria-label="Packaging for Fenwick"></div><figcaption>Packaging</figcaption></figure>
</div>
</section>
<style>
.pfolio { font: 15px system-ui, sans-serif; color: #241430; padding: 24px; }
.pfolio__heading { margin: 0 0 18px; font-size: 22px; font-weight: 700; }
.pfolio__grid { display: grid; gap: 16px; }
.pfolio__grid--2 { grid-template-columns: repeat(2, 1fr); }
.pfolio__grid--3 { grid-template-columns: repeat(3, 1fr); }
.pfolio__grid--4 { grid-template-columns: repeat(4, 1fr); }
.pfolio__item { margin: 0; position: relative; border-radius: 10px; overflow: hidden; }
.pfolio__item div { aspect-ratio: 4 / 3; opacity: .85; }
.pfolio__item figcaption { position: absolute; left: 0; right: 0; bottom: 0; padding: 8px 10px; background: #241430cc; color: #FAF7F2; font-size: 13px; font-weight: 600; opacity: 0; }
.pfolio__grid--always figcaption { opacity: 1; }
.pfolio__grid--hover .pfolio__item:hover figcaption, .pfolio__grid--hover .pfolio__item:focus-within figcaption { opacity: 1; }
@media (prefers-reduced-motion: no-preference) {
.pfolio__item figcaption { transition: opacity .15s; }
}
</style><section class="font-sans text-[#241430] p-6">
<h2 class="m-0 mb-4.5 text-2xl font-bold">Selected work</h2>
<div class="pfolio-tw pfolio-tw--3 pfolio-tw--hover grid gap-4">
<figure class="pfolio-tw__item m-0 relative rounded-[10px] overflow-hidden"><div class="aspect-[4/3] opacity-85" style="background:#D9C8F0;" role="img" aria-label="Brand refresh for Northwind"></div><figcaption class="pfolio-tw__cap absolute left-0 right-0 bottom-0 px-2.5 py-2 bg-[#241430cc] text-[#FAF7F2] text-[13px] font-semibold">Brand refresh</figcaption></figure>
<figure class="pfolio-tw__item m-0 relative rounded-[10px] overflow-hidden"><div class="aspect-[4/3] opacity-85" style="background:#D9C8F0;" role="img" aria-label="App redesign for Halcyon"></div><figcaption class="pfolio-tw__cap absolute left-0 right-0 bottom-0 px-2.5 py-2 bg-[#241430cc] text-[#FAF7F2] text-[13px] font-semibold">App redesign</figcaption></figure>
<figure class="pfolio-tw__item m-0 relative rounded-[10px] overflow-hidden"><div class="aspect-[4/3] opacity-85" style="background:#D9C8F0;" role="img" aria-label="Packaging for Fenwick"></div><figcaption class="pfolio-tw__cap absolute left-0 right-0 bottom-0 px-2.5 py-2 bg-[#241430cc] text-[#FAF7F2] text-[13px] font-semibold">Packaging</figcaption></figure>
</div>
</section>
<style>
.pfolio-tw--2 { grid-template-columns: repeat(2, 1fr); }
.pfolio-tw--3 { grid-template-columns: repeat(3, 1fr); }
.pfolio-tw--4 { grid-template-columns: repeat(4, 1fr); }
.pfolio-tw__cap { opacity: 0; }
.pfolio-tw--always .pfolio-tw__cap { opacity: 1; }
.pfolio-tw--hover .pfolio-tw__item:hover .pfolio-tw__cap, .pfolio-tw--hover .pfolio-tw__item:focus-within .pfolio-tw__cap { opacity: 1; }
@media (prefers-reduced-motion: no-preference) {
.pfolio-tw__cap { transition: opacity .15s; }
}
</style>export function PortfolioGrid({
heading = "Selected work",
columns = "3",
alwaysShowCaptions = false,
accent = "#D9C8F0",
}) {
const items = [
{ label: "Brand refresh", alt: "Brand refresh for Northwind" },
{ label: "App redesign", alt: "App redesign for Halcyon" },
{ label: "Packaging", alt: "Packaging for Fenwick" },
];
return (
<section style={{ font: "15px system-ui, sans-serif", color: "#241430", padding: 24 }}>
<h2 style={{ margin: "0 0 18px", fontSize: 22, fontWeight: 700 }}>{heading}</h2>
<div style={{ display: "grid", gap: 16, gridTemplateColumns: `repeat(${columns}, 1fr)` }}>
{items.map((item) => (
<figure key={item.label} style={{ margin: 0, position: "relative", borderRadius: 10, overflow: "hidden" }}>
<div role="img" aria-label={item.alt} style={{ aspectRatio: "4 / 3", opacity: 0.85, background: accent }} />
<figcaption style={{ position: "absolute", left: 0, right: 0, bottom: 0, padding: "8px 10px",
background: "#241430cc", color: "#FAF7F2", fontSize: 13, fontWeight: 600,
opacity: alwaysShowCaptions ? 1 : 0 }}>{item.label}</figcaption>
</figure>
))}
</div>
</section>
);
}