React图片手风琴悬停效果优化:展开方向与收缩逻辑咨询
手风琴式图片悬停效果优化方案
需求与问题
我开发了一个包含3张图片的React应用,想要实现:
- 当前图片悬停展开时,其余图片收缩
- 中间图片悬停时双向向左右展开,左右图片分别向对应方向收缩(而非统一左向右)
但当前实现中图片展开会遮挡其余图片,需要解决这个问题。
修改后的React代码
import React, { useState } from "react"; import "./styles.css"; export default function App() { const [hoveredIndex, setHoveredIndex] = useState(null); const imageUrls = [ "https://images.unsplash.com/photo-1682686581551-867e0b208bd1?q=80&w=1470&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", "https://images.unsplash.com/photo-1697219590638-d2db7748802e?q=80&w=1452&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", "https://images.unsplash.com/photo-1682686581427-7c80ab60e3f3?q=80&w=1470&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", ]; return ( <div className="accordion-container"> {imageUrls.map((imageUrl, index) => ( <div key={index} className={`accordion-item ${hoveredIndex === index ? "active" : ""} ${ index === 0 ? "left-item" : index === 1 ? "middle-item" : "right-item" }`} onMouseEnter={() => setHoveredIndex(index)} onMouseLeave={() => setHoveredIndex(null)} > <div className="image-wrapper"> <img src={imageUrl} alt={`Image ${index + 1}`} /> </div> </div> ))} </div> ); }
修改后的CSS代码
.accordion-container { display: flex; width: 1000px; height: 720px; margin: 150px auto; position: relative; overflow: hidden; border-radius: 25px; } .accordion-item { flex: 1; position: relative; transition: flex 0.5s ease; overflow: hidden; } .image-wrapper { width: 100%; height: 100%; position: absolute; top: 0; transition: all 0.5s ease; } .image-wrapper img { width: 100%; height: 100%; object-fit: cover; } /* 非激活项统一收缩 */ .accordion-container:hover .accordion-item:not(.active) { flex: 0.15; } /* 激活项展开 */ .accordion-item.active { flex: 2.7; } /* 左侧项激活:右侧项向右收缩隐藏 */ .left-item.active ~ .right-item { transform: translateX(100%); } /* 右侧项激活:自身向左展开,左侧项向左收缩隐藏 */ .right-item.active { transform: translateX(-100%); } .right-item.active ~ .left-item { transform: translateX(-100%); } /* 中间项激活:双向展开,左右项分别向两侧收缩隐藏 */ .middle-item.active { flex: 3; } .middle-item.active ~ .right-item { transform: translateX(100%); } .left-item:not(.active):has(+ .middle-item.active) { transform: translateX(-100%); }
关键改动说明
- 容器布局重构:使用
flex布局的容器替代原有的分散结构,通过flex属性精确控制各图片项的宽度占比,避免绝对定位导致的遮挡问题 - 方向逻辑实现:为左、中、右三个图片项分别添加专属类名,利用CSS相邻兄弟选择器和
transform属性,实现不同项激活时的定向收缩效果 - 过渡效果优化:通过
flex和transform的组合过渡,实现平滑的展开/收缩动画,同时利用容器的overflow: hidden隐藏收缩后超出的部分
内容的提问来源于stack exchange,提问作者Sougata Mukherjee
相关产品推荐
相关产品推荐

