You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为作品集网站实现非对称按钮的悬停缩放推挤动画?

问题分析与解决方案

你要实现的非对称按钮悬停放大+推挤交互,纯CSS可实现基础效果,但要完美复刻精细的动态逻辑,结合JavaScript会更灵活可控。先看你现有代码的核心问题:2x2等大Grid没有非对称布局,推挤逻辑仅覆盖hover元素后的兄弟节点,scale变换会导致元素重叠。


一、纯CSS优化方案(适合基础需求)

先调整Grid为非对称布局,针对每个位置的按钮单独编写hover规则,用transform-origin控制放大原点,避免偏移。

修改后的CSS

body, html {
    height: 100%;
    margin: 0;
    padding: 20px;
    box-sizing: border-box;
}
  
.container {
    display: grid;
    height: 100%;
    /* 非对称布局:第一列/行占比更大 */
    grid-template-columns: 1.2fr 0.8fr;
    grid-template-rows: 1.2fr 0.8fr;
    gap: 15px;
    position: relative;
}
  
.button {
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: #f0f0f0;
    border-radius: 8px;
    overflow: hidden;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    position: relative;
    z-index: 0;
}
  
.button button {
    width: 100%;
    height: 100%;
    border: none;
    background: transparent;
    font-size: 1.2rem;
    cursor: pointer;
}

/* 左上按钮:向右下放大,推挤右下两个按钮 */
.button:nth-child(1):hover {
    transform: scale(1.1);
    z-index: 1;
    transform-origin: top left;
}
.button:nth-child(1):hover ~ .button:nth-child(2) {
    transform: translateX(10%);
}
.button:nth-child(1):hover ~ .button:nth-child(3) {
    transform: translateY(10%);
}
.button:nth-child(1):hover ~ .button:nth-child(4) {
    transform: translate(10%, 10%);
}

/* 右上按钮:向左下放大,推挤左下两个按钮 */
.button:nth-child(2):hover {
    transform: scale(1.1);
    z-index: 1;
    transform-origin: top right;
}
.button:nth-child(2):hover ~ .button:nth-child(3) {
    transform: translate(-10%, 10%);
}
.button:nth-child(2):hover ~ .button:nth-child(4) {
    transform: translateY(10%);
}

/* 左下按钮:向右上放大,推挤右上两个按钮 */
.button:nth-child(3):hover {
    transform: scale(1.1);
    z-index: 1;
    transform-origin: bottom left;
}
.button:nth-child(3):hover ~ .button:nth-child(4) {
    transform: translateX(10%);
}
.button:nth-child(1):not(:hover) {
    transform: translateX(-10%);
}
.button:nth-child(2):not(:hover) {
    transform: translate(-10%, -10%);
}

/* 右下按钮:向左上放大,推挤左上两个按钮 */
.button:nth-child(4):hover {
    transform: scale(1.1);
    z-index: 1;
    transform-origin: bottom right;
}
.button:nth-child(1):not(:hover) {
    transform: translate(-10%, -10%);
}
.button:nth-child(2):not(:hover) {
    transform: translateY(-10%);
}
.button:nth-child(3):not(:hover) {
    transform: translateX(-10%);
}

.container:hover .button:not(:hover) {
    transition-delay: 0s;
}

纯CSS局限:代码冗余,推挤距离固定,响应式适配繁琐。


二、JavaScript增强方案(完美复刻推荐)

用JS监听hover事件,动态计算每个按钮的推挤方向与距离,实现更自然的交互逻辑。

HTML(无需修改)

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Portifólio João Pedro</title>
        
        <link rel="stylesheet" href="style.css">
    </head>
    <body>
        <div class="container">
            <div class="button">
              <button>Botão 1</button>
            </div>
            <div class="button">
              <button>Botão 2</button>
            </div>
            <div class="button">
              <button>Botão 3</button>
            </div>
            <div class="button">
              <button>Botão 4</button>
            </div>
          </div>
          <script src="script.js"></script>
    </body>
</html>

CSS(简化基础样式)

body, html {
    height: 100%;
    margin: 0;
    padding: 20px;
    box-sizing: border-box;
}
  
.container {
    display: grid;
    height: 100%;
    grid-template-columns: 1.2fr 0.8fr;
    grid-template-rows: 1.2fr 0.8fr;
    gap: 15px;
    position: relative;
}
  
.button {
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: #f0f0f0;
    border-radius: 8px;
    overflow: hidden;
    transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), z-index 0.3s;
    position: relative;
    z-index: 0;
}
  
.button button {
    width: 100%;
    height: 100%;
    border: none;
    background: transparent;
    font-size: 1.2rem;
    cursor: pointer;
}

.button.hovered {
    transform: scale(1.1);
    z-index: 1;
}

JavaScript(核心交互逻辑)

const container = document.querySelector('.container');
const buttons = document.querySelectorAll('.button');

buttons.forEach(btn => {
    btn.addEventListener('mouseenter', (e) => {
        const hoverBtn = e.currentTarget;
        hoverBtn.classList.add('hovered');
        
        const hoverRect = hoverBtn.getBoundingClientRect();
        
        buttons.forEach(otherBtn => {
            if (otherBtn === hoverBtn) return;
            
            const otherRect = otherBtn.getBoundingClientRect();
            // 计算相对中心位置的偏移
            const dx = (otherRect.left + otherRect.width/2) - (hoverRect.left + hoverRect.width/2);
            const dy = (otherRect.top + otherRect.height/2) - (hoverRect.top + hoverRect.height/2);
            
            // 根据方向设置推挤距离
            let tx = dx > 0 ? 10 : dx < 0 ? -10 : 0;
            let ty = dy > 0 ? 10 : dy < 0 ? -10 : 0;
            
            otherBtn.style.transform = `translate(${tx}%, ${ty}%)`;
        });
    });
    
    btn.addEventListener('mouseleave', () => {
        buttons.forEach(b => {
            b.classList.remove('hovered');
            b.style.transform = '';
        });
    });
});

JS方案优势:动态计算推挤方向,代码可扩展性强,响应式适配更灵活,能完美匹配参考网站的交互细节。


内容的提问来源于stack exchange,提问作者NotprQn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 12:49:56