
本文详解如何基于 html/css/js 构建一个语义清晰、动画平滑、布局自适应的可折叠蓝色卡片组件,解决常见“内容覆盖”“高度塌陷”“定位错位”等问题,支持点击切换、箭头旋转与内容自然延展。
本文详解如何基于 html/css/js 构建一个语义清晰、动画平滑、布局自适应的可折叠蓝色卡片组件,解决常见“内容覆盖”“高度塌陷”“定位错位”等问题,支持点击切换、箭头旋转与内容自然延展。
在实际开发中,将 .rectangle 设计为 标签虽具语义(导航意图),但其默认 display: inline 行为与绝对定位(position: absolute)结合时,会严重干扰父容器(.tile-container)的 flex 布局流,导致后续 .hidden-text 无法正确跟随高度变化而延展——它被强制“压”在固定高度的锚点下方,甚至因 position: absolute 脱离文档流而悬浮覆盖内容。
✅ 正确解法是:改用 以下为优化后的完整实现(已通过实测验证):✅ 推荐方案:Grid 驱动 + 类名控制 + 纯 CSS 动画
<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=PT+Sans+Narrow:wght@400;700&display=swap" rel="stylesheet"><style>
.tile-container {
padding: 5px;
font-size: 25px; /* 基准字号,子元素用 em 继承 */
max-width: 600px;
margin: 0 auto;
}
.rectangle {
background-color: #0051a5;
border-radius: 1em;
cursor: pointer;
display: grid;
/* 定义网格区域:标题区、加号区、隐藏内容区 */
grid-template-areas:
"sample plus"
"extratext extratext";
grid-template-rows: 1fr auto; /* 标题占满剩余空间,隐藏内容初始隐藏 */
grid-template-columns: 1fr max-content;
overflow: hidden; /* 关键!防止展开时内容溢出破坏动画 */
transition: grid-template-rows 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.rectangle.expanded {
grid-template-rows: 1fr max-content; /* 展开后第二行显式分配空间 */
}
.plus {
grid-area: plus;
width: 1.2em;
height: 1.2em;
margin: 0.5em;
background:
linear-gradient(#fff 0 0),
linear-gradient(#fff 0 0),
#0051a5;
background-position: center;
background-size: 60% 2px, 2px 60%;
background-repeat: no-repeat;
transition: transform 0.3s ease;
border-radius: 50%;
}
.rectangle.expanded .plus {
transform: rotate(45deg);
}
.tile-label {
grid-area: sample;
font-family: 'PT Sans Narrow', sans-serif;
font-size: 1em;
text-transform: uppercase;
font-weight: 700;
color: #fff;
padding: 0.8em 1em 0.5em;
align-self: end; /* 底部对齐,避免随内容拉伸 */
}
.tile-accent {
color: #FFC72C;
}
.hidden-text {
grid-area: extratext;
font-family: 'PT Sans Narrow', sans-serif;
font-size: 0.75em;
color: #333;
background-color: #fff;
padding: 0.75em 1em;
margin: 0 0.5em;
border-top: 1px solid #e0e0e0;
opacity: 0;
transform: translateY(-10px);
transition:
opacity 0.25s ease,
transform 0.25s ease,
height 0.25s ease;
}
.rectangle.expanded .hidden-text {
opacity: 1;
transform: translateY(0);
height: auto;
}
/* 可选:增强可访问性 */
.rectangle:focus {
outline: 2px solid #4d90fe;
outline-offset: 2px;
}
</style><div class="tile-container">
<div class="rectangle">
<div class="plus"></div>
<div class="tile-label">
Sample <span class="tile-accent">Text</span>
</div>
<div class="hidden-text">
<ul style="margin: 0; padding-left: 1.5em;">
<li>Item 1 — 支持任意长度文本</li>
<li>Item 2 — 自动适配行高与内边距</li>
<li>Item 3 — 无高度硬编码,完全响应式</li>
</ul>
</div>
</div>
</div>
<script>
document.querySelector('.rectangle').addEventListener('click', function() {
this.classList.toggle('expanded');
// 可选:添加键盘支持(Enter/Space)
this.setAttribute('aria-expanded', this.classList.contains('expanded'));
});
// 无障碍增强:为屏幕阅读器提供语义
const rect = document.querySelector('.rectangle');
rect.setAttribute('role', 'button');
rect.setAttribute('tabindex', '0');
rect.setAttribute('aria-expanded', 'false');
rect.setAttribute('aria-label', '点击展开或收起详情内容');
</script>
? 关键设计要点说明











