HTML&CSS:3D 轮播图全攻略

这个 HTML 文件实现了一个具有 3D 效果的团队成员轮播展示页面,支持多种交互方式切换成员信息。


大家复制代码时,可能会因格式转换出现错乱,导致样式失效。建议先少量复制代码进行测试,若未能解决问题,私信回复源码两字,我会发送完整的压缩包给你。

演示效果

HTML&CSS

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>微信公众号:前端Hardy</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
        }

        body {
            min-height: 100vh;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            background-color: #f5f5f5;
            overflow: hidden;
        }

        .about-title {
            font-size: 7.5rem;
            font-weight: 900;
            text-transform: uppercase;
            letter-spacing: -0.02em;
            position: absolute;
            top: 45px;
            left: 50%;
            transform: translateX(-50%);
            pointer-events: none;
            white-space: nowrap;
            font-family: "Arial Black", "Arial Bold", Arial, sans-serif;
            background: linear-gradient(to bottom,
                    rgb(8 42 123 / 35%) 30%,
                    rgb(255 255 255 / 0%) 76%);
            -webkit-background-clip: text;
            background-clip: text;
            color: transparent;
        }

        .carousel-container {
            width: 100%;
            max-width: 1200px;
            height: 450px;
            position: relative;
            perspective: 1000px;
            margin-top: 80px;
        }

        .carousel-track {
            width: 100%;
            height: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
            position: relative;
            transform-style: preserve-3d;
            transition: transform 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94);
        }

        .card {
            position: absolute;
            width: 280px;
            height: 380px;
            background: white;
            border-radius: 20px;
            overflow: hidden;
            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
            transition: all 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94);
            cursor: pointer;
        }

        .card img {
            width: 100%;
            height: 100%;
            object-fit: cover;
            transition: all 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94);
        }

        .card.center {
            z-index: 10;
            transform: scale(1.1) translateZ(0);
        }

        .card.center img {
            filter: none;
        }

        .card.left-2 {
            z-index: 1;
            transform: translateX(-400px) scale(0.8) translateZ(-300px);
            opacity: 0.7;
        }

        .card.left-2 img {
            filter: grayscale(100%);
        }

        .card.left-1 {
            z-index: 5;
            transform: translateX(-200px) scale(0.9) translateZ(-100px);
            opacity: 0.9;
        }

        .card.left-1 img {
            filter: grayscale(100%);
        }

        .card.right-1 {
            z-index: 5;
            transform: translateX(200px) scale(0.9) translateZ(-100px);
            opacity: 0.9;
        }

        .card.right-1 img {
            filter: grayscale(100%);
        }

        .card.right-2 {
            z-index: 1;
            transform: translateX(400px) scale(0.8) translateZ(-300px);
            opacity: 0.7;
        }

        .card.right-2 img {
            filter: grayscale(100%);
        }

        .card.hidden {
            opacity: 0;
            pointer-events: none;
        }

        .member-info {
            text-align: center;
            margin-top: 40px;
            transition: all 0.5s ease-out;
        }

        .member-name {
            color: rgb(8, 42, 123);
            font-size: 2.5rem;
            font-weight: 700;
            margin-bottom: 10px;
            position: relative;
            display: inline-block;
        }

        .member-name::before,
        .member-name::after {
            content: "";
            position: absolute;
            top: 100%;
            width: 100px;
            height: 2px;
            background: rgb(8, 42, 123);
        }

        .member-name::before {
            left: -120px;
        }

        .member-name::after {
            right: -120px;
        }

        .member-role {
            color: #848696;
            font-size: 1.5rem;
            font-weight: 500;
            opacity: 0.8;
            text-transform: uppercase;
            letter-spacing: 0.1em;
            padding: 10px 0;
            margin-top: -15px;
            position: relative;
        }

        .dots {
            display: flex;
            justify-content: center;
            gap: 10px;
            margin-top: 60px;
        }

        .dot {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            background: rgba(8, 42, 123, 0.2);
            cursor: pointer;
            transition: all 0.3s ease;
        }

        .dot.active {
            background: rgb(8, 42, 123);
            transform: scale(1.2);
        }

        .nav-arrow {
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            background: rgba(8, 42, 123, 0.6);
            color: white;
            width: 40px;
            height: 40px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            z-index: 20;
            transition: all 0.3s ease;
            font-size: 1.5rem;
            border: none;
            outline: none;
            padding-bottom: 4px;
        }

        .nav-arrow:hover {
            background: rgba(0, 0, 0, 0.8);
            transform: translateY(-50%) scale(1.1);
        }

        .nav-arrow.left {
            left: 20px;
            padding-right: 3px;
        }

        .nav-arrow.right {
            right: 20px;
            padding-left: 3px;
        }

        @media (max-width: 768px) {
            .about-title {
                font-size: 4.5rem;
            }

            .card {
                width: 200px;
                height: 280px;
            }

            .card.left-2 {
                transform: translateX(-250px) scale(0.8) translateZ(-300px);
            }

            .card.left-1 {
                transform: translateX(-120px) scale(0.9) translateZ(-100px);
            }

            .card.right-1 {
                transform: translateX(120px) scale(0.9) translateZ(-100px);
            }

            .card.right-2 {
                transform: translateX(250px) scale(0.8) translateZ(-300px);
            }

            .member-name {
                font-size: 2rem;
            }

            .member-role {
                font-size: 1.2rem;
            }

            .member-name::before,
            .member-name::after {
                width: 50px;
            }

            .member-name::before {
                left: -70px;
            }

            .member-name::after {
                right: -70px;
            }
        }
    </style>
</head>

<body>
    <h1 class="about-title">OUR TEAM</h1>

    <div class="carousel-container">
        <button class="nav-arrow left">‹</button>
        <div class="carousel-track">
            <div class="card" data-index="0">
                <img src="https://images.unsplash.com/photo-1573497019940-1c28c88b4f3e?q=80&w=3687&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
                    alt="Team Member 1">
            </div>
            <div class="card" data-index="1">
                <img src="https://images.unsplash.com/photo-1568602471122-7832951cc4c5?q=80&w=3870&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
                    alt="Team Member 2">
            </div>
            <div class="card" data-index="2">
                <img src="https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=900&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8M3x8cHJvZmVzc2lvbmFsJTIwcGVvcGxlfGVufDB8fDB8fHww"
                    alt="Team Member 3">
            </div>
            <div class="card" data-index="3">
                <img src="https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=900&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8N3x8cHJvZmVzc2lvbmFsJTIwcGVvcGxlfGVufDB8fDB8fHww"
                    alt="Team Member 4">
            </div>
            <div class="card" data-index="4">
                <img src="https://images.unsplash.com/photo-1655249481446-25d575f1c054?w=900&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mjh8fHByb2Zlc3Npb25hbCUyMHBlb3BsZXxlbnwwfHwwfHx8MA%3D%3D"
                    alt="Team Member 5">
            </div>
            <div class="card" data-index="5">
                <img src="https://images.unsplash.com/photo-1519085360753-af0119f7cbe7?q=80&w=3687&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
                    alt="Team Member 6">
            </div>
        </div>
        <button class="nav-arrow right">›</button>
    </div>

    <div class="member-info">
        <h2 class="member-name">David Kim</h2>
        <p class="member-role">Founder</p>
    </div>

    <div class="dots">
        <div class="dot active" data-index="0"></div>
        <div class="dot" data-index="1"></div>
        <div class="dot" data-index="2"></div>
        <div class="dot" data-index="3"></div>
        <div class="dot" data-index="4"></div>
        <div class="dot" data-index="5"></div>
    </div>
    <script>
        const teamMembers = [
            { name: "Emily Kim", role: "Founder" },
            { name: "Michael Steward", role: "Creative Director" },
            { name: "Emma Rodriguez", role: "Lead Developer" },
            { name: "Julia Gimmel", role: "UX Designer" },
            { name: "Lisa Anderson", role: "Marketing Manager" },
            { name: "James Wilson", role: "Product Manager" }
        ];

        const cards = document.querySelectorAll(".card");
        const dots = document.querySelectorAll(".dot");
        const memberName = document.querySelector(".member-name");
        const memberRole = document.querySelector(".member-role");
        const leftArrow = document.querySelector(".nav-arrow.left");
        const rightArrow = document.querySelector(".nav-arrow.right");
        let currentIndex = 0;
        let isAnimating = false;

        function updateCarousel(newIndex) {
            if (isAnimating) return;
            isAnimating = true;

            currentIndex = (newIndex + cards.length) % cards.length;

            cards.forEach((card, i) => {
                const offset = (i - currentIndex + cards.length) % cards.length;

                card.classList.remove(
                    "center",
                    "left-1",
                    "left-2",
                    "right-1",
                    "right-2",
                    "hidden"
                );

                if (offset === 0) {
                    card.classList.add("center");
                } else if (offset === 1) {
                    card.classList.add("right-1");
                } else if (offset === 2) {
                    card.classList.add("right-2");
                } else if (offset === cards.length - 1) {
                    card.classList.add("left-1");
                } else if (offset === cards.length - 2) {
                    card.classList.add("left-2");
                } else {
                    card.classList.add("hidden");
                }
            });

            dots.forEach((dot, i) => {
                dot.classList.toggle("active", i === currentIndex);
            });

            memberName.style.opacity = "0";
            memberRole.style.opacity = "0";

            setTimeout(() => {
                memberName.textContent = teamMembers[currentIndex].name;
                memberRole.textContent = teamMembers[currentIndex].role;
                memberName.style.opacity = "1";
                memberRole.style.opacity = "1";
            }, 300);

            setTimeout(() => {
                isAnimating = false;
            }, 800);
        }

        leftArrow.addEventListener("click", () => {
            updateCarousel(currentIndex - 1);
        });

        rightArrow.addEventListener("click", () => {
            updateCarousel(currentIndex + 1);
        });

        dots.forEach((dot, i) => {
            dot.addEventListener("click", () => {
                updateCarousel(i);
            });
        });

        cards.forEach((card, i) => {
            card.addEventListener("click", () => {
                updateCarousel(i);
            });
        });

        document.addEventListener("keydown", (e) => {
            if (e.key === "ArrowLeft") {
                updateCarousel(currentIndex - 1);
            } else if (e.key === "ArrowRight") {
                updateCarousel(currentIndex + 1);
            }
        });

        let touchStartX = 0;
        let touchEndX = 0;

        document.addEventListener("touchstart", (e) => {
            touchStartX = e.changedTouches[0].screenX;
        });

        document.addEventListener("touchend", (e) => {
            touchEndX = e.changedTouches[0].screenX;
            handleSwipe();
        });

        function handleSwipe() {
            const swipeThreshold = 50;
            const diff = touchStartX - touchEndX;

            if (Math.abs(diff) > swipeThreshold) {
                if (diff > 0) {
                    updateCarousel(currentIndex + 1);
                } else {
                    updateCarousel(currentIndex - 1);
                }
            }
        }

        updateCarousel(0);

    </script>
</body>

</html>

HTML

  • about-title:页面标题。
  • carousel-container:包含轮播图的容器。
  • nav-arrow left:左箭头导航按钮。
  • carousel-track:轮播图轨道。
  • card元素:每个卡片代表一个团队成员,包含图片和数据索引。
  • nav-arrow right:右箭头导航按钮。
  • member-info:显示当前团队成员的信息。
  • member-name:成员姓名。
  • member-role:成员角色。 -dots:包含指示点的容器,每个点对应一个团队成员。

CSS

  • 全局样式:* 选择器重置默认样式,设置字体族和盒模型。
  • body:设置页面整体布局,背景色,以及 Flexbox 布局。
  • .about-title:定义页面标题的样式,包括字体大小、渐变色等。
  • .carousel-container:设置轮播图容器的尺寸、位置和透视效果。
  • .carousel-track:设置轮播图轨道的布局和过渡效果。
  • .card:定义卡片的基本样式,包括尺寸、背景色、阴影等。
  • 不同状态的卡片(如 .center、.left-1 等):定义卡片在不同位置的变换样式。
  • .member-info:设置成员信息的样式,包括文本对齐和过渡效果。
  • .member-name:定义成员姓名的样式,包括字体、颜色等。
  • .member-role:定义成员角色的样式。
  • .dots:设置指示点容器的样式。
  • .dot:定义指示点的样式,包括形状、颜色等。
  • .nav-arrow:定义导航箭头的样式,包括位置、颜色、过渡效果等。
  • 响应式样式:@media (max-width: 768px) 为小屏幕设备调整样式。

各位互联网搭子,要是这篇文章成功引起了你的注意,别犹豫,关注、点赞、评论、分享走一波,让我们把这份默契延续下去,一起在知识的海洋里乘风破浪!

相关推荐
小小小小宇38 分钟前
前端Loader笔记
前端
烛阴2 小时前
从0到1掌握盒子模型:精准控制网页布局的秘诀
前端·javascript·css
前端工作日常5 小时前
我理解的`npm pack` 和 `npm install <local-path>`
前端
李剑一5 小时前
说个多年老前端都不知道的标签正确玩法——q标签
前端
嘉小华5 小时前
大白话讲解 Android屏幕适配相关概念(dp、px 和 dpi)
前端
姑苏洛言5 小时前
在开发跑腿小程序集成地图时,遇到的坑,MapContext.includePoints(Object object)接口无效在组件中使用无效?
前端
奇舞精选5 小时前
Prompt 工程实用技巧:掌握高效 AI 交互核心
前端·openai
Danny_FD5 小时前
React中可有可无的优化-对象类型的使用
前端·javascript
用户757582318556 小时前
混合应用开发:企业降本增效之道——面向2025年移动应用开发趋势的实践路径
前端
P1erce6 小时前
记一次微信小程序分包经历
前端