تاروپود — خودآموز HTML و CSS

فصل ۶ از ۱۰

پیشرفت ترم
۰٪

ترم ۵ · تعامل و جزئیات

transform

فصل ۶پیش‌نمایش رایگان
۸ دقیقه مطالعه فصل ۶

در این فصل چه می‌سازی#

آخر این فصل یک ردیف کارت داری که وقتی موس رویشان می‌رود، زنده می‌شوند: کارت کمی بالا می‌پرد، بزرگ‌تر می‌شود و کمی کج می‌ایستد — مثل کارتی که از میز بلند شده تا خودش را نشان بدهد. ابزارِ این کار یک property تازه است به اسم transform: با آن یک عنصر را جابه‌جا می‌کنی، بزرگ و کوچک می‌کنی، یا می‌چرخانی، بی‌آنکه HTML را دست بزنی.

یک ردیف سه کارت که کارتِ وسط با موس بزرگ‌تر و کمی کج شده و از دو کارتِ کناری بالاتر آمده، ولی جای اصلی‌اش در ردیف هنوز محفوظ است

آخر این فصل می‌توانی:

  • با transform یک عنصر را جابه‌جا، بزرگ یا بچرخانی
  • فرقِ translate()، scale() و rotate() را بگویی و درست را انتخاب کنی
  • با transform-origin نقطهٔ چرخش یا بزرگ‌شدن را عوض کنی
  • توضیح بدهی چرا transform فقط ظاهر را عوض می‌کند، نه جای واقعیِ عنصر در چیدمان

قبل از شروع#

  • از ترم ۳: display: flex و gap — ردیفِ کارت‌ها را با همین می‌سازیم.
  • از فصل ۱ (همین ترم): :hover — همهٔ حرکت‌ها را روی همین حالت سوار می‌کنیم.
  • از ترم ۲: padding، border-radius و رنگ.

مثل همیشه فقط یک مرورگر لازم داری، یا فقط همین آزمایشگاه.

۱. transform و scale(): بزرگ کردن#

بیا اول ردیفِ کارت‌ها را بسازیم. HTML یک <main> است با سه <article>، چون هر کارت یک تکهٔ مستقل است:

<main class="row">
  <article class="card">یک</article>
  <article class="card">دو</article>
  <article class="card">سه</article>
</main>

و استایلِ پایه: کارت‌ها را با flexbox کنارِ هم می‌چینیم.

.row {
  display: flex;
  gap: 16px;
}

.card {
  flex: 1;
  padding: 32px;
  background-color: #2a6b93;
  color: #ffffff;
  text-align: center;
  border-radius: 8px;
}

حالا اولین transform. می‌خواهیم کارت با موس بزرگ‌تر شود. برای این از تابعِ scale() استفاده می‌کنیم: scale(1.1) یعنی «۱٫۱ برابرِ اندازهٔ اصلی». این را روی :hover بگذار:

.card:hover {
  transform: scale(1.1);
}

چک کن: موس را روی یک کارت ببر — بزرگ می‌شود، و موس را که برداری به اندازهٔ اصلی برمی‌گردد. حالا خوب دقت کن: وقتی کارت بزرگ می‌شود، کمی روی کارت‌های کناری می‌آید، ولی آن‌ها ذره‌ای جابه‌جا نمی‌شوند و سرِ جایشان می‌مانند. این نکته را به خاطر بسپار؛ در بخش ۵ همین رفتار، هم قلبِ ماجراست و هم یک تلهٔ رایج.

قبل از ادامه، جواب بده: scale(1) چه می‌کند؟ و scale(0.5) چه؟


جواب: scale(1) یعنی همان اندازهٔ اصلی، هیچ تغییری نمی‌دهد. scale(0.5) یعنی نصفِ اندازه — کارت کوچک می‌شود. عددِ بزرگ‌تر از ۱ بزرگ می‌کند، کوچک‌تر از ۱ کوچک.

۲. translate(): جابه‌جا کردن#

تابعِ بعدی translate() است: عنصر را از جای خودش جابه‌جا می‌کند. دو مقدار می‌گیرد — جابه‌جاییِ افقی و عمودی — ولی یک نسخهٔ ساده‌ترش هم داریم: translateY() فقط عمودی، و translateX() فقط افقی. برای اینکه کارت با موس کمی «بالا بپرد»، از translateY() با یک عددِ منفی استفاده می‌کنیم (منفی یعنی به بالا):

.card:hover {
  transform: translateY(-8px);
}

چک کن: حالا موس که روی کارت برود، کارت ۸ پیکسل بالا می‌پرد. عدد را به -20px عوض کن تا بالاتر بپرد، بعد به 10px تا به‌جایش پایین برود. با چشمت جهتِ منفی و مثبت را ببین.

۳. rotate(): چرخاندن#

تابعِ سوم rotate() است: عنصر را می‌چرخاند. مقدارش با واحدِ deg (درجه) نوشته می‌شود — 360deg یک دورِ کامل است. برای یک کجیِ ملایم، مقدارِ کوچک بده:

.card:hover {
  transform: rotate(-5deg);
}

چک کن: کارت با موس کمی کج می‌شود. عددِ منفی خلافِ عقربهٔ ساعت می‌چرخاند، مثبت با عقربهٔ ساعت. rotate(5deg) را امتحان کن و فرقِ جهت را ببین. حواست باشد کارت دورِ مرکزِ خودش می‌چرخد — این را در بخش بعد عوض می‌کنیم.

قبل از ادامه، جواب بده: rotate(360deg) روی یک کارت چه اثری دارد که با چشم دیده شود؟


جواب: هیچ. 360deg یک دورِ کامل است و کارت دقیقاً به جای اول برمی‌گردد، پس ظاهرش عوض‌شده به‌نظر نمی‌رسد. (اگر همین کارت transition داشت، خودِ مسیرِ چرخیدن را می‌دیدی — ولی آن فصلِ بعد است.)

۴. transform-origin: نقطهٔ چرخش را عوض کن#

هر transform یک نقطهٔ لنگر دارد که کار حولِ آن انجام می‌شود، و پیش‌فرضش مرکزِ عنصر است. برای همین rotate() دورِ وسط می‌چرخید و scale() از وسط بزرگ می‌شد. با transform-origin این نقطه را عوض می‌کنی. مثلاً بگو چرخش از پایینِ کارت باشد، انگار کارت روی لبهٔ پایینی‌اش ایستاده و کج می‌شود:

.card:hover {
  transform: rotate(-5deg);
  transform-origin: bottom center;
}

چک کن: حالا کارت به‌جای چرخیدن دورِ وسط، از لبهٔ پایینش کج می‌شود. مقدارها را عوض کن: top center، بعد bottom right. هر بار ببین لنگر کجا می‌رود و چرخش چطور فرق می‌کند.

💡 نکته: می‌توانی چند تابع را در یک transform پشتِ هم بگذاری، با فاصله: transform: translateY(-8px) scale(1.05) rotate(-2deg);. مرورگر همه را با هم اعمال می‌کند. همین را در کدِ کاملِ آخر به‌کار می‌بریم.

۵. یک تلهٔ مهم: transform فقط ظاهر است#

حالا مهم‌ترین نکتهٔ این فصل. فرض کن نمی‌خواهی با موس، بلکه می‌خواهی کارتِ وسط را همیشه کمی بالاتر از بقیه نشان بدهی تا برجسته باشد. وسوسه می‌شوی که مستقیم به یک کارت translate بدهی. بیا موقتاً این را امتحان کنیم — به کارتِ وسط یک class بده و بنویس:

.card:nth-child(2) {
  transform: translateY(-40px);
}

کارتِ وسط ۴۰ پیکسل بالا می‌رود — ولی یک چیزِ عجیب هم می‌بینی: جای خالیِ کارت در ردیف هنوز آنجاست، و کارت‌های کناری ذره‌ای برای پر کردنش تکان نمی‌خورند. انگار کارت از جایش بلند شده ولی سایه‌اش سرِ جا مانده.

🔧 اگر کار نکرد: انتظار داشتی بقیهٔ کارت‌ها جابه‌جا شوند و آن جای خالی پر شود، ولی نشد؟ این خرابی نیست — این دقیقاً کارِ transform است. transform فقط ظاهرِ عنصر را در لحظهٔ نقاشی جابه‌جا می‌کند؛ جای واقعیِ عنصر در چیدمان سرِ جای اولش می‌ماند و همان‌قدر فضا اشغال می‌کند. برای همین همسایه‌ها خبردار نمی‌شوند. اگر واقعاً می‌خواهی چیدمان عوض شود و همسایه‌ها جابه‌جا شوند، ابزارش margin است نه transform. آن قاعدهٔ :nth-child(2) را پاک کن.

و این ضعف نیست؛ دقیقاً همان چیزی است که transform را برای حرکت‌های :hover عالی می‌کند. چون کارت هنگام بزرگ‌شدن یا پریدن جای واقعی‌اش را عوض نمی‌کند، بقیهٔ صفحه سرِ جا می‌ماند و هیچ‌چیز نمی‌پرد و جابه‌جا نمی‌شود. تصور کن اگر هر بار موس روی یک کارت می‌رفت، کلِ صفحه تکان می‌خورد — افتضاح بود. transform همین را حل می‌کند.

کد کامل#

این هم دو فایلِ کامل. اول index.html:

<!-- index.html -->
<!DOCTYPE html>
<html lang="fa" dir="rtl">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>transform</title>
    <link rel="stylesheet" href="styles.css">
  </head>
  <body>
    <main class="row">
      <article class="card">یک</article>
      <article class="card">دو</article>
      <article class="card">سه</article>
    </main>
  </body>
</html>

و styles.css — حالا هر سه تابع را در یک transform با هم می‌گذاریم: کارت هم‌زمان بالا می‌پرد، بزرگ می‌شود و کمی کج می‌ایستد، با لنگرِ پایین:

/* styles.css */
* {
  box-sizing: border-box;
}

body {
  background-color: #f6edda;
  padding: 32px;
}

.row {
  display: flex;
  gap: 16px;
}

.card {
  flex: 1;
  padding: 32px;
  background-color: #2a6b93;
  color: #ffffff;
  text-align: center;
  border-radius: 8px;
}

.card:hover {
  transform: translateY(-8px) scale(1.05) rotate(-2deg);
  transform-origin: bottom center;
}

یک کارت که با موس بالا آمده و کمی کج شده، در حالی که جای اصلی‌اش در ردیف با یک قابِ کم‌رنگ نشان داده شده تا معلوم شود فضایش هنوز محفوظ است

چک کن: موس را روی هر کارت ببر — با هم بالا می‌پرد، بزرگ می‌شود و از لبهٔ پایین کج می‌ایستد. و همان‌طور که فهمیدی، هیچ‌کدام از کارت‌های دیگر برای این حرکت جابه‌جا نمی‌شوند.

🤖 با AI: از دستیار AI ات بپرس «چطور یک کارت را با CSS کمی بزرگ‌تر و کج کنم وقتی موس رویش می‌رود؟». جوابش را خط‌به‌خط بخوان و در آزمایشگاه امتحانش کن — بعد از خودش بپرس «آیا این حرکت جای کارت را در چیدمان عوض می‌کند یا فقط ظاهرش را؟». چیزی که با چشمت در آزمایشگاه می‌بینی، جوابِ واقعی است، نه چیزی که AI با اطمینان می‌گوید.

واژه‌های تازهٔ این فصل#

کلمه تلفظ به حروف فارسی یعنی چه
transform ترنسفورم property ای که ظاهرِ یک عنصر را جابه‌جا، بزرگ یا می‌چرخاند
translate() ترنسلِیت عنصر را جابه‌جا می‌کند (translateX/translateY فقط یک محور)
scale() اسکِیل عنصر را بزرگ یا کوچک می‌کند؛ عدد بزرگ‌تر از ۱ بزرگ، کوچک‌تر کوچک
rotate() روتِیت عنصر را می‌چرخاند؛ مقدار با واحدِ deg
transform-origin ترنسفورم-اوریجین نقطهٔ لنگرِ چرخش و بزرگ‌شدن؛ پیش‌فرض مرکز است

تمرین‌ها

اول خودت فکر کن یا امتحان کن — بعد اینجا را باز کن.

در فصل بعد#

الان کارت‌هایت با موس حرکت می‌کنند — ولی این حرکت‌ها ناگهانی‌اند؛ کارت یک‌دفعه می‌پرد و یک‌دفعه برمی‌گردد. فصل بعد سراغِ transition می‌رویم: یاد می‌گیری این جهش‌ها را نرم و آرام کنی، طوری که کارت در طولِ چند دهمِ ثانیه بزرگ شود، نه در یک چشم‌به‌هم‌زدن. همین transform را برمی‌داریم و روان‌ترش می‌کنیم.

به آخر این فصل رسیدی!

اگر ساختی و جواب داد، این دکمه مال توست.