دسترسی سریع


مقایسه جامع Container Queries و Media Queries | طراحی ریسپانسیو مدرن در CSS

مقایسه جامع Container Queries و Media Queries | طراحی ریسپانسیو مدرن در CSS
خلاصه مطلب

Media Queries سال‌ها استاندارد طراحی ریسپانسیو بودند، اما Container Queries انقلابی در این حوزه ایجاد کرده‌اند. در این مقاله، تفاوت‌های این دو رویکرد را یاد می‌گیرید و می‌فهمید کی از کدام استفاده کنید. همراه با ۱۵+ مثال عملی، ساخت ویجت‌های مستقل و پروژه کامل.

مقدمه: محدودیت Media Queries و تولد Container Queries

برای سال‌های طولانی، Media Queries تنها راه طراحی ریسپانسیو بود. اما یک مشکل بزرگ داشت: Media Queries به اندازه صفحه نمایش (viewport) نگاه می‌کند، نه به اندازه المان والد. این یعنی اگر یک کامپوننت (مثل کارت محصول) را در جای مختلف صفحه با عرض‌های مختلف قرار دهید، نمی‌تواند واکنش متفاوتی نشان دهد.

محدودیت Media Queries:

  • یک کارت در سایدبار (عرض ۲۵۰px) و در main (عرض ۸۰۰px) یکسان به نظر می‌رسد

  • کامپوننت‌ها قابل استفاده مجدد در هر جای صفحه نیستند

  • برای هر اندازه صفحه باید جداگانه کد بزنید

راه حل: Container Queries
Container Queries به اندازه المان والد (container) نگاه می‌کند. یعنی یک کامپوننت مستقل از اندازه صفحه، بر اساس جایگاهی که در آن قرار گرفته، استایل متفاوت می‌گیرد.


مقایسه سریع: Media Queries vs Container Queries

ویژگی Media Queries Container Queries
نگاه به اندازه viewport (صفحه نمایش) اندازه المان والد (container)
کاربرد اصلی چیدمان کلی صفحه کامپوننت‌های مستقل
قابلیت استفاده مجدد محدود (به جایگاه وابسته است) بالا (کاملاً مستقل)
ساخت ویجت دشوار بسیار آسان
سینتکس @media (max-width: 768px) @container (max-width: 400px)
پشتیبانی مرورگر کامل (از قدیم) تمام مرورگرهای مدرن از ۲۰۲۳
نیاز به تعریف کانتینر خیر بله (با container-type)

مفاهیم پایه Container Queries (مرور سریع)

ویژگی مقدارهای رایج توضیح
container-type inline-size, block-size, size, normal نوع کانتینر (معمولاً inline-size)
container-name نام دلخواه (مثل sidebar, card) نام‌گذاری کانتینر
@container (min-width: 300px) شرط query
container (مخفف) sidebar / inline-size ترکیب type و name

۱۵+ مثال کاربردی Container Queries در مقایسه با Media Queries

مثال ۱: تفاوت اساسی – Media Queries به کل صفحه نگاه می‌کند

css
/* Media Queries – به کل صفحه نگاه می‌کند */  @media (max-width: 600px) {    .card {      display: block;    }    .card img {      width: 100%;    }  }  @media (min-width: 601px) {    .card {      display: flex;    }    .card img {      width: 200px;    }  }

مشکل: اگر این کارت را در سایدبار ۲۵۰px قرار دهید، باز هم نمایش flex می‌گیرد (چون صفحه بزرگ است) و ظاهر آن خراب می‌شود.

مثال ۲: راه حل با Container Queries – کامپوننت هوشمند

css
/* تعریف کانتینر */  .card-container {    container-type: inline-size;  }     /* Container Queries – به اندازه والد نگاه می‌کند */  @container (max-width: 300px) {    .card {      display: block;    }    .card img {      width: 100%;    }  }  @container (min-width: 301px) {    .card {      display: flex;    }    .card img {      width: 120px;    }  }
html
<!-- این کارت در هر جایی که قرار بگیرد، بر اساس عرض والد خودش رفتار می‌کند -->  <div class="card-container" style="width: 250px;">    <div class="card">      <img src="image.jpg">      <div class="card-content">...</div>    </div>  </div>  <div class="card-container" style="width: 500px;">    <div class="card"> <!-- اینجا flex نمایش داده می‌شود -->      <img src="image.jpg">      <div class="card-content">...</div>    </div>  </div>

مثال ۳: کارت محصول هوشمند – کاملاً مستقل

یک کارت محصول که در عرض‌های مختلف، چیدمان خود را تغییر می‌دهد.

css
.product-container {    container-type: inline-size;    container-name: product;  }  .product-card {    background: white;    border-radius: 12px;    overflow: hidden;    transition: all 0.3s;  }  /* حالت باریک (موبایل داخل سایدبار) */  @container product (max-width: 300px) {    .product-card {      display: block;      text-align: center;    }    .product-image {      width: 100%;      height: 150px;    }    .product-title {      font-size: 16px;    }  }  /* حالت متوسط */  @container product (min-width: 301px) and (max-width: 500px) {    .product-card {      display: flex;      gap: 15px;    }    .product-image {      width: 120px;      height: 120px;    }  }  /* حالت پهن (برای main صفحه) */  @container product (min-width: 501px) {    .product-card {      display: flex;      gap: 20px;    }    .product-image {      width: 200px;      height: 200px;    }    .product-title {      font-size: 24px;    }  }

مثال ۴: ویجت آب و هوا (Weather Widget) – قابلیت استفاده مجدد بالا

یک ویجت که در هدر، سایدبار و فوتر می‌تواند قرار بگیرد و هر بار ظاهر متفاوتی داشته باشد.

css
.weather-container {    container-type: inline-size;    container-name: weather;  }  .weather-widget {    background: linear-gradient(135deg, #667eea, #764ba2);    border-radius: 16px;    padding: 16px;    color: white;  }  /* حالت کوچک (برای سایدبار یا فوتر) */  @container weather (max-width: 200px) {    .weather-widget {      text-align: center;    }    .temp {      font-size: 24px;    }    .details {      display: none; /* جزئیات را مخفی کن */    }  }  /* حالت بزرگ (برای هدر یا main) */  @container weather (min-width: 201px) {    .weather-widget {      display: flex;      justify-content: space-between;      align-items: center;    }    .temp {      font-size: 48px;    }    .details {      display: block;    }  }

مثال ۵: ناوبری (Navbar) که با عرض کانتینر تغییر می‌کند

یک منو که در هدر پهن، همه آیتم‌ها را نشان می‌دهد و در سایدبار، به صورت آیکون درمی‌آید.

css
.nav-container {    container-type: inline-size;    container-name: nav;  }  .nav-menu {    display: flex;    gap: 10px;  }  .nav-item {    padding: 10px;  }  /* عرض کم: فقط آیکون‌ها */  @container nav (max-width: 300px) {    .nav-item span {      display: none;    }    .nav-item {      font-size: 24px;    }  }  /* عرض متوسط: متن + آیکون */  @container nav (min-width: 301px) and (max-width: 500px) {    .nav-item {      display: flex;      gap: 8px;    }  }  /* عرض زیاد: همه چیز */  @container nav (min-width: 501px) {    .nav-menu {      justify-content: space-around;    }  }

مثال ۶: گالری تصاویر تطبیقی با Container Queries

گالری که بر اساس عرض والد، تعداد ستون‌ها را تغییر می‌دهد.

css
.gallery-container {    container-type: inline-size;  }  .gallery {    display: grid;    gap: 16px;  }  @container (min-width: 600px) {    .gallery {      grid-template-columns: repeat(3, 1fr);    }  }  @container (min-width: 400px) and (max-width: 599px) {    .gallery {      grid-template-columns: repeat(2, 1fr);    }  }  @container (max-width: 399px) {    .gallery {      grid-template-columns: 1fr;    }  }

مثال ۷: مقاله یا بلاگ پست با چیدمان متغیر

یک مقاله که در عرض‌های مختلف، اندازه فونت و حاشیه را تغییر می‌دهد.

css
.article-container {    container-type: inline-size;  }  .article {    padding: 20px;  }  @container (min-width: 800px) {    .article {      font-size: 18px;      padding: 40px;      max-width: 700px;      margin: 0 auto;    }    .article h1 {      font-size: 36px;    }  }  @container (max-width: 799px) {    .article {      font-size: 14px;      padding: 15px;    }    .article h1 {      font-size: 24px;    }  }

مثال ۸: دکمه جستجو (Search Bar) هوشمند

یک نوار جستجو که در عرض کم، فقط آیکون و در عرض زیاد، ورودی کامل نشان می‌دهد.

css
.search-container {    container-type: inline-size;  }  .search-bar {    display: flex;    align-items: center;    background: #f0f0f0;    border-radius: 24px;  }  .search-input {    border: none;    background: transparent;    padding: 10px;    transition: all 0.3s;  }  .search-icon {    padding: 10px;    cursor: pointer;  }  @container (max-width: 150px) {    .search-input {      display: none; /* فقط آیکون */    }  }  @container (min-width: 151px) {    .search-input {      display: block;      width: 100%;    }  }

مثال ۹: مقایسه مستقیم – ساخت یک صفحه کامل با هر دو روش

css
/* Media Queries – برای چیدمان کلی صفحه */  @media (max-width: 768px) {    .page {      grid-template-columns: 1fr;    }    .sidebar {      order: 2;    }  }  @media (min-width: 769px) {    .page {      grid-template-columns: 280px 1fr;    }  }     /* Container Queries – برای کامپوننت‌های داخل صفحه */  .sidebar-container {    container-type: inline-size;  }  .main-container {    container-type: inline-size;  }     /* ویجت سایدبار – بر اساس عرض سایدبار */  @container (max-width: 250px) {    .widget {      display: block;      text-align: center;    }    .widget-icon {      font-size: 32px;    }  }  @container (min-width: 251px) {    .widget {      display: flex;      gap: 15px;    }  }     /* ویجت main – بر اساس عرض اصلی */  @container (min-width: 600px) {    .product-grid {      grid-template-columns: repeat(3, 1fr);    }  }  @container (max-width: 599px) {    .product-grid {      grid-template-columns: repeat(2, 1fr);    }  }

مثال ۱۰: کارت نظرات کاربران (Comment Card)

یک کارت نظر که در عرض کم، تصویر بالا و در عرض زیاد، تصویر کنار متن است.

css
.comment-container {    container-type: inline-size;  }  .comment {    display: flex;    gap: 16px;    padding: 16px;    background: #f8f9fa;    border-radius: 12px;  }  .avatar {    width: 50px;    height: 50px;    border-radius: 50%;    background: #3498db;  }  @container (max-width: 300px) {    .comment {      flex-direction: column;      text-align: center;    }    .avatar {      margin: 0 auto;    }  }

مثال ۱۱: نام‌گذاری چندین کانتینر (container-name)

استفاده از نام برای کانتینرهای مختلف در یک صفحه.

css
.sidebar {    container-name: sidebar;    container-type: inline-size;  }  .main {    container-name: main;    container-type: inline-size;  }  .footer {    container-name: footer;    container-type: inline-size;  }     /* هر کدام قوانین جداگانه دارند */  @container sidebar (max-width: 200px) {    .menu-item span { display: none; }  }  @container main (min-width: 700px) {    .product-card { display: flex; }  }  @container footer (max-width: 400px) {    .footer-links { flex-direction: column; }  }

مثال ۱۲: کانتینرهای تو در تو (Nested Containers)

قدرت واقعی Container Queries زمانی است که کانتینرها داخل هم قرار می‌گیرند.

css
.outer {    container-type: inline-size;    container-name: outer;  }  .inner {    container-type: inline-size;    container-name: inner;  }  @container outer (min-width: 500px) {    .outer-box {      background: red;    }  }  @container inner (max-width: 200px) {    .inner-box {      background: blue;    }  }

مثال ۱۳: استفاده با CSS Grid برای حداکثر قدرت

ترکیب Container Queries و Grid برای ساخت ویجت‌های فوق‌العاده تطبیقی.

css
.dashboard-widget {    container-type: inline-size;  }  .widget-content {    display: grid;    gap: 16px;  }  @container (min-width: 400px) {    .widget-content {      grid-template-columns: repeat(2, 1fr);    }  }  @container (min-width: 600px) {    .widget-content {      grid-template-columns: repeat(4, 1fr);    }  }

مثال ۱۴: انیمیشن با Container Queries

تغییر استایل همراه با انیمیشن.

css
.animated-container {    container-type: inline-size;    transition: all 0.3s;  }  .box {    width: 100px;    height: 100px;    background: #3498db;    transition: all 0.3s;  }  @container (min-width: 300px) {    .box {      width: 150px;      background: #e74c3c;      transform: rotate(10deg);    }  }

مثال ۱۵: پشتیبانی از Container Queries در مرورگرهای قدیمی (fallback)

روش نوشتن کد برای مرورگرهای قدیمی که Container Queries را پشتیبانی نمی‌کنند.

css
/* Fallback برای مرورگرهای قدیمی */  .card {    display: block;  }  /* فقط مرورگرهای مدرن این را می‌بینند */  @supports (container-type: inline-size) {    .card-container {      container-type: inline-size;    }    @container (min-width: 400px) {      .card {        display: flex;      }    }  }

پروژه عملی: ساخت داشبورد با کامپوننت‌های مستقل (کامل)

css
/* تنظیمات پایه */  * {    margin: 0;    padding: 0;    box-sizing: border-box;  }     body {    font-family: system-ui, sans-serif;    background: #f5f6fa;  }     /* چیدمان کلی صفحه با Media Queries */  .dashboard {    display: grid;    grid-template-columns: 260px 1fr;    min-height: 100vh;  }     @media (max-width: 768px) {    .dashboard {      grid-template-columns: 1fr;    }  }     /* سایدبار – از Container Queries استفاده می‌کند */  .sidebar {    background: #2c3e50;    color: white;    container-type: inline-size;    container-name: sidebar;  }     /* Main area */  .main {    padding: 20px;    container-type: inline-size;    container-name: main;  }     /* ویجت آمار – خودش را با عرض والد تنظیم می‌کند */  .stats-widget {    background: white;    border-radius: 12px;    padding: 20px;    margin-bottom: 20px;    container-type: inline-size;  }     .stats-grid {    display: grid;    gap: 15px;  }     @container stats-widget (min-width: 400px) {    .stats-grid {      grid-template-columns: repeat(2, 1fr);    }  }     @container stats-widget (min-width: 600px) {    .stats-grid {      grid-template-columns: repeat(4, 1fr);    }  }     /* منوی سایدبار – در عرض کم فقط آیکون */  @container sidebar (max-width: 200px) {    .menu-item span {      display: none;    }    .menu-item {      justify-content: center;    }  }     /* کارت محصول در main */  .product-card-container {    container-type: inline-size;  }     .product-card {    background: white;    border-radius: 12px;    overflow: hidden;    display: flex;    transition: all 0.3s;  }     @container product-card-container (max-width: 300px) {    .product-card {      flex-direction: column;    }    .product-image {      height: 150px;    }  }     @container product-card-container (min-width: 301px) {    .product-card {      flex-direction: row;    }    .product-image {      width: 120px;    }  }
html
<div class="dashboard">    <aside class="sidebar">      <div class="menu-item">🏠 <span>خانه</span></div>      <div class="menu-item">📊 <span>آمار</span></div>      <div class="menu-item">⚙️ <span>تنظیمات</span></div>    </aside>    <main class="main">      <div class="stats-widget">        <div class="stats-grid">          <div class="stat-card">بازدید: ۱۲٬۰۰۰</div>          <div class="stat-card">فروش: ۳۴۰</div>          <div class="stat-card">کاربر: ۱٬۲۰۰</div>          <div class="stat-card">امتیاز: ۴.۸</div>        </div>      </div>      <div class="product-card-container">        <div class="product-card">          <div class="product-image">تصویر</div>          <div class="product-info">            <h3>محصول عالی</h3>            <p>توضیحات محصول...</p>          </div>        </div>      </div>    </main>  </div>

جدول مرجع: کی از کدام استفاده کنیم؟

سناریو راه‌حل بهتر دلیل
چیدمان کلی صفحه (هدر، فوتر، سایدبار) Media Queries وابسته به اندازه کل صفحه است
کامپوننت‌های قابل استفاده مجدد (کارت، ویجت، دکمه) Container Queries مستقل از صفحه عمل می‌کنند
طراحی ریسپانسیو برای دستگاه‌های مختلف (موبایل/تب/دسکتاپ) Media Queries device-based design
کتابخانه کامپوننت (مثل کارت محصول در هر جای سایت) Container Queries کاملاً portable
تغییر فونت و spacing بر اساس عرض صفحه Media Queries تجربه خوانایی بهتر
تغییر layout یک ویجت در سایدبار vs main Container Queries تنها راه حل صحیح
پشتیبانی از مرورگرهای قدیمی (قبل از ۲۰۲۳) Media Queries پشتیبانی کامل
پروژه‌های جدید با هدف آینده هر دو با هم قدرت ترکیبی

11. ویژگی‌ها و بخش‌های مختلف

  • ✅ مقایسه کامل Media vs Container Queries

  • ✅ ۱۵+ مثال کاربردی با کدهای آماده

  • ✅ پروژه عملی (داشبورد با کامپوننت‌های مستقل)

  • ✅ جدول مرجع برای انتخاب درست

  • ✅ پشتیبانی از fallback برای مرورگرهای قدیمی

  • ✅ نام‌گذاری کانتینر (container-name) برای پروژه‌های بزرگ

  • ✅ کانتینرهای تو در تو (Nested Containers)

  • ✅ کدهای کاملاً قابل کپی و اجرا


۱۴. بخش تمرین عملی (چالش نهایی)

💡 چالش نهایی (پروژه محور):
یک صفحه فروشگاهی کامل بسازید که شامل:

  1. چیدمان کلی صفحه با Media Queries (موبایل: ۱ ستون، تبلت: ۲ ستون، دسکتاپ: سایدبار + main)

  2. کامپوننت کارت محصول با Container Queries که در ۳ حالت مختلف ظاهر شود:

    • عرض کمتر از ۲۰۰px (فقط تصویر)

    • عرض بین ۲۰۰ تا ۳۵۰px (تصویر + عنوان)

    • عرض بیشتر از ۳۵۰px (تصویر + عنوان + قیمت + دکمه)

  3. ویجت سبد خرید در سایدبار که در عرض کم (موبایل) به صورت افقی و در عرض زیاد عمودی شود
  4. سرچ بار هوشمند که در عرض کم فقط آیکون و در عرض زیاد ورودی کامل نشان دهد
  5. فوتر با ۳ ستون که در موبایل عمودی و در دسکتاپ افقی شود (با Media Queries)

کدهای خود را در بخش نظرات به اشتراک بگذارید. بهترین پروژه‌ها را در مقاله بعدی معرفی می‌کنیم.


کلمات کلیدی:

Container Queries,Media Queries,طراحی ریسپانسیو,CSS مدرن,responsive design,container-type,container query vs media query

اشتراک گذاری:
امتیاز دهید:
(0.0 از 0 رای)
مطالب مشابه

نظرات (0)

هنوز نظری ثبت نشده است. شما اولین نفر باشید!
لطفا نام خود را وارد کنید (حداقل ۲ کاراکتر)
لطفا ایمیل معتبر وارد کنید
حداقل ۱۰ و حداکثر ۲۰۰۰ کاراکتر. نظرات پس از تایید نمایش داده می‌شوند.
نظر باید حداقل ۱۰ کاراکتر باشد
امتیاز: (اختیاری)
نظرات پس از تایید نمایش داده می‌شوند

پرسش و پاسخ

حداقل ۱۰ و حداکثر ۱۰۰۰ کاراکتر. سوالات پس از بررسی منتشر می‌شوند.
لطفا سوال معتبری وارد کنید (حداقل ۱۰ کاراکتر)
لطفا نام معتبر وارد کنید
لطفا ایمیل معتبر وارد کنید
عدد ۵ رقمی نمایش داده شده را وارد کنید
لطفا کد امنیتی را وارد کنید
سوالات پس از تایید نمایش داده می‌شوند
هنوز پرسشی ثبت نشده است.