🚀 Flex布局实战:打造点击膨胀的动态卡片!🔥

244 阅读5分钟

🧩 项目背景:当CSS遇上魔法

想象你有一盒乐高积木,现在要搭建一个会变魔术的展示台,点击某个积木它就会突然膨胀,其他积木自动闪开——这就是我们今天要实现的Expanding Cards项目!

屏幕录制 2025-06-02 170236.gif

🧠 核心知识点大揭秘

🌈 弹性布局的魔法咒语(Flex布局)

✨ 居中大法:两招搞定

body {
  display: flex; /* 开启弹性布局 */
  align-items: center; /* 纵轴居中 */
  justify-content: center; /* 主轴居中 */
  height: 100vh; /* 占满屏幕高度 */
}

类比:就像在舞池中央放一个旋转木马,所有元素自动被吸附到中心!🎉

dc066c26cec331a235e78657852cda5.png

🧱 容器与子元素的默契配合

.container {
  display: flex; /* 一行排开 */
  width: 90vw; /* 占90%视口宽度 */
}

.qq-panel {
  flex: 0.5; /* 初始平均分配 */
  transition: all 700ms ease-in; /* 添加魔法特效 */
}

小贴士flex就像给每个卡片装上了弹簧,点击时弹簧突然伸长!💥

image.png

🧪 相对单位的魔法:100vh

height: 100vh; /* 占满屏幕高度 */

场景:无论你是用手机📱还是电脑🖥️,卡片都会完美贴合屏幕高度!

image.png

🎨 过渡效果:让元素优雅起舞

transition: all 700ms ease-in;

比喻:就像给卡片穿上滑轮鞋,动作变得丝滑流畅!⛸️

image.png

🧩 BEM命名规范:给元素戴名牌

<div class="qq-panel">
  <h3 class="qq-panel__title">标题</h3>
</div>

好处:代码就像给每个角色发了身份证,再也不怕命名混乱啦!🆔

image.png

🤖 JS魔法:让卡片活起来

panel.addEventListener('click', () => {
  console.log('biubiubiu'); // 控制台撒花
  removeActiveClasses(); 
  panel.classList.add("qq-panel_active");
});

彩蛋:点击卡片会触发"biubiubiu"的控制台烟花秀!🎇

image.png

🧾 完整代码源码(可直接复制运行)

文档小剧场:虽然有些文档链接可能像消失的魔法一样无法访问,但我们的代码已经完整打包,直接复制就能运行!🎉

📁 1. HTML结构文件(index.html)

<!DOCTYPE html>
<html lang="en">
  <head>
    <!-- 设置字符编码为UTF-8 -->
    <meta charset="UTF-8" />
    <!-- 设置视口,确保移动端正确显示 -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!-- 引入外部样式表 -->
    <link rel="stylesheet" href="common.css" />
    <title>Expanding Cards</title>
  </head>
  <body>
    <!-- 主容器 -->
    <div class="container">
      <!-- 第一个面板:默认激活状态 -->
      <div class="qq-panel qq-panel_active" style="background-image: url('https://images.unsplash.com/photo-1558979158-65a1eaa08691?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80')">
        <h3 class="qq-panel__title">Explore The World</h3>
      </div>
      <!-- 第二个面板:森林主题 -->
      <div class="qq-panel" style="background-image: url('https://images.unsplash.com/photo-1572276596237-5db2c3e16c5d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80')">
        <h3 class="qq-panel__title">Wild Forest</h3>
      </div>
      <!-- 第三个面板:海滩主题 -->
      <div class="qq-panel" style="background-image: url('https://images.unsplash.com/photo-1507525428034-b723cf961d3e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1353&q=80')">
        <h3 class="qq-panel__title">Sunny Beach</h3>
      </div>
      <!-- 第四个面板:冬季城市主题 -->
      <div class="qq-panel" style="background-image: url('https://images.unsplash.com/photo-1551009175-8a68da93d5f9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1351&q=80')">
        <h3 class="qq-panel__title">City on Winter</h3>
      </div>
      <!-- 第五个面板:山脉云海主题 -->
      <div class="qq-panel" style="background-image: url('https://images.unsplash.com/photo-1549880338-65ddcdfd017b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80')">
        <h3 class="qq-panel__title">Mountains - Clouds</h3>
      </div>
    </div>
    <!-- 引入JavaScript文件 -->
    <script src="common.js"></script>
  </body>
</html>

7843d86fd59e6125968fc2158fa1ff5.png

🎨 2. CSS魔法阵(common.css)

/* 全局样式重置 */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* 页面主体样式 */
body {
    display: flex; /* 弹性布局 pad 手机 布局 flex  */
    align-items: center; /* 垂直居中对齐 */
    justify-content: center; /* 水平居中对齐 */
    height: 100vh;/* vh 相对单位 viewport height 一屏高度100vh, 等比例划分*/
    overflow: hidden;/* 超出隐藏 */
    /* background-color: green; */
}

/* 容器样式 */
.container {
    display: flex;/* 弹性布局 格式化上下文 */
    width: 90vw; /* 90% viewport width 视口宽度 */
}

/* 面板基础样式 */
.qq-panel {
    height: 80vh; /* 设置面板高度为视口高度的80% */
    border-radius: 50px; /* 圆角边框 */
    color: #fff; /* 文字颜色为白色 */
    cursor: pointer; /* 鼠标悬停时显示手型光标 */
    margin: 10px; /* 外边距 */
    position: relative; /* 相对定位,用于内部元素定位 */
    flex: 0.5; /* 默认占据空间比例 */
    transition: all 700ms ease-in;/*过渡效果 元素样式改变后 */
}

/* 面板标题样式 */
.qq-panel__title {
    font-size: 24px; /* 标题字体大小 */
    position: absolute; /* 绝对定位 */
    bottom: 20px; /* 距离底部20px */
    left: 20px; /* 距离左侧20px */
    opacity: 0; /* 默认不可见 */
}

/* 激活状态的面板样式 */
.qq-panel_active {
    flex: 5; /* 激活时占据更多空间 */
}

/* 激活状态下的标题样式 */
.qq-panel_active .qq-panel__title {
    opacity: 1; /* 激活时显示标题 */
    transition: opacity 0.3s ease-in 0.4s; /* 标题淡入动画 */
}

48ec6bbc32cf40d1fc4d95044a37e17.png

🤖 3. JS魔法书(common.js)

// 获取所有面板元素
const panels = document.querySelectorAll('.qq-panel');

// 为每个面板添加点击事件监听器
panels.forEach(panel => {
    // JS 是事件机制的语言
    // 每一个元素上监听
    panel.addEventListener('click', () => {
        console.log('biubiubiu');
        removeActiveClasses(); //模块化
        panel.classList.add("qq-panel_active");
    })
})

/**
 * 移除所有面板的激活状态
 * 这是一个模块化的函数,用于重置所有面板的状态
 */
function removeActiveClasses() {
    panels.forEach(panel => {
        panel.classList.remove('qq-panel_active');
    })
}

fcff8aee1c52da9afa683e10d317cd1.png


🖼️ 页面展示模块(效果预览)

🎬 动态效果演示

  1. 初始状态

image.png

五个卡片整齐排列,等待你的点击魔法!

  1. 点击某个卡片后

屏幕录制 2025-06-02 170818.gif

被点击的卡片像气球一样膨胀,其他卡片自动退位让贤!

🧪 效果演示:点击卡片的魔法时刻

  1. 点击任意卡片,它会像吹气球一样膨胀🎈
  2. 其他卡片会优雅地缩回原位
  3. 标题文字会像从魔法盒里跳出来✨
  4. 控制台还会出现神秘的"biubiubiu"烟花秀🎇

🚀 学习建议:让知识生根发芽

  1. 动手实践:试着修改flex值,看看卡片如何变化
  2. 代码调试:在控制台添加console.log,观察点击事件的触发过程
  3. 扩展玩法
    • 给卡片添加阴影效果
    • 尝试不同的过渡动画
    • 添加音效增强交互体验

🎁 开发者小秘密

你知道吗?100vh在某些设备上可能会有小bug,可以试试calc(100vh - 1px)来规避~ 😜

📚 知识点总结

技术点说明使用场景
Flex布局灵活的响应式布局方案手机/PC适配
BEM命名结构清晰的命名规范复杂项目维护
100vh单位占满屏幕高度全屏展示
transition光滑的过渡效果交互增强
JS事件控制动态变化用户交互

🚀 最后

通过这个项目,我们不仅掌握了弹性布局的精髓,还学会了如何用CSS和JS创造惊艳的用户体验。记住:前端开发就像魔法,CSS是咒语,JS是魔杖!🧙‍♂️

image.png