用TRAE sole实现css按钮切换动画的背景左右滑动的效果

43 阅读5分钟

大家好,我的开源项目PakePlus可以将网页/Vue/React项目打包为桌面/手机应用并且小于5M只需几分钟,官网地址:pakeplus.com

思路分析

  • 使用伪元素创建滑动背景

  • 通过CSS过渡实现平滑动画

  • 利用CSS选择器控制不同状态下的位置

  • 添加悬停效果增强交互体验

.toggle-container {
    display: flex;
    background: rgba(0, 0, 0, 0.2);
    border-radius: 50px;
    padding: 5px;
    position: relative;
}

.toggle-option {
    flex: 1;
    text-align: center;
    padding: 12px 0;
    color: white;
    cursor: pointer;
    position: relative;
    z-index: 2;
}

.toggle-bg {
    position: absolute;
    top: 5px;
    left: 5px;
    height: calc(100% - 10px);
    width: calc(50% - 5px);
    background: linear-gradient(90deg, #ff8a00, #e52e71);
    border-radius: 50px;
    transition: all 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}

.toggle-container.option2 .toggle-bg {
    left: calc(50% + 0px);
    background: linear-gradient(90deg, #00b4db, #0083b0);
}

实现原理

  • 使用flex布局创建两个等宽的按钮选项
  • 通过绝对定位的伪元素.toggle-bg作为滑动背景
  • 利用CSS过渡实现平滑的左右滑动动画
  • 通过添加/移除.option2类来切换背景位置
  • 使用cubic-bezier缓动函数增强动画效果

全部代码:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>按钮切换动画 - 背景左右滑动</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
            padding: 20px;
        }
        
        .container {
            width: 100%;
            max-width: 800px;
            background: rgba(255, 255, 255, 0.1);
            backdrop-filter: blur(10px);
            border-radius: 20px;
            padding: 40px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
            border: 1px solid rgba(255, 255, 255, 0.2);
        }
        
        h1 {
            color: white;
            text-align: center;
            margin-bottom: 10px;
            font-weight: 600;
            font-size: 2.5rem;
        }
        
        .subtitle {
            color: rgba(255, 255, 255, 0.8);
            text-align: center;
            margin-bottom: 40px;
            font-size: 1.1rem;
        }
        
        .demo-section {
            background: rgba(255, 255, 255, 0.1);
            border-radius: 15px;
            padding: 30px;
            margin-bottom: 30px;
        }
        
        .toggle-container {
            display: flex;
            background: rgba(0, 0, 0, 0.2);
            border-radius: 50px;
            padding: 5px;
            position: relative;
            margin: 20px 0;
            width: 300px;
            margin-left: auto;
            margin-right: auto;
        }
        
        .toggle-option {
            flex: 1;
            text-align: center;
            padding: 12px 0;
            color: white;
            font-weight: 500;
            cursor: pointer;
            position: relative;
            z-index: 2;
            transition: color 0.3s ease;
        }
        
        .toggle-bg {
            position: absolute;
            top: 5px;
            left: 5px;
            height: calc(100% - 10px);
            width: calc(50% - 5px);
            background: linear-gradient(90deg, #ff8a00, #e52e71);
            border-radius: 50px;
            transition: all 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
        }
        
        /* 当第二个选项被选中时,背景滑动到右侧 */
        .toggle-container.option2 .toggle-bg {
            left: calc(50% + 0px);
            background: linear-gradient(90deg, #00b4db, #0083b0);
        }
        
        /* 悬停效果 */
        .toggle-option:hover {
            color: rgba(255, 255, 255, 0.9);
        }
        
        .code-container {
            background: #1e1e1e;
            border-radius: 10px;
            padding: 20px;
            color: #d4d4d4;
            font-family: 'Courier New', monospace;
            overflow-x: auto;
            margin-top: 20px;
        }
        
        .code-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
            color: #ccc;
        }
        
        .code-title {
            font-size: 1rem;
            font-weight: 500;
        }
        
        .copy-btn {
            background: #007acc;
            color: white;
            border: none;
            padding: 5px 10px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 0.8rem;
            transition: background 0.3s;
        }
        
        .copy-btn:hover {
            background: #005a9e;
        }
        
        .explanation {
            color: white;
            margin-top: 30px;
            line-height: 1.6;
        }
        
        .explanation h3 {
            margin-bottom: 10px;
            color: #ffcc00;
        }
        
        .explanation ul {
            margin-left: 20px;
            margin-bottom: 15px;
        }
        
        .highlight {
            color: #ffcc00;
            font-weight: 500;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>按钮切换动画</h1>
        <p class="subtitle">背景左右滑动效果实现</p>
        
        <div class="demo-section">
            <div class="toggle-container" id="toggleContainer">
                <div class="toggle-option" data-option="1">选项一</div>
                <div class="toggle-option" data-option="2">选项二</div>
                <div class="toggle-bg"></div>
            </div>
        </div>
        
        <div class="code-container">
            <div class="code-header">
                <div class="code-title">CSS 实现代码</div>
                <button class="copy-btn" id="copyBtn">复制代码</button>
            </div>
            <pre id="codeSnippet">
.toggle-container {
    display: flex;
    background: rgba(0, 0, 0, 0.2);
    border-radius: 50px;
    padding: 5px;
    position: relative;
}

.toggle-option {
    flex: 1;
    text-align: center;
    padding: 12px 0;
    color: white;
    cursor: pointer;
    position: relative;
    z-index: 2;
}

.toggle-bg {
    position: absolute;
    top: 5px;
    left: 5px;
    height: calc(100% - 10px);
    width: calc(50% - 5px);
    background: linear-gradient(90deg, #ff8a00, #e52e71);
    border-radius: 50px;
    transition: all 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}

.toggle-container.option2 .toggle-bg {
    left: calc(50% + 0px);
    background: linear-gradient(90deg, #00b4db, #0083b0);
}</pre>
        </div>
        
        <div class="explanation">
            <h3>实现原理</h3>
            <ul>
                <li>使用<strong class="highlight">flex布局</strong>创建两个等宽的按钮选项</li>
                <li>通过<strong class="highlight">绝对定位</strong>的伪元素<strong class="highlight">.toggle-bg</strong>作为滑动背景</li>
                <li>利用<strong class="highlight">CSS过渡</strong>实现平滑的左右滑动动画</li>
                <li>通过添加/移除<strong class="highlight">.option2</strong>类来切换背景位置</li>
                <li>使用<strong class="highlight">cubic-bezier</strong>缓动函数增强动画效果</li>
            </ul>
            <p>这种实现方式简洁高效,仅使用CSS和少量JavaScript即可完成,适合各种现代Web应用。</p>
        </div>
    </div>

    <script>
        const toggleContainer = document.getElementById('toggleContainer');
        const toggleOptions = document.querySelectorAll('.toggle-option');
        const copyBtn = document.getElementById('copyBtn');
        const codeSnippet = document.getElementById('codeSnippet');
        
        // 切换选项
        toggleOptions.forEach(option => {
            option.addEventListener('click', () => {
                const optionValue = option.getAttribute('data-option');
                toggleContainer.className = 'toggle-container';
                if (optionValue === '2') {
                    toggleContainer.classList.add('option2');
                }
            });
        });
        
        // 复制代码功能
        copyBtn.addEventListener('click', () => {
            const textArea = document.createElement('textarea');
            textArea.value = codeSnippet.textContent;
            document.body.appendChild(textArea);
            textArea.select();
            document.execCommand('copy');
            document.body.removeChild(textArea);
            
            // 显示复制成功反馈
            const originalText = copyBtn.textContent;
            copyBtn.textContent = '已复制!';
            setTimeout(() => {
                copyBtn.textContent = originalText;
            }, 2000);
        });
    </script>
</body>
</html>

大家好,我是1024小神,技术群 / 私活群 / 股票群 或 交朋友 都可以私信我。 如果你觉得本文有用,一键三连 (点赞、评论、关注),就是对我最大的支持~