CSS, HTML, JavaScript, سورس کد

سورس کد هاور کارت سه بعدی با CSS و JS (افکت تیلت + کارت چرخشی)

هاور کارت سه بعدی با جاوا اسکریپت - طاووس وب
زمان مطالعه: ۷ دقیقهسطح: مبتدی تا متوسطسورس کد رایگان
خلاصه در یک نگاه
  • دو مدل آماده: کارت تیلت که با حرکت ماوس در سه بعد می‌چرخد و کارت دو رو (Flip) که روی هاور برمی‌گردد.
  • پایهٔ هر دو، سه ویژگی CSS است: perspective، transform-style: preserve-3d و translateZ.
  • کارت تیلت فقط ۱۵ خط جاوااسکریپت خالص دارد و به jQuery یا Vue نیازی ندارد.
  • برای موبایل و کاربرانی که انیمیشن را خاموش کرده‌اند، نسخهٔ جایگزین در نظر گرفته شده است.

هاور کارت سه بعدی یکی از ساده‌ترین راه‌ها برای زنده کردن بخش نمونه‌کار، معرفی تیم یا پلن‌های قیمت است. در این مطلب از طاووس وب دو مدل کاربردی را با کد کامل می‌سازیم: کارتی که با حرکت ماوس کج می‌شود و یک لایهٔ براق روی آن حرکت می‌کند، و کارتی دو رو که با هاور یا لمس برمی‌گردد و پشتش توضیحات را نشان می‌دهد. نسخهٔ اولیهٔ این سورس را هم می‌توانید در پیش‌نمایش قدیمی ببینید؛ کدی که اینجا می‌خوانید بازنویسی سبک‌تر و بدون وابستگی به فریم‌ورک است.

دموی زنده هاور کارت سه بعدی

ماوس را روی کارت‌ها حرکت دهید

کارت تیلت

کارت با حرکت ماوس در دو محور می‌چرخد و عنوان و دکمه با فاصله‌های مختلف از سطح کارت جلو می‌آیند.

نمونه‌کار ↗
کارت دو رو

روی کارت بروید یا لمسش کنید.

پشت کارت

اینجا توضیح، قیمت یا لینک قرار می‌گیرد. کد این کارت

روی موبایل، کارت دو رو با لمس برمی‌گردد و کارت تیلت ثابت می‌ماند تا اسکرول مختل نشود.

افکت سه بعدی در CSS چطور ساخته می‌شود؟

مرورگر به‌طور پیش‌فرض همه‌چیز را تخت می‌کشد. برای اینکه چرخش یک کارت «عمق» داشته باشد، سه چیز لازم است:

  1. perspective روی والدفاصلهٔ فرضی چشم بیننده تا صفحه را مشخص می‌کند. عدد کمتر (مثلاً ۵۰۰px) یعنی عمق اغراق‌شده‌تر؛ عدد بیشتر (۱۲۰۰px) یعنی حرکت ملایم‌تر. ما ۹۰۰px را انتخاب کرده‌ایم.
  2. transform-style: preserve-3d روی کارتبدون این ویژگی، فرزندان کارت در سطح آن «پرس» می‌شوند و translateZ اثری ندارد.
  3. translateZ روی لایه‌هابه عنوان، متن و دکمه فاصله‌های متفاوت (۳۰ تا ۷۰ پیکسل) می‌دهیم تا هنگام چرخش، جابه‌جایی لایه‌ها (Parallax) دیده شود.

جاوااسکریپت فقط موقعیت ماوس روی کارت را به دو متغیر CSS یعنی --rx و --ry تبدیل می‌کند؛ خود چرخش را CSS انجام می‌دهد. همین جداسازی باعث می‌شود کد کوتاه، خوانا و روان باشد.

کد کامل کارت تیلت (HTML، CSS و JS)

ساختار HTML ساده است؛ یک والد برای perspective و خود کارت. لایهٔ glare همان درخشش متحرک است:

<div class="card-scene">
  <div class="tilt-card" tabindex="0">
    <div class="glare"></div>
    <h3>عنوان کارت</h3>
    <p>توضیح کوتاه دربارهٔ پروژه یا محصول.</p>
    <a class="badge" href="#">مشاهده</a>
  </div>
</div>

در CSS، زاویهٔ چرخش از متغیرها خوانده می‌شود و هر لایه با translateZ جلو می‌آید:

.card-scene { perspective: 900px; }

.tilt-card {
  position: relative;
  height: 280px;
  padding: 24px;
  border-radius: 22px;
  color: #fff;
  background: linear-gradient(145deg, #8224E3, #5F01AF 60%, #2B0A47);
  transform-style: preserve-3d;
  transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: transform .15s ease-out;
  overflow: hidden;
}
.tilt-card h3    { transform: translateZ(50px); }
.tilt-card p     { transform: translateZ(30px); }
.tilt-card .badge{ transform: translateZ(70px); }

.tilt-card .glare {
  position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(circle at var(--gx,50%) var(--gy,50%),
              rgba(255,255,255,.35), transparent 55%);
  opacity: 0; transition: opacity .3s;
}
.tilt-card:hover .glare { opacity: 1; }

و جاوااسکریپت، که فقط روی دستگاه‌های دارای ماوس فعال می‌شود:

const card = document.querySelector('.tilt-card');
const canHover = matchMedia('(hover: hover)').matches;
const reduce = matchMedia('(prefers-reduced-motion: reduce)').matches;

if (card && canHover && !reduce) {
  const MAX = 9; // حداکثر زاویه به درجه
  card.addEventListener('mousemove', (e) => {
    const r = card.getBoundingClientRect();
    const x = (e.clientX - r.left) / r.width;   // 0 تا 1
    const y = (e.clientY - r.top) / r.height;   // 0 تا 1
    card.style.setProperty('--ry', `${(x - .5) * MAX * 2}deg`);
    card.style.setProperty('--rx', `${(.5 - y) * MAX * 2}deg`);
    card.style.setProperty('--gx', `${x * 100}%`);
    card.style.setProperty('--gy', `${y * 100}%`);
  });
  card.addEventListener('mouseleave', () => {
    card.style.setProperty('--rx', '0deg');
    card.style.setProperty('--ry', '0deg');
  });
}

اگر چند کارت دارید، به‌جای querySelector از querySelectorAll و یک حلقهٔ forEach استفاده کنید. عدد MAX را بین ۶ تا ۱۲ نگه دارید؛ زاویهٔ بیشتر خوانایی متن را کم می‌کند.

کد کارت چرخشی دو رو (Flip Card) با CSS خالص

<div class="flip-card" tabindex="0">
  <div class="flip-inner">
    <div class="face front">روی کارت</div>
    <div class="face back">پشت کارت</div>
  </div>
</div>
.flip-card { perspective: 900px; height: 280px; }

.flip-inner {
  position: relative; width: 100%; height: 100%;
  transform-style: preserve-3d;
  transition: transform .7s cubic-bezier(.3,.7,.2,1);
}
.flip-card:hover .flip-inner,
.flip-card:focus-within .flip-inner,
.flip-card.on .flip-inner { transform: rotateY(180deg); }

.face {
  position: absolute; inset: 0;
  border-radius: 22px; padding: 24px;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden; /* سافاری */
}
.front { background: #F3ECFC; }
.back  { background: #2B0A47; color: #fff; transform: rotateY(180deg); }

نکتهٔ کلیدی backface-visibility: hidden است: پشت هر رو را پنهان می‌کند تا وقتی کارت برمی‌گردد، متن آینه‌ای دیده نشود. کلاس on را هم با یک خط جاوااسکریپت روی کلیک اضافه کنید تا کارت روی موبایل با لمس برگردد: card.onclick = () => card.classList.toggle('on').

نکات موبایل، دسترس‌پذیری و سرعت

  • موبایل هاور ندارد. با matchMedia('(hover: hover)') تیلت را فقط برای ماوس فعال کنید و برای کارت دو رو، لمس را جایگزین هاور کنید.
  • کیبورد را فراموش نکنید. tabindex="0" و قاعدهٔ :focus-within باعث می‌شوند کاربر کیبورد هم بتواند پشت کارت را ببیند.
  • به تنظیم کاهش حرکت احترام بگذارید. برای کاربرانی که در سیستم‌عامل «کاهش حرکت» را روشن کرده‌اند، prefers-reduced-motion انیمیشن را حذف می‌کند.
  • فقط transform را انیمیت کنید. تغییر width، top یا box-shadow در هر حرکت ماوس باعث رندر دوباره می‌شود؛ transform روی GPU اجرا می‌شود و روان می‌ماند.
  • در تعداد زیاده‌روی نکنید. اگر همهٔ عناصر صفحه تکان بخورند، هیچ‌کدام برجسته نیست. افکت را برای کارت‌های مهم نگه دارید.
کاربردهای هاور کارت سه بعدی در طراحی سایت
جاهایی که هاور کارت سه بعدی ارزش افزوده دارد

اگر به افکت‌های سبک دیگر هم علاقه دارید، سورس کد انیمیشن لودینگ و دکمهٔ عضویت در خبرنامه با انیمیشن را هم ببینید. برای یادگیری چیدمان کارت‌ها کنار هم، آموزش CSS Grid بهترین نقطهٔ شروع است.

می‌خواهید نمونه‌کارهایتان حرفه‌ای‌تر دیده شوند؟طاووس وب صفحهٔ نمونه‌کار و لندینگ را با افکت‌های سبک و سریع، متناسب با برند شما طراحی می‌کند.

طراحی لندینگ پیج

سؤالات متداول هاور کارت سه بعدی

آیا هاور کارت سه بعدی سرعت سایت را کم می‌کند؟

خیر، به شرط اینکه فقط transform انیمیت شود. کد این مطلب هیچ کتابخانه‌ای بارگذاری نمی‌کند و حجم آن کمتر از دو کیلوبایت است.

این کد در وردپرس و المنتور کار می‌کند؟

بله. HTML را در ابزارک HTML المنتور یا بلوک HTML سفارشی بگذارید، CSS را در بخش CSS سفارشی و جاوااسکریپت را در فوتر سایت یا همان ابزارک اضافه کنید.

چرا کارت در سافاری درست برنمی‌گردد؟

معمولاً پیشوند -webkit-backface-visibility جا افتاده یا یکی از والدها overflow: hidden دارد که preserve-3d را خنثی می‌کند.

چطور زاویهٔ چرخش را کمتر کنم؟

در جاوااسکریپت عدد MAX را کم کنید یا مقدار perspective را بیشتر کنید (مثلاً ۱۲۰۰px) تا حرکت ملایم‌تر شود.

آیا به Vue یا jQuery نیاز دارم؟

نه. نسخهٔ قدیمی این سورس با Vue نوشته شده بود، اما نسخهٔ این مطلب با جاوااسکریپت خالص کار می‌کند.

دانلود از گیت هاب ناشر سورس کد

دانلود فایل

پسورد فایل : ندارد

author-avatar

درباره مهدی حبیبی

مهدی حبیبی، بنیان‌گذار طاووس وب و برنامه‌نویس فرانت‌اند با بیش از ۵ سال تجربه در طراحی سایت و بیش از ۵۰ پروژهٔ انجام‌شده. تخصصش وردپرس، المنتور، ووکامرس، سئو و بهینه‌سازی سرعت است و تجربهٔ پروژه‌های واقعی را در طاووس وب به زبان ساده آموزش می‌دهد. و البته مجنون قهوه!

  1. حمید رضایی گفت:

    سلام وقت شما بخیر
    این سورس کد رو باید چطور ازش استفاده کنیم؟یعنی کجای سایت قرارش بدیم؟

    1. وقت شماهم بخیر
      بستگی داره کجا بخوای ازش استفاده کنی. تو المنتور میتونی تو قسمت HTML Block استفاده کنی ازش و با چت جی پی تی اختصاصی سازیش کنی.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *