响应式卡片网格
使用 CSS Grid 构建会自动重排的旅行主题卡片。
启用 JavaScript 后可编辑、运行和保存此案例。固定源码如下:
<!doctype html>
<html lang="zh-Hans" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>响应式卡片网格</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; min-height: 100vh; padding: clamp(28px, 6vw, 72px) 20px; color: #28221e; font-family: "Palatino Linotype", "STSong", serif; background: #f2e8d4; }
main { width: min(1180px, 100%); margin: auto; }
header { display: flex; justify-content: space-between; gap: 20px; align-items: end; margin-bottom: 32px; }
.stamp { display: grid; width: 70px; height: 70px; place-items: center; border: 2px dashed #bd4d37; border-radius: 50%; color: #bd4d37; font: 800 12px/1.3 "Courier New", monospace; text-align: center; transform: rotate(8deg); }
.eyebrow { color: #bd4d37; font: 800 12px/1 "Courier New", monospace; letter-spacing: .17em; }
h1 { margin: 8px 0 0; font-size: clamp(40px, 7vw, 72px); line-height: .95; }
.grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: 18px; }
article { position: relative; min-height: 310px; display: flex; flex-direction: column; justify-content: flex-end; overflow: hidden; padding: 24px; border: 1px solid rgba(61,46,36,.18); border-radius: 2px; color: #fff; isolation: isolate; box-shadow: 0 12px 30px rgba(74,52,34,.12); transition: transform .25s ease, box-shadow .25s ease; }
article::before, article::after { content: ""; position: absolute; z-index: -2; }
article::before { inset: 0; background: var(--scene); }
article::after { inset: 38% 0 0; z-index: -1; background: linear-gradient(transparent, rgba(12,12,12,.78)); }
article:hover { transform: translateY(-7px) rotate(-.4deg); box-shadow: 0 24px 44px rgba(74,52,34,.2); }
article:nth-child(1) { grid-column: span 7; --scene: radial-gradient(circle at 72% 28%, #f8d486 0 8%, transparent 8.5%), linear-gradient(155deg, #688d8d 0 48%, #274d4d 48% 65%, #153939 65%); }
article:nth-child(2) { grid-column: span 5; --scene: radial-gradient(circle at 35% 27%, #fff6df 0 7%, transparent 7.5%), linear-gradient(35deg, #784c5c 0 38%, #c77e69 38% 62%, #e9b77f 62%); }
article:nth-child(3) { grid-column: span 4; --scene: repeating-linear-gradient(120deg, transparent 0 18px, rgba(255,255,255,.08) 19px 21px), linear-gradient(150deg, #5276a4, #1b3150); }
article:nth-child(4) { grid-column: span 8; --scene: radial-gradient(ellipse at 50% 90%, #947547 0 24%, transparent 25%), linear-gradient(165deg, #d3aa69 0 52%, #865c36 52%); }
.place { font: 800 11px/1 "Courier New", monospace; letter-spacing: .16em; }
h2 { margin: 9px 0 7px; font-size: clamp(28px, 4vw, 42px); line-height: 1; }
p { max-width: 480px; margin: 0; color: rgba(255,255,255,.78); font-family: "Avenir Next", "Microsoft YaHei", sans-serif; font-size: 13px; line-height: 1.6; }
.arrow { position: absolute; top: 20px; right: 20px; display: grid; width: 40px; height: 40px; place-items: center; border: 1px solid rgba(255,255,255,.6); border-radius: 50%; font-family: sans-serif; }
@media (max-width: 720px) { header { align-items: center; } .grid article { grid-column: 1 / -1; min-height: 290px; } }
@media (max-width: 450px) { .stamp { display: none; } }
@media (prefers-reduced-motion: reduce) { article { transition: none; } }
</style>
</head>
<body>
<main>
<header><div><span class="eyebrow">WEEKEND FIELD NOTES</span><h1>走远一点</h1></div><div class="stamp">KEEP<br>ROAMING</div></header>
<section class="grid" aria-label="旅行目的地">
<article><span class="arrow" aria-hidden="true">↗</span><span class="place">ZHEJIANG · 01</span><h2>临海山径</h2><p>在雾气散去前穿过松林,让海风成为清晨的第一段对白。</p></article>
<article><span class="arrow" aria-hidden="true">↗</span><span class="place">YUNNAN · 02</span><h2>峡谷日落</h2><p>沿着红色岩壁向西,等待山谷被最后一束光点亮。</p></article>
<article><span class="arrow" aria-hidden="true">↗</span><span class="place">SICHUAN · 03</span><h2>高原夜空</h2><p>关掉所有灯,抬头看银河落在营地之外。</p></article>
<article><span class="arrow" aria-hidden="true">↗</span><span class="place">GANSU · 04</span><h2>沙丘来信</h2><p>风每天都在重写沙漠,而脚印只需要负责记录此刻。</p></article>
</section>
</main>
</body>
</html>