10分钟实现高颜值扩展卡片交互:零基础玩转CSS动效

278 阅读5分钟

前言

本文将详细讲解如何实现一个优雅的扩展卡片(Expanding Cards)组件,这是GitHub上流行的"50 Projects in 50 Days"系列中的经典案例。通过HTML、CSS和JavaScript的配合,我们将实现卡片点击后平滑展开的视觉效果,同时学习现代前端开发中的布局技术和交互设计思想。

image.png

项目结构与实现步骤

1. HTML结构设计

首先,让我们查看完整的HTML代码:

<!DOCTYPE html>
<html lang="en">
  <head>
    <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>
    <script src="common.js"></script>
  </body>
</html>

HTML结构采用了以下设计原则:

  1. 语义化结构:使用合适的HTML5标签构建页面框架

  2. BEM命名规范:采用Block-Element-Modifier命名方式组织CSS类名

    • qq-panel:组件的块级元素
    • qq-panel__title:标题作为面板的子元素
    • qq-panel_active:表示激活状态的修饰符
  3. 初始激活状态:第一个卡片默认添加qq-panel_active类,确保页面加载时就有展示效果

  4. 背景图片内联:直接在HTML中通过style属性设置背景图片,简化实现

  5. 外部资源链接:分离CSS和JavaScript,便于代码维护

2. CSS样式实现

CSS布局采用现代弹性盒模型和相对单位实现响应式设计:

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100vh;
    overflow: hidden;
}

.container {
    display: flex;
    width: 90vw;
}

.qq-panel {
    height: 80vh;
    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;
    left: 20px;
    opacity: 0;
}

.qq-panel_active {
    flex: 5;
}

.qq-panel_active .qq-panel__title {
    opacity: 1;
    transition: opacity 0.3s ease-in 0.4s;
}

3. JavaScript交互逻辑

交互逻辑通过简洁的事件监听和DOM操作实现:

const panels = document.querySelectorAll('.qq-panel');

panels.forEach(panel => {
    panel.addEventListener('click', () => {
        removeActiveClasses();
        panel.classList.add('qq-panel_active');
    })
})

function removeActiveClasses() {
    panels.forEach(panel => {
        panel.classList.remove('qq-panel_active');
    })
}

技术要点深入分析

1. display属性详解

display属性是CSS布局的基础,它定义了元素的显示类型与行为:

  • block:块级元素,默认占据一行
  • inline:行内元素,在文本流中显示
  • inline-block:结合了行内和块级特性
  • flex:弹性布局,一维布局系统
  • grid:网格布局,二维布局系统
  • none:元素不显示且不占空间

在本项目中,我们使用了display: flex创建弹性布局上下文:

body {
    display: flex; /* 弹性布局,移动端时代的布局主流方式 */
    align-items: center; /* 纵轴居中 */
    justify-content: center; /* 主轴居中 */
    height: 100vh;
}

.container {
    display: flex; /* 子元素水平排列,不会换行 */
    width: 90vw;
}

弹性布局的优势在于:

  • 容器能自动调整子元素大小
  • 简化垂直居中等常见布局难题
  • 响应式设计更加简洁
  • 减少媒体查询的使用

2. 相对单位系统

相对单位是响应式设计的核心,本项目使用了以下相对单位:

  • vh (viewport height):视口高度的百分比

    body {
        height: 100vh; /* 占满整个视口高度 */
    }
    .qq-panel {
        height: 80vh; /* 占视口高度的80% */
    }
    
  • vw (viewport width):视口宽度的百分比

    .container {
        width: 90vw; /* 占视口宽度的90% */
    }
    

相对单位的优势:

  • 自适应不同屏幕大小
  • 保持设计比例一致
  • 减少媒体查询代码
  • 简化响应式实现

3. Flex布局与动态比例

组件的核心交互效果通过flex属性值的变化实现:

.qq-panel {
    flex: 0.5; /* 初始状态下的收缩比例 */
    transition: all 700ms ease-in; /* 过渡效果 */
}

.qq-panel_active {
    flex: 5; /* 激活状态下的扩展比例 */
}

通过改变flex值(从0.5到5)创造出卡片展开的视觉效果,配合transition属性实现平滑过渡。

4. 层次化动画效果

标题显示采用了延迟过渡效果,创造层次感:

.qq-panel__title {
    opacity: 0; /* 初始状态隐藏 */
}

.qq-panel_active .qq-panel__title {
    opacity: 1;
    transition: opacity 0.3s ease-in 0.4s; /* 0.4秒延迟显示 */
}

这种延迟效果让用户先看到卡片展开,再看到标题文字显示,增强了交互的艺术性和期待感。

用户体验设计考量

项目在用户体验方面的精心设计:

  1. 视觉和谐

    • 圆角设计(border-radius: 50px)柔化视觉边界
    • 统一的图片风格营造连贯体验
  2. 交互反馈

    • 鼠标悬停时的指针变化(cursor: pointer)提示可点击
    • 点击后的平滑过渡给予用户直观反馈
  3. 动效节奏

    • 展开动画(700ms)和标题显示(300ms延迟400ms)形成富有韵律的体验链
    • 避免所有元素同时变化,创造高级感

实现要点总结

  1. 语义化HTML结构与BEM命名规范提升代码可维护性
  2. 弹性布局实现元素间的动态比例关系
  3. 相对单位确保跨设备一致性体验
  4. CSS过渡效果设计达到视觉层次感
  5. JavaScript事件机制实现简洁的交互逻辑
  6. 模块化函数设计提高代码可读性和可维护性

实践启示

这个扩展卡片组件看似简单,却融合了多项前端核心技术与设计理念。从中我们可以学习到:

  1. 优秀的UI组件往往建立在简洁代码基础上
  2. 精心设计的过渡效果能显著提升用户体验
  3. 相对单位和弹性布局是响应式设计的基础
  4. 前端交互设计需要考虑动效的层次感和时间节奏

通过掌握这些技术和设计思想,我们能够在实际项目中创造出既美观又实用的前端组件,为用户带来"尖叫"级别的交互体验。