指尖上的时光博物馆:用 CSS 实现交互式记忆展柜

一、雨夜中的回忆盒子

窗外的雨点击打在玻璃上,我蜷在沙发里翻着旧硬盘。光标停在 "2020 年夏" 的文件夹上,指尖突然触到一丝凉意 ------ 那是巴厘岛海水的温度,是东京居酒屋的烟火气,是布拉格广场的玫瑰香。我突然想做一个「时光展柜」,让这些瞬间能在点击间绽放成立体的故事。

🌊 场景还原:当点击遇见记忆

html 复制代码
<div class="container">
    <!-- 初始状态:五张卡片像被压缩的时间胶囊 -->
    <div class="panel active" style="background-image:url('https://picsum.photos/id/1018/1200/800')">
        <h3>Explore the World</h3>
    </div>
    <div class="panel" style="background-image:url('https://picsum.photos/id/292/1200/800')">
        <h3>Have a good dinner</h3>
    </div>
    <!-- 更多卡片... -->
</div>

当鼠标点击那张海洋主题的卡片时,它突然从窄条膨胀成巨幕 ------ 浪花声仿佛透过屏幕传来,2019 年在巴厘岛潜水的记忆瞬间被点亮:珊瑚群在阳光下折射出蓝绿色光斑,教练打手势让我看游过的海龟... 其他卡片则谦逊地退到两侧,像博物馆里等待观赏的展品。

二、技术拆解:让静态图片拥有呼吸感

这个交互效果的核心,是 CSS 弹性布局与过渡动画的默契配合:

1. 卡片的「呼吸」机制

css 复制代码
.panel {
    flex: 0.5; /* 初始宽度占比 */
    transition: flex 0.7s ease-in; /* 0.7秒缓动展开 */
}
.panel.active {
    flex: 5; /* 激活后宽度扩大10倍 */
}

就像老式相机的暗箱,卡片在flex: 0.5到flex: 5的变化中,从「缩略图」变为「巨幕」。ease-in缓动函数让展开过程像拉开窗帘般自然 ------ 开始缓慢,逐渐加速,最后轻柔定格。

2. 文字的「浮现」魔法

css 复制代码
.panel h3 {
    opacity: 0; /* 初始隐藏 */
}
.panel.active h3 {
    opacity: 1;
    transition: opacity 0.3s ease-in 0.4s; /* 0.4秒后淡入 */
}

标题文字的出现藏着小心机:在卡片展开 0.4 秒后才开始淡入。这个延迟让视觉焦点先被图片抓住,再自然过渡到文字叙事,就像电影镜头从全景慢慢推到字幕。

三、适配不同屏幕的「时光机」

当我在手机上打开这个页面时,发现最后两张卡片自动隐藏了 ------ 这是代码里的「屏幕魔法」:

css 复制代码
@media(max-width: 480px) {
    .panel:nth-of-type(4),
    .panel:nth-of-type(5) {
        display: none; /* 小屏幕隐藏后两张卡片 */
    }
}

就像老式相册会根据页数自动调整厚度,响应式设计让展柜在不同设备上都能完美呈现。在地铁上用手机浏览时,手指点击卡片的瞬间,狭窄的屏幕会突然「膨胀」出整个世界。

四、从技术到故事:交互设计的灵魂

这个看似简单的效果,藏着交互设计的核心逻辑:让操作成为故事的入口。当用户点击卡片时,不是在触发代码,而是在「打开」一段记忆 ------ 就像小时候打开奶奶的木箱,每一次掀开盖子,都有樟脑丸香气和旧毛衣里掉出的糖纸。

你可以用它做:

  • 旅行博客的「目的地展厅」,点击城市卡片展开行程故事
  • 美食公众号的「菜谱墙」,点击菜品图片弹出做法
  • 个人简历的「项目展示」,点击卡片展开作品详情
javascript 复制代码
const panels = document.querySelectorAll('.panel');
panels.forEach(panel => {
    panel.addEventListener('click', () => {
        removeActiveClasses(); // 先关闭所有卡片
        panel.classList.add('active'); // 再打开当前卡片
    });
});

这段 JavaScript 像极了博物馆的管理员:当你走进一个展厅,它会轻轻关上其他展室的门,让你能专注欣赏眼前的故事。

尾声:让代码成为记忆的容器

雨还在下,但硬盘里的旧照片已经有了新的生命。这个用 CSS 和 JavaScript 搭建的「时光展柜」,让我明白技术最美的样子不是炫技,而是成为情感的载体。就像此刻,当我点击那张海洋图片,2019 年的阳光依然能穿过代码,照亮现实里的雨夜。

五、完整代码

html 复制代码
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Expanding Card Effect</title>
    <style>
        @import url('https://fonts.googleapis.com/css2?family=Muli&display=swap');
        *{
            box-sizing: border-box;
        }
        body {
            font-family: 'Muli', sans-serif;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100vh;
            overflow: hidden;
            margin: 0;
        }

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

        .panel {
            background-size: auto 100%;
            background-position: center;
            background-repeat: no-repeat;
            height: 80vh;
            border-radius: 50px;
            color: #fff;
            cursor: pointer;
            flex:0.5;
            margin: 10px;
            position: relative;
            transition: flex 0.7s ease-in;
        }

        .panel h3{
            font-size: 24px;
            position: absolute;
            bottom: 20px;
            left: 20px;
            margin: 0;
            opacity: 0;
        }

        .panel.active {
            flex: 5;
        }

        .panel.active h3 {
            opacity: 1;
            transition: opacity 0.3s ease-in 0.4s;
        }

        @media(max-width: 480px) {
            .container {
                width:100vw;
            }
            .panel:nth-of-type(4),
            .panel:nth-of-type(5) {
                display: none;
            }
        }
    </style>
</head>
<body>
<div class="container">
    <!-- 使用在线图片替代本地图片 -->
    <div class="panel active" style="background-image:url('https://picsum.photos/id/1018/1200/800')">
        <h3>Explore the World</h3>
    </div>
    <div class="panel" style="background-image:url('https://picsum.photos/id/292/1200/800')">
        <h3>Have a good dinner</h3>
    </div>
    <div class="panel" style="background-image:url('https://picsum.photos/id/431/1200/800')">
        <h3>Drink some tea for happy!</h3>
    </div>
    <div class="panel" style="background-image:url('https://picsum.photos/id/1025/1200/800')">
        <h3>See the beautiful things!</h3>
    </div>
    <div class="panel" style="background-image:url('https://picsum.photos/id/325/1200/800')">
        <h3>Let's Play!</h3>
    </div>
</div>
<script>
    const panels = document.querySelectorAll('.panel');
    panels.forEach((panel)=>{
        panel.addEventListener('click',()=>{
            removeActiveClasses();
            panel.classList.add('active')
        })
    })

    function removeActiveClasses(){
        panels.forEach(panel=>{
            panel.classList.remove('active');
        })
    }
</script>
</body>
</html>
相关推荐
超人不会飛39 分钟前
就着HTTP聊聊SSE的前世今生
前端·javascript·http
蓝胖子的多啦A梦42 分钟前
Vue+element 日期时间组件选择器精确到分钟,禁止选秒的配置
前端·javascript·vue.js·elementui·时间选选择器·样式修改
夏天想1 小时前
vue2+elementui使用compressorjs压缩上传的图片
前端·javascript·elementui
今晚打老虎z1 小时前
dotnet-env: .NET 开发者的环境变量加载工具
前端·chrome·.net
用户3802258598241 小时前
vue3源码解析:diff算法之patchChildren函数分析
前端·vue.js
烛阴1 小时前
XPath 进阶:掌握高级选择器与路径表达式
前端·javascript
小鱼小鱼干1 小时前
【JS/Vue3】关于Vue引用透传
前端
JavaDog程序狗1 小时前
【前端】HTML+JS 实现超燃小球分裂全过程
前端
独立开阀者_FwtCoder1 小时前
URL地址末尾加不加 "/" 有什么区别
前端·javascript·github
独立开阀者_FwtCoder1 小时前
Vue3 新特性:原来watch 也能“暂停”和“恢复”了!
前端·javascript·github