وضعیت CSS 2022

ویژگی‌های طراحی وب امروز و فردا، همانطور که در Google IO 2022 مشاهده شد، به علاوه برخی موارد اضافی.

سال ۲۰۲۲ قرار است یکی از بهترین سال‌های CSS باشد، چه از نظر ویژگی‌ها و چه از نظر انتشار ویژگی‌های مشترک برای مرورگرها، با هدف پیاده‌سازی ۱۴ ویژگی مشترک!

نمای کلی

این پست، قالب مقاله‌ای از سخنرانی ارائه شده در Google IO 2022 است. قرار نیست این مقاله یک راهنمای جامع در مورد هر ویژگی باشد، بلکه یک مقدمه و مرور مختصر برای جلب توجه شماست و به جای عمق، به وسعت مطلب می‌پردازد. اگر علاقه‌مند شدید، انتهای هر بخش را برای لینک‌های منابع به اطلاعات بیشتر بررسی کنید.

فهرست مطالب

برای پرش به موضوعات مورد علاقه از لیست زیر استفاده کنید:

سازگاری با مرورگرها

دلیل اصلی انتشار مشترک بسیاری از ویژگی‌های CSS، تلاش‌های Interop 2022 است. قبل از مطالعه تلاش‌های Interop، مهم است که به تلاش‌های Compat 2021 نگاهی بیندازیم.

کامپت ۲۰۲۱

اهداف سال ۲۰۲۱، که بر اساس بازخورد توسعه‌دهندگان از طریق نظرسنجی‌ها تعیین شده بود، تثبیت ویژگی‌های فعلی، بهبود مجموعه تست و افزایش امتیاز قبولی مرورگرها برای پنج ویژگی زیر بود:

  1. موقعیت یابی sticky
  2. اندازه aspect-ratio
  3. طرح بندی flex
  4. طرح grid
  5. transform موقعیت و انیمیشن

نمرات آزمون در کل افزایش یافت که نشان‌دهنده‌ی بهبود پایداری و قابلیت اطمینان است. تبریک فراوان به تیم‌های حاضر!

اینتراپ ۲۰۲۲

امسال، مرورگرها برای بحث در مورد ویژگی‌ها و اولویت‌هایی که قصد داشتند روی آنها کار کنند، گرد هم آمدند و تلاش‌های خود را متحد کردند. آنها قصد داشتند ویژگی‌های وب زیر را برای توسعه‌دهندگان ارائه دهند:

  1. @layer
  2. فضاها و توابع رنگی
  3. مهار
  4. <dialog>
  5. سازگاری با فرم
  6. پیمایش
  7. زیرشبکه
  8. تایپوگرافی
  9. واحدهای دیدبانی
  10. سازگاری وب

این یک لیست هیجان‌انگیز و جاه‌طلبانه است که بی‌صبرانه منتظرم ببینم چه اتفاقی می‌افتد.

تازه برای سال 2022

همانطور که انتظار می‌رود، وضعیت CSS 2022 به طور چشمگیری تحت تأثیر کار Interop 2022 قرار گرفته است.

لایه‌های آبشاری

Browser Support

  • کروم: ۹۹.
  • لبه: ۹۹.
  • فایرفاکس: ۹۷.
  • سافاری: ۱۵.۴.

Source

قبل از @layer ، ترتیب کشف‌شده‌ی استایل‌شیت‌های بارگذاری‌شده بسیار مهم بود، زیرا استایل‌هایی که آخر بارگذاری می‌شدند می‌توانستند استایل‌های بارگذاری‌شده‌ی قبلی را بازنویسی کنند. این امر منجر به استایل‌شیت‌های ورودی با مدیریت دقیق شد، که در آن توسعه‌دهندگان باید استایل‌های کم‌اهمیت‌تر را ابتدا و استایل‌های مهم‌تر را بعداً بارگذاری می‌کردند. روش‌های کاملی برای کمک به توسعه‌دهندگان در مدیریت این اهمیت وجود دارد، مانند ITCSS .

با استفاده از @layer ‎، فایل ورودی می‌تواند لایه‌ها و ترتیب آنها را از قبل تعریف کند. سپس، همزمان با بارگذاری، بارگذاری یا تعریف استایل‌ها، می‌توان آنها را درون یک لایه قرار داد و به این ترتیب، اهمیت نادیده گرفتن استایل حفظ می‌شود، اما بدون هماهنگی دقیق بارگذاری.

این ویدئو نشان می‌دهد که چگونه لایه‌های آبشاری تعریف‌شده، فرآیند نوشتن و بارگذاری آزادتر و آزادتری را فراهم می‌کنند، در حالی که همچنان آبشار را در صورت نیاز حفظ می‌کنند.

Chrome DevTools برای تجسم اینکه کدام استایل‌ها از کدام لایه‌ها می‌آیند، مفید است:

تصویری از نوار کناری Styles در Chrome Devtools، که نحوه نمایش استایل‌ها در گروه‌های لایه جدید را نشان می‌دهد.

منابع

زیرشبکه

Browser Support

  • کروم: ۱۱۷.
  • لبه: ۱۱۷.
  • فایرفاکس: ۷۱.
  • سافاری: ۱۶.

Source

قبل از subgrid ، یک grid درون grid دیگر نمی‌توانست خود را با سلول‌های والد یا خطوط grid تراز کند. طرح‌بندی هر grid منحصر به فرد بود. بسیاری از طراحان یک grid واحد را روی کل طرح خود قرار می‌دهند و دائماً موارد را درون آن تراز می‌کنند، کاری که در CSS قابل انجام نبود.

بعد از subgrid ، یک فرزند از یک شبکه می‌تواند ستون‌ها یا ردیف‌های والدین خود را به عنوان ستون‌ها یا ردیف‌های خود بپذیرد و خود یا فرزندانش را با آنها تراز کند!

در دموی زیر، عنصر body یک شبکه کلاسیک از سه ستون ایجاد می‌کند: ستون وسط main نام دارد و ستون‌های چپ و راست خطوط خود را fullbleed نامگذاری می‌کنند. سپس، هر عنصر در body، <nav> و <main> ، با تنظیم grid-template-columns: subgrid ، خطوط نامگذاری شده را از body اقتباس می‌کند.

​​body {
  display: grid;
  grid-template-columns:
    [fullbleed-start]
    auto [main-start] min(90%, 60ch) [main-end] auto
    [fullbleed-end]
  ;
}

body > * {
  display: grid;
  grid-template-columns: subgrid;
}

در نهایت، فرزندان عناصر <nav> یا <main> می‌توانند با استفاده از ستون‌ها و خطوط fullbleed و main ، خودشان را تراز یا اندازه‌بندی کنند.

.main-content {
  grid-column: main;
}

.fullbleed {
  grid-column: fullbleed;
}

ابزارهای توسعه (Devtools) می‌توانند به شما در دیدن خطوط و زیرشبکه‌ها کمک کنند (در حال حاضر فقط در فایرفاکس). در تصویر زیر، شبکه والد و زیرشبکه‌ها روی هم قرار گرفته‌اند. اکنون شبیه به نحوه تفکر طراحان در مورد طرح‌بندی است.

تصویری از یک دموی subgrid، که با استفاده از ابزار Chrome Devtools grid overlay برای نمایش خطوط تعریف شده توسط CSS استفاده شده است.

در پنل عناصر devtools می‌توانید ببینید که کدام عناصر شبکه‌ای و کدام زیرشبکه‌ای هستند، که برای اشکال‌زدایی یا اعتبارسنجی طرح‌بندی بسیار مفید است.

تصویری از پنل عناصر Devtools کروم که عناصر دارای طرح‌بندی شبکه‌ای یا زیرشبکه‌ای را برچسب‌گذاری می‌کند.
تصویر از ابزار توسعه فایرفاکس

منابع

پرس و جوهای کانتینر

Browser Support

  • کروم: ۱۰۵.
  • لبه: ۱۰۵.
  • فایرفاکس: ۱۱۰.
  • سافاری: ۱۶.

Source

قبل از @container ، عناصر یک صفحه وب فقط می‌توانستند به اندازه کل viewport واکنش نشان دهند. این برای طرح‌بندی‌های ماکرو عالی است، اما برای طرح‌بندی‌های میکرو، که ظرف بیرونی آنها کل viewport نیست، تنظیم طرح‌بندی بر اساس آن غیرممکن است.

بعد از @container ، عناصر می‌توانند به اندازه یا سبک کانتینر والد پاسخ دهند! تنها نکته این است که کانتینرها باید خود را به عنوان اهداف پرس و جوی ممکن اعلام کنند، که این یک الزام کوچک برای یک مزیت بزرگ است.

/* establish a container */
.day {
  container-type: inline-size;
  container-name: calendar-day;
}

این سبک‌ها همان چیزی هستند که باعث می‌شوند ستون‌های دوشنبه، سه‌شنبه، چهارشنبه، پنجشنبه و جمعه در ویدیوی زیر توسط عناصر رویداد قابل پرس‌وجو باشند.

نسخه آزمایشی توسط اونا کراوتس

در اینجا CSS برای پرس و جو از ظرف calendar-day برای اندازه آن، سپس تنظیم طرح بندی و اندازه فونت آمده است:

@container calendar-day (max-width: 200px) {
  .date {
    display: block;
  }

  .date-num {
    font-size: 2.5rem;
    display: block;
  }
}

یک مثال دیگر: یک کامپوننت کتاب خودش را با فضای موجود در ستونی که به آن کشیده شده است، تطبیق می‌دهد:

نسخه آزمایشی توسط مکس بوک

ارزیابی اونا از وضعیت به عنوان یک واکنش‌گرای جدید درست است. هنگام استفاده از @container ، تصمیمات طراحی هیجان‌انگیز و معناداری وجود دارد که می‌توان گرفت.

منابع

accent-color

Browser Support

  • کروم: ۹۳.
  • لبه: ۹۳.
  • فایرفاکس: ۹۲.
  • سافاری: ۱۵.۴.

Source

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

پس از accent-color ، یک خط CSS رنگ برند را به اجزای داخلی اضافه می‌کند. مرورگر علاوه بر ته رنگ، هوشمندانه رنگ‌های متضاد مناسب را برای بخش‌های فرعی کامپوننت انتخاب می‌کند و با طرح‌های رنگی سیستم (روشن یا تیره) سازگار می‌شود.

/* tint everything */
:root {
  accent-color: hotpink;
}

/* tint one element */
progress {
  accent-color: indigo;
}

عناصر HTML با لهجه روشن و تیره در کنار هم برای مقایسه.

برای کسب اطلاعات بیشتر در مورد accent-color ، به پست من در web.dev مراجعه کنید که در آن جنبه‌های بسیار بیشتری از این ویژگی مفید CSS را بررسی کرده‌ام.

منابع

سطح رنگ ۴ و ۵

در دهه‌های گذشته، فضای وب تحت سلطه sRGB بوده است، اما در دنیای دیجیتال رو به گسترش نمایشگرهای با کیفیت بالا و دستگاه‌های تلفن همراه مجهز به صفحه نمایش‌های OLED یا QLED، sRGB کافی نیست. علاوه بر این، انتظار می‌رود صفحات پویایی که با ترجیحات کاربر سازگار می‌شوند، وجود داشته باشند و مدیریت رنگ به یک نگرانی رو به رشد برای طراحان، سیستم‌های طراحی و نگهدارندگان کد تبدیل شده است.

البته نه در سال ۲۰۲۲—CSS تعدادی تابع و فضای رنگی جدید دارد: - رنگ‌هایی که به قابلیت‌های رنگی HD نمایشگرها می‌رسند. - فضاهای رنگی که با یک هدف، مانند یکنواختی ادراکی، مطابقت دارند. - فضاهای رنگی برای گرادیان‌هایی که نتایج درون‌یابی را به شدت تغییر می‌دهند. - توابع رنگی برای کمک به شما در ترکیب و کنتراست و انتخاب فضایی که کار را در آن انجام می‌دهید.

قبل از همه این ویژگی‌های رنگی، سیستم‌های طراحی نیاز داشتند تا رنگ‌های متضاد مناسب را از قبل محاسبه کنند و از پالت‌های پر جنب و جوش مناسب اطمینان حاصل کنند، در حالی که پیش‌پردازنده‌ها یا جاوا اسکریپت کارهای سنگین را انجام می‌دادند.

بعد از همه این ویژگی‌های رنگی، مرورگر و CSS می‌توانند تمام کارها را به صورت پویا و در زمان مناسب انجام دهند. به جای ارسال حجم زیادی از فایل‌های CSS و جاوا اسکریپت به کاربران برای فعال کردن تم‌بندی و تجسم داده‌ها، CSS می‌تواند هماهنگی و محاسبات را انجام دهد. CSS همچنین برای بررسی پشتیبانی قبل از استفاده یا مدیریت مناسب fallbackها، مجهزتر است.

@media (dynamic-range: high) {
  .neon-pink {
    --neon-glow: color(display-p3 1 0 1);
  }
}

@supports (color: lab(0% 0 0)) {
  .neon-pink {
    --neon-glow: lab(150% 160 0);
  }
}

hwb()

Browser Support

  • کروم: ۱۰۱.
  • لبه: ۱۰۱.
  • فایرفاکس: ۹۶.
  • سافاری: ۱۵.

Source

HWB مخفف رنگ (hue)، سفیدی (whiteness) و سیاهی (blackness) است. این اصطلاح خود را به عنوان روشی انسان‌پسند برای بیان رنگ معرفی می‌کند، زیرا فقط یک رنگ (hue) و مقداری سفید یا سیاه برای روشن یا تیره کردن است. هنرمندانی که رنگ‌ها را با سفید یا سیاه ترکیب می‌کنند، ممکن است از این ترکیب رنگی جدید قدردانی کنند.

استفاده از این تابع رنگ، رنگ‌هایی از فضای رنگی sRGB، همانند HSL و RGB، تولید می‌کند. از نظر جدید بودن برای سال ۲۰۲۲، این به شما رنگ‌های جدیدی نمی‌دهد، اما ممکن است برخی از کارها را برای طرفداران سینتکس و مدل ذهنی آسان‌تر کند.

منابع

فضاهای رنگی

نحوه نمایش رنگ‌ها با یک فضای رنگی انجام می‌شود. هر فضای رنگی ویژگی‌ها و مصالحه‌های مختلفی را برای کار با رنگ ارائه می‌دهد. برخی ممکن است همه رنگ‌های روشن را با هم ترکیب کنند؛ برخی ممکن است ابتدا آنها را بر اساس روشنایی‌شان در یک ردیف قرار دهند.

قرار است CSS در سال ۲۰۲۲، ۱۰ فضای رنگی جدید ارائه دهد که هر کدام ویژگی‌های منحصر به فردی دارند تا به طراحان و توسعه‌دهندگان در نمایش، انتخاب و ترکیب رنگ‌ها کمک کنند. پیش از این، sRGB تنها گزینه برای کار با رنگ بود، اما اکنون CSS پتانسیل جدید و یک فضای رنگی پیش‌فرض جدید، LCH، را ارائه می‌دهد.

color-mix()

Browser Support

  • کروم: ۱۱۱.
  • لبه: ۱۱۱.
  • فایرفاکس: ۱۱۳.
  • سافاری: ۱۶.۲.

Source

قبل از color-mix() ، توسعه‌دهندگان و طراحان به پیش‌پردازنده‌هایی مانند Sass نیاز داشتند تا رنگ‌ها را قبل از اینکه مرورگر آنها را ببیند، با هم ترکیب کنند. اکثر توابع ترکیب رنگ نیز گزینه‌ای برای مشخص کردن فضای رنگی که باید ترکیب را در آن انجام دهند، ارائه نمی‌دادند، که گاهی اوقات منجر به نتایج گیج‌کننده‌ای می‌شد.

پس از تابع color-mix() ، توسعه‌دهندگان و طراحان می‌توانند رنگ‌ها را در مرورگر، در کنار تمام استایل‌های دیگر خود، بدون اجرای فرآیندهای ساخت یا گنجاندن جاوا اسکریپت، با هم ترکیب کنند. علاوه بر این، آن‌ها می‌توانند مشخص کنند که ترکیب در کدام فضای رنگی انجام شود یا از فضای رنگی پیش‌فرض LCH استفاده کنند.

اغلب، یک رنگ برند به عنوان پایه استفاده می‌شود و انواع مختلفی از آن ایجاد می‌شود، مانند رنگ‌های روشن‌تر یا تیره‌تر برای استایل‌های hover. در اینجا نحوه‌ی نمایش آن با color-mix() آمده است:

.color-mix-example {
  --brand: #0af;

  --darker: color-mix(var(--brand) 25%, black);
  --lighter: color-mix(var(--brand) 25%, white);
}

و اگر می‌خواستید آن رنگ‌ها را در یک فضای رنگی متفاوت، مانند srgb، ترکیب کنید، آن را تغییر دهید:

.color-mix-example {
  --brand: #0af;

  --darker: color-mix(in srgb, var(--brand) 25%, black);
  --lighter: color-mix(in srgb, var(--brand) 25%, white);
}

در اینجا یک دموی تغییر تم با استفاده از color-mix() آمده است. سعی کنید رنگ برند را تغییر دهید و به‌روزرسانی تم را تماشا کنید:

از ترکیب رنگ‌ها در فضاهای رنگی مختلف در استایل‌شیت‌های خود در سال ۲۰۲۲ لذت ببرید!

منابع

color-contrast()

قبل از color-contrast() ، نویسندگان stylesheet باید از قبل رنگ‌های قابل دسترس را می‌دانستند. اغلب یک پالت، متن سیاه یا سفید را روی یک نمونه رنگ نشان می‌داد تا به کاربر سیستم رنگ نشان دهد که کدام رنگ متن برای ایجاد کنتراست مناسب با آن نمونه رنگ مورد نیاز است.

تصویر صفحه از ۳ پالت متریال، که ۱۴ رنگ و رنگ‌های کنتراست سفید یا سیاه مناسب برای متن را نشان می‌دهد.
مثالی از پالت‌های رنگی متریال دیزاین ۲۰۱۴

پس از color-contrast() ، نویسندگان استایل‌شیت می‌توانند این وظیفه را به‌طور کامل به مرورگر محول کنند. شما نه‌تنها می‌توانید از مرورگر برای انتخاب خودکار رنگ سیاه یا سفید استفاده کنید، بلکه می‌توانید فهرستی از رنگ‌های مناسب سیستم طراحی را به آن بدهید و از آن بخواهید اولین رنگی را که با نسبت کنتراست مورد نظر شما مطابقت دارد، انتخاب کند.

در اینجا تصویری از دموی مجموعه پالت رنگ HWB را مشاهده می‌کنید که در آن رنگ‌های متن به طور خودکار توسط مرورگر بر اساس رنگ نمونه انتخاب می‌شوند:

تصویری از دموی HWB که در آن هر پالت، جفت متفاوتی از متن روشن یا تیره دارد، که توسط مرورگر تعیین می‌شود.
نسخه آزمایشی را امتحان کنید

اصول اولیه این سینتکس به این شکل است که خاکستری به تابع ارسال می‌شود و مرورگر تعیین می‌کند که سیاه یا سفید بیشترین کنتراست را دارند:

color: color-contrast(gray);

این تابع همچنین می‌تواند با فهرستی از رنگ‌ها سفارشی‌سازی شود، که از بین آنها، رنگی با بالاترین کنتراست را انتخاب می‌کند:

color: color-contrast(gray vs indigo, rebeccapurple, hotpink);

در نهایت، در صورتی که ترجیح داده شود رنگی با بالاترین کنتراست از لیست انتخاب نشود، می‌توان یک نسبت کنتراست هدف ارائه داد و اولین رنگی که از آن عبور کند انتخاب می‌شود:

color: color-contrast(
  var(--bg-blue-1)
  vs
  var(--text-lightest), var(--text-light), var(--text-subdued)
  to AA /* 4.5 could also be passed */
);

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

منابع

نحو رنگ نسبی

Browser Support

  • کروم: ۱۱۱.
  • لبه: ۱۱۱.
  • فایرفاکس: ۱۱۳.
  • سافاری: ۱۵.

Source

قبل از سینتکس رنگ نسبی، برای محاسبه رنگ و انجام تنظیمات، کانال‌های رنگ باید به صورت جداگانه در ویژگی‌های سفارشی قرار می‌گرفتند. این محدودیت همچنین HSL را به تابع رنگ اصلی برای دستکاری رنگ‌ها تبدیل می‌کرد زیرا رنگ، اشباع یا روشنایی همگی می‌توانستند به روشی ساده با calc() تنظیم شوند.

پس از سینتکس رنگ نسبی، هر رنگی در هر فضایی می‌تواند تجزیه، اصلاح و به عنوان یک رنگ برگردانده شود، همه این‌ها در یک خط CSS انجام می‌شود. دیگر هیچ محدودیتی برای HSL وجود ندارد - دستکاری‌ها را می‌توان در هر فضای رنگی دلخواه انجام داد و برای تسهیل آن به ویژگی‌های سفارشی بسیار کمتری نیاز است.

در مثال سینتکس زیر، یک هگز پایه ارائه شده و دو رنگ جدید نسبت به آن ایجاد می‌شوند. رنگ اول --absolute-change یک رنگ جدید در LCH از رنگ پایه ایجاد می‌کند، سپس روشنایی رنگ پایه را با 75% جایگزین می‌کند و کروما ( c ) و رنگ ( h ) را حفظ می‌کند. رنگ دوم --relative-change یک رنگ جدید در LCH از رنگ پایه ایجاد می‌کند، اما این بار کروما ( c ) را 20٪ کاهش می‌دهد.

.relative-color-syntax {
  --color: #0af;
  --absolute-change: lch(from var(--color) 75% c h);
  --relative-change: lch(from var(--color) l calc(c-20%) h);
}

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

در دموی زیر، از سینتکس رنگ نسبی برای ایجاد انواع روشن‌تر و تیره‌تر از یک رنگ پایه استفاده کرده‌ام و از color-contrast() برای اطمینان از کنتراست مناسب برچسب‌ها استفاده کرده‌ام:

تصویر صفحه با ۳ ستون، هر ستون یا تیره‌تر یا روشن‌تر از ستون مرکزی است.
نسخه آزمایشی را امتحان کنید

این تابع همچنین می‌تواند برای تولید پالت رنگ استفاده شود. در اینجا یک نسخه آزمایشی وجود دارد که در آن کل پالت‌ها از یک رنگ پایه ارائه شده تولید می‌شوند. این مجموعه CSS به تمام پالت‌های مختلف قدرت می‌دهد، هر پالت به سادگی یک پایه متفاوت ارائه می‌دهد. به عنوان یک امتیاز، از آنجایی که من از LCH استفاده کرده‌ام، به میزان ادراک پالت‌ها توجه کنید - به لطف این فضای رنگی، هیچ نقطه داغ یا مرده‌ای دیده نمی‌شود.

:root {
  --_color-base: #339af0;

  --color-0:  lch(from var(--_color-base) 98% 10 h);
  --color-1:  lch(from var(--_color-base) 93% 20 h);
  --color-2:  lch(from var(--_color-base) 85% 40 h);
  --color-3:  lch(from var(--_color-base) 75% 46 h);
  --color-4:  lch(from var(--_color-base) 66% 51 h);
  --color-5:  lch(from var(--_color-base) 61% 52 h);
  --color-6:  lch(from var(--_color-base) 55% 57 h);
  --color-7:  lch(from var(--_color-base) 49% 58 h);
  --color-8:  lch(from var(--_color-base) 43% 55 h);
  --color-9:  lch(from var(--_color-base) 39% 52 h);
  --color-10: lch(from var(--_color-base) 32% 48 h);
  --color-11: lch(from var(--_color-base) 25% 45 h);
  --color-12: lch(from var(--_color-base) 17% 40 h);
  --color-13: lch(from var(--_color-base) 10% 30 h);
  --color-14: lch(from var(--_color-base) 5% 20 h);
  --color-15: lch(from var(--_color-base) 1% 5 h);
}
تصویری از ۱۵ پالت که همگی به صورت پویا توسط CSS تولید شده‌اند.
نسخه آزمایشی را امتحان کنید

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

منابع

فضاهای رنگی گرادیان

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

۴ گرادیان در یک شبکه، همه از فیروزه‌ای تا صورتی پررنگ. LCH و LAB سرزندگی ثابت‌تری دارند، در حالی که sRGB در وسط کمی اشباع‌زدایی می‌شود.

بعد از فضاهای رنگی گرادیان، به مرورگر بگویید که از کدام فضای رنگی برای درون‌یابی رنگ استفاده کند. این به توسعه‌دهندگان و طراحان این امکان را می‌دهد که گرادیان مورد نظر خود را انتخاب کنند. فضای رنگی پیش‌فرض نیز به جای sRGB به LCH تغییر می‌کند.

دستور جمع بعد از جهت گرادیان قرار می‌گیرد، از new in دستور استفاده می‌کند و اختیاری است:

background-image: linear-gradient(
  to right in hsl,
  black, white
);

background-image: linear-gradient(
  to right in lch,
  black, white
);

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

۱۱ فضای رنگی که سیاه و سفید را با هم مقایسه می‌کنند.

در مثال بعدی، رنگ مشکی به آبی تغییر می‌کند زیرا این یک فضای مشکل‌ساز شناخته شده برای گرادیان‌ها است. اکثر فضاهای رنگی در طول درون‌یابی رنگ یا، همانطور که من دوست دارم به آن فکر کنم، به بنفش متمایل می‌شوند، زیرا رنگ‌ها در فضای رنگی خود از نقطه A به نقطه B حرکت می‌کنند. از آنجایی که گرادیان یک خط مستقیم از نقطه A به نقطه B را طی می‌کند، شکل فضای رنگی به طور چشمگیری ایستگاه‌هایی را که مسیر در طول مسیر طی می‌کند تغییر می‌دهد.

۱۱ فضای رنگی که آبی و مشکی را با هم مقایسه می‌کنند.

برای کاوش‌های عمیق‌تر، مثال‌ها و نظرات، این رشته توییت را بخوانید.

منابع

inert

Browser Support

  • کروم: ۱۰۲.
  • لبه: ۱۰۲.
  • فایرفاکس: ۱۱۲.
  • سافاری: ۱۵.۵

Source

قبل از inert ، هدایت تمرکز کاربر به بخش‌هایی از صفحه یا برنامه که نیاز به توجه فوری داشتند، روش خوبی بود. این استراتژی تمرکز هدایت‌شده به عنوان focus trapping شناخته می‌شد، زیرا توسعه‌دهندگان تمرکز را در یک فضای تعاملی قرار می‌دادند، به رویدادهای تغییر تمرکز گوش می‌دادند و اگر تمرکز از فضای تعاملی خارج می‌شد، دوباره به آن بازگردانده می‌شد. کاربرانی که از کیبورد یا صفحه‌خوان استفاده می‌کنند، قبل از ادامه کار، به فضای تعاملی هدایت می‌شوند تا از تکمیل کار اطمینان حاصل شود.

بعد از inert ، نیازی به trapping نیست زیرا می‌توانید کل بخش‌های صفحه یا برنامه را freeze یا guard کنید. کلیک‌ها و تلاش‌های تغییر focus به سادگی در حالی که آن بخش‌های سند inert هستند، در دسترس نیستند. همچنین می‌توان این را مانند guards به جای trap در نظر گرفت، که inert علاقه‌ای به نگه داشتن شما در جایی ندارد، بلکه می‌خواهد مکان‌های دیگر را از دسترس خارج کند.

یک مثال خوب از این مورد، تابع alert() در جاوا اسکریپت است:

وب‌سایت به صورت تعاملی نمایش داده می‌شود، سپس تابع alert() فراخوانی می‌شود و صفحه دیگر فعال نیست.

در ویدیوی قبلی توجه کنید که چگونه صفحه تا زمان فراخوانی alert() با ماوس و کیبورد قابل دسترسی بود. به محض نمایش پنجره هشدار، بقیه صفحه ثابت یا inert شد. تمرکز کاربران درون پنجره هشدار قرار می‌گیرد و جای دیگری برای رفتن ندارد. به محض اینکه کاربر تعامل برقرار کند و درخواست تابع هشدار را تکمیل کند، صفحه دوباره تعاملی می‌شود. inert به توسعه‌دهندگان این امکان را می‌دهد تا به راحتی به همین تجربه تمرکز هدایت‌شده دست یابند.

در اینجا یک نمونه کد کوچک برای نشان دادن نحوه کار آن آورده شده است:

<body>
  <div class="modal">
    <h2>Modal Title</h2>
    <p>...<p>
    <button>Save</button>
    <button>Discard</button>
  </div>
  <main inert>
    <!-- cannot be keyboard focused or clicked -->
  </main>
</body>

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

منابع

فونت‌های COLRv1

قبل از فونت‌های COLRv1، وب دارای فونت‌های OT-SVG بود، که آن هم فرمتی باز برای فونت‌هایی با گرادیان و رنگ‌ها و جلوه‌های داخلی بود. البته این فونت‌ها می‌توانستند خیلی بزرگ شوند و در حالی که امکان ویرایش متن را فراهم می‌کردند، فضای زیادی برای سفارشی‌سازی وجود نداشت.

پس از فونت‌های COLRv1 ، وب دارای فونت‌های کم‌حجم‌تر، مقیاس‌پذیر در مقیاس برداری، قابل تغییر موقعیت، دارای گرادیان و حالت ترکیبی است که پارامترهایی را برای سفارشی‌سازی فونت در هر مورد استفاده یا مطابقت با یک برند می‌پذیرند.

مقایسه بصری و نمودار میله‌ای، که نشان می‌دهد فونت‌های COLRv1 چگونه واضح‌تر و کوچک‌تر هستند.
تصویر از https://developer.chrome.com/blog/colrv1-fonts/ گرفته شده است

در اینجا مثالی از پست وبلاگ توسعه‌دهندگان کروم در مورد ایموجی‌ها آورده شده است. شاید متوجه شده باشید که اگر اندازه فونت یک ایموجی را افزایش دهید، وضوح آن حفظ نمی‌شود. این یک تصویر است و نه یک اثر هنری برداری. اغلب در برنامه‌ها وقتی از یک ایموجی استفاده می‌شود، آن را با یک عنصر با کیفیت بالاتر جایگزین می‌کنند. با فونت‌های COLRv1، ایموجی‌ها برداری و زیبا هستند:

فونت‌های آیکون می‌توانند با این فرمت کارهای شگفت‌انگیزی انجام دهند، پالت‌های رنگی دوتایی سفارشی و موارد دیگر را ارائه دهند. بارگذاری یک فونت COLRv1 درست مانند هر فایل فونت دیگری است:

@import url(https://fonts.googleapis.com/css2?family=Bungee+Spice);

سفارشی‌سازی فونت COLRv1 با @font-palette-values ​​انجام می‌شود، یک at-rule ویژه CSS برای گروه‌بندی و نامگذاری مجموعه‌ای از گزینه‌های سفارشی‌سازی در یک bundle برای مراجعات بعدی. توجه کنید که چگونه یک نام سفارشی را درست مانند یک ویژگی سفارشی مشخص می‌کنید، که با -- شروع می‌شود:

@import url(https://fonts.googleapis.com/css2?family=Bungee+Spice);

@font-palette-values --colorized {
  font-family: "Bungee Spice";
  base-palette: 0;
  override-colors: 0 hotpink, 1 cyan, 2 white;
}

با استفاده --colorized به عنوان نام مستعار برای سفارشی‌سازی‌ها، آخرین مرحله اعمال پالت رنگ به عنصری است که از خانواده فونت رنگی استفاده می‌کند:

@import url(https://fonts.googleapis.com/css2?family=Bungee+Spice);

@font-palette-values --colorized {
  font-family: "Bungee Spice";
  base-palette: 0;
  override-colors: 0 hotpink, 1 cyan, 2 white;
}

.spicy {
  font-family: "Bungee Spice";
  font-palette: --colorized;
}
تصویری از فونت Bungee Spice با کلمه DUNE.
فونت Bungee Spice با رنگ‌های سفارشی نمایش داده شده است، منبع از https://developer.chrome.com/blog/colrv1-fonts/

با افزایش تنوع فونت‌ها و فونت‌های رنگی، تایپوگرافی وب در مسیر بسیار باشکوهی به سمت سفارشی‌سازی غنی و بیان خلاقانه قرار دارد.

منابع

واحدهای دیدبانی

گرافیکی که نشان می‌دهد چگونه صفحه نمایش دستگاه و پنجره مرورگر و یک iframe، همگی دارای نماهای متفاوتی هستند.

قبل از انواع جدید viewport، وب واحدهای فیزیکی را برای کمک به تناسب viewportها ارائه می‌داد. یکی برای ارتفاع، عرض، کوچکترین اندازه (vmin) و بزرگترین ضلع (vmax) وجود داشت. این واحدها برای بسیاری از موارد به خوبی کار می‌کردند، اما مرورگرهای موبایل پیچیدگی‌هایی را ایجاد کردند.

در موبایل، هنگام بارگذاری یک صفحه، نوار وضعیت با آدرس اینترنتی (url) نمایش داده می‌شود و این نوار مقداری از فضای نمایشگر را اشغال می‌کند. پس از چند ثانیه و کمی تعامل، نوار وضعیت ممکن است به صورت کشویی کنار برود تا تجربه نمایشگر بزرگتری را برای کاربر فراهم کند. اما وقتی آن نوار به بیرون کشیده می‌شود، ارتفاع نمایشگر تغییر کرده است و هر واحد vh با تغییر اندازه هدف خود، تغییر مکان داده و تغییر اندازه می‌دهد. در سال‌های بعد، واحد vh به طور خاص نیاز داشت تا تصمیم بگیرد که از کدام یک از دو اندازه نمایشگر استفاده خواهد کرد، زیرا این امر باعث ایجاد مشکلات چیدمان بصری نامطلوب در دستگاه‌های تلفن همراه می‌شد. مشخص شد که vh همیشه بزرگترین نمایشگر را نشان می‌دهد.

.original-viewport-units {
  height: 100vh;
  width: 100vw;
  --size: 100vmin;
  --size: 100vmax;
}

پس از انواع جدید نمای دید، واحدهای نمای دید کوچک، بزرگ و پویا در دسترس قرار گرفتند و معادل‌های منطقی به واحدهای فیزیکی اضافه شد. ایده این است که به توسعه‌دهندگان و طراحان این امکان را بدهیم که واحدی را که می‌خواهند برای سناریوی خاص خود استفاده کنند، انتخاب کنند. شاید اشکالی نداشته باشد که وقتی نوار وضعیت از بین می‌رود، یک تغییر طرح کوچک و نامطلوب داشته باشیم، بنابراین می‌توان بدون نگرانی dvh (ارتفاع نمای دید پویا) استفاده کرد.

گرافیکی با سه تلفن برای کمک به نشان دادن DVH، LVH و SVH. تلفن مثال DVH دارای دو خط عمودی است، یکی بین پایین نوار جستجو و پایین پنجره نمایش و یکی بین بالای نوار جستجو (زیر نوار وضعیت سیستم) تا پایین پنجره نمایش؛ نشان می‌دهد که چگونه DVH می‌تواند هر یک از این دو طول را داشته باشد. LVH در وسط با یک خط بین پایین نوار وضعیت دستگاه و دکمه پنجره نمایش تلفن نشان داده شده است. مورد آخر، مثال واحد SVH است که خطی از پایین نوار جستجوی مرورگر تا پایین پنجره نمایش را نشان می‌دهد.

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

واحدهای ارتفاع نمای دید
​​.new-height-viewport-units {
  height: 100vh;
  height: 100dvh;
  height: 100svh;
  height: 100lvh;
  block-size: 100vb;
  block-size: 100dvb;
  block-size: 100svb;
  block-size: 100lvb;
}
واحدهای عرض نمای دید
.new-width-viewport-units {
  width: 100vw;
  width: 100dvw;
  width: 100svw;
  width: 100lvw;
  inline-size: 100vi;
  inline-size: 100dvi;
  inline-size: 100svi;
  inline-size: 100lvi;
}
کوچکترین واحدهای جانبی نمای دید
.new-min-viewport-units {
  --size: 100vmin;
  --size: 100dvmin;
  --size: 100svmin;
  --size: 100lvmin;
}
بزرگترین واحدهای جانبی منظره یاب
.new-max-viewport-units {
  --size: 100vmax;
  --size: 100dvmax;
  --size: 100svmax;
  --size: 100lvmax;
}

امید است که این موارد به توسعه‌دهندگان و طراحان انعطاف‌پذیری لازم برای دستیابی به طرح‌های واکنش‌گرا برای viewport را بدهد.

منابع

:has()

Browser Support

  • کروم: ۱۰۵.
  • لبه: ۱۰۵.
  • فایرفاکس: ۱۲۱.
  • سافاری: ۱۵.۴.

Source

قبل از :has() ، موضوع یک انتخابگر همیشه در انتها قرار داشت. برای مثال، موضوع این انتخابگر یک آیتم لیست است: ul > li . انتخابگرهای کاذب می‌توانند انتخابگر را تغییر دهند اما موضوع را تغییر نمی‌دهند: ul > li:hover یا ul > li:not(.selected) .

پس از :has() ، یک موضوع بالاتر در درخت عناصر می‌تواند در حین ارائه پرس‌وجو در مورد فرزندان، موضوع باقی بماند: ul:has(> li) . درک این موضوع که چگونه :has() نام رایج "انتخابگر والد" را دارد، آسان است، زیرا موضوع انتخابگر اکنون در این مورد والد است.

در اینجا یک مثال سینتکس پایه آورده شده است که در آن کلاس .parent همچنان موضوع است اما فقط در صورتی انتخاب می‌شود که یک عنصر فرزند دارای کلاس .child باشد:

.parent:has(.child) {...}

در اینجا مثالی آورده شده است که در آن یک عنصر <section> موضوع است، اما انتخابگر فقط در صورتی مطابقت دارد که یکی از فرزندان دارای :focus-visible :

section:has(*:focus-visible) {...}

انتخابگر :has() زمانی که موارد استفاده عملی بیشتری آشکار شود، به یک ابزار فوق‌العاده تبدیل می‌شود. برای مثال، در حال حاضر انتخاب تگ‌های <a> هنگام قرار دادن تصاویر در کنار هم امکان‌پذیر نیست، و این امر آموزش نحوه تغییر سبک‌های تگ لنگر را در چنین مواردی دشوار می‌کند. با این حال، با :has() این امکان وجود دارد:

a:has(> img) {...}

همه اینها مثال‌هایی بودند که در آنها :has() فقط شبیه یک انتخابگر والد به نظر می‌رسد. مورد استفاده از تصاویر درون عناصر <figure> و تنظیم سبک‌ها روی تصاویر را در صورتی که شکل دارای <figcaption> باشد، در نظر بگیرید. در مثال زیر، شکل‌هایی با figcaption انتخاب می‌شوند و سپس تصاویر درون آن زمینه. :has() استفاده می‌شود و موضوع را تغییر نمی‌دهد، زیرا موضوع مورد نظر ما تصاویر است نه شکل‌ها:

figure:has(figcaption) img {...}

ترکیب‌ها ظاهراً بی‌پایان هستند. :has() را با کوئری‌های مقداری ترکیب کنید و طرح‌بندی‌های شبکه CSS را بر اساس تعداد فرزندان تنظیم کنید. :has() را با حالت‌های کلاس شبه تعاملی ترکیب کنید و برنامه‌هایی ایجاد کنید که به روش‌های خلاقانه جدیدی پاسخ می‌دهند.

بررسی پشتیبانی با @supports و تابع selector() آن ساده می‌شود، که قبل از استفاده، بررسی می‌کند که آیا مرورگر سینتکس را می‌فهمد یا خیر:

@supports (selector(:has(works))) {
  /* safe to use :has() */
}

منابع

۲۰۲۲ و پس از آن

هنوز تعدادی کار وجود دارد که پس از عرضه همه این ویژگی‌های شگفت‌انگیز در سال ۲۰۲۲، انجام آنها دشوار خواهد بود. بخش بعدی نگاهی به برخی از مشکلات باقی‌مانده و راه‌حل‌هایی که به‌طور فعال برای حل آنها در حال توسعه هستند، می‌اندازد. این راه‌حل‌ها تجربی هستند، حتی اگر ممکن است در مرورگرها مشخص شده یا در پشت پرچم‌ها موجود باشند.

نتیجه‌ی بخش‌های بعدی باید این باشد که مشکلات ذکر شده، افراد زیادی از شرکت‌های مختلف را به دنبال راه‌حل کرده است - نه اینکه این راه‌حل‌ها قرار است در سال ۲۰۲۳ منتشر شوند.

ویژگی‌های سفارشی با تایپ آزاد

Browser Support

  • کروم: ۸۵.
  • لبه: ۸۵.
  • فایرفاکس: ۱۲۸.
  • سافاری: ۱۶.۴

Source

ویژگی‌های سفارشی CSS شگفت‌انگیز هستند. آن‌ها امکان ذخیره انواع چیزها را درون یک متغیر نامگذاری شده فراهم می‌کنند که سپس می‌توان آن را گسترش داد، روی آن محاسبه کرد، به اشتراک گذاشت و موارد دیگر. در واقع، آن‌ها آنقدر انعطاف‌پذیر هستند که خوب می‌شد اگر برخی از آن‌ها انعطاف‌پذیری کمتری داشتند.

سناریویی را در نظر بگیرید که در آن یک box-shadow از ویژگی‌های سفارشی برای مقادیر خود استفاده می‌کند:

box-shadow: var(--x) var(--y) var(--blur) var(--spread) var(--color);

همه این‌ها به خوبی کار می‌کنند تا زمانی که هر یک از ویژگی‌ها به مقداری تغییر کنند که CSS در آنجا نمی‌پذیرد، مانند --x: red . اگر هر یک از متغیرهای تو در تو وجود نداشته باشد یا روی یک نوع مقدار نامعتبر تنظیم شده باشد، کل سایه می‌شکند.

اینجاست که @property وارد عمل می‌شود: --x می‌تواند به یک ویژگی سفارشی تایپ‌شده تبدیل شود، دیگر نه آزاد و انعطاف‌پذیر، بلکه ایمن با برخی مرزهای تعریف‌شده:

@property --x {
  syntax: '<length>';
  initial-value: 0px;
  inherits: false;
}

حالا، وقتی تابع box-shadow از var(--x) و بعد از آن --x: red استفاده می‌کند، red نادیده گرفته می‌شود زیرا یک <length> نیست. این یعنی سایه به کار خود ادامه می‌دهد، حتی اگر مقدار نامعتبری به یکی از ویژگی‌های سفارشی آن داده شده باشد. به جای شکست، به initial-value خود یعنی 0px برمی‌گردد.

انیمیشن

علاوه بر ایمنی نوع، درهای زیادی را برای انیمیشن نیز باز می‌کند. انعطاف‌پذیری سینتکس CSS، متحرک‌سازی برخی چیزها، مانند گرادیان‌ها را غیرممکن می‌کند. @property در اینجا کمک می‌کند زیرا ویژگی typed CSS می‌تواند مرورگر را در مورد قصد توسعه‌دهنده در درون درون‌یابی بیش از حد پیچیده مطلع کند. اساساً دامنه امکان را محدود می‌کند تا جایی که یک مرورگر می‌تواند جنبه‌هایی از یک سبک را که قبلاً نمی‌توانست، متحرک‌سازی کند.

این مثال آزمایشی را در نظر بگیرید، که در آن از یک گرادیان شعاعی برای ایجاد بخشی از یک پوشش استفاده می‌شود و یک جلوه فوکوس نورافکن ایجاد می‌کند. جاوا اسکریپت هنگام فشار دادن کلید alt/opt، x و y ماوس را تنظیم می‌کند و سپس اندازه کانونی را به مقدار کوچکتری مانند ۲۵٪ تغییر می‌دهد و دایره فوکوس نورافکن را در موقعیت ماوس ایجاد می‌کند:

نسخه آزمایشی را امتحان کنید
.focus-effect {
  --focal-size: 100%;
  --mouse-x: center;
  --mouse-y: center;

  mask-image: radial-gradient(
    circle at var(--mouse-x) var(--mouse-y),
    transparent 0%,
    transparent var(--focal-size),
    black 0%
  );
}

با این حال، گرادیان‌ها را نمی‌توان متحرک کرد. آن‌ها بیش از حد انعطاف‌پذیر و پیچیده هستند که مرورگر بتواند «فقط» نحوه‌ی متحرک‌سازی مورد نظر شما را تشخیص دهد. با این حال، با @property ، می‌توان یک ویژگی را تایپ و به صورت جداگانه متحرک‌سازی کرد، که مرورگر به راحتی می‌تواند منظور شما را درک کند.

بازی‌های ویدیویی که از این افکت فوکوس استفاده می‌کنند، همیشه دایره را متحرک می‌کنند، از یک دایره بزرگ گرفته تا یک دایره سوراخ سوزنی. در اینجا نحوه استفاده از @property با نسخه آزمایشی ما آمده است تا مرورگر، ماسک گرادیان را متحرک کند:

@property --focal-size {
  syntax: '<length-percentage>';
  initial-value: 100%;
  inherits: false;
}

.focus-effect {
  --focal-size: 100%;
  --mouse-x: center;
  --mouse-y: center;

  mask-image: radial-gradient(
    circle at var(--mouse-x) var(--mouse-y),
    transparent 0%,
    transparent var(--focal-size),
    black 0%
  );

  transition: --focal-size .3s ease;
}
نسخه آزمایشی را امتحان کنید

مرورگر اکنون می‌تواند اندازه گرادیان را متحرک کند، زیرا ما مساحت سطح اصلاح را به تنها یک ویژگی کاهش داده‌ایم و مقدار را تایپ کرده‌ایم تا مرورگر بتواند هوشمندانه طول‌ها را درون‌یابی کند.

@property می‌تواند کارهای خیلی بیشتری انجام دهد، اما این امکانات کوچک می‌توانند بسیار مفید باشند.

منابع

در min-width یا max-width بود

قبل از محدوده‌های پرس‌وجوی رسانه، یک پرس‌وجوی رسانه‌ای CSS min-width و max-width برای بیان شرایط over and under استفاده می‌کند. این می‌تواند چیزی شبیه به این باشد:

@media (min-width: 320px) {
  
}

پس از محدوده‌های پرس‌وجوی رسانه، همان پرس‌وجوی رسانه می‌تواند به این شکل باشد:

@media (width >= 320px) {
  
}

یک پرس‌وجوی رسانه‌ای CSS با استفاده از هر دو ویژگی min-width و max-width می‌تواند به این شکل باشد:

@media (min-width: 320px) and (max-width: 1280px) {
  
}

پس از محدوده‌های پرس‌وجوی رسانه، همان پرس‌وجوی رسانه می‌تواند به این شکل باشد:

@media (320px <= width <= 1280px) {
  
}

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

منابع

متغیرهای پرس و جوی رسانه‌ای وجود ندارد

قبل از @custom-media ، کوئری‌های مدیا مجبور بودند بارها و بارها خود را تکرار کنند، یا برای تولید خروجی مناسب بر اساس متغیرهای استاتیک در طول زمان ساخت، به پیش‌پردازنده‌ها متکی باشند.

بعد از @custom-media ، CSS امکان نامگذاری مستعار به کوئری‌های رسانه و ارجاع به آنها را درست مانند یک ویژگی سفارشی فراهم می‌کند.

نامگذاری چیزها بسیار مهم است: می‌تواند هدف را با سینتکس هماهنگ کند، و اشتراک‌گذاری چیزها و استفاده از آنها را در تیم‌ها آسان‌تر کند. در اینجا چند پرس‌وجوی رسانه‌ای سفارشی وجود دارد که بین پروژه‌ها از من پیروی می‌کنند:

@custom-media --OSdark  (prefers-color-scheme: dark);
@custom-media --OSlight (prefers-color-scheme: light);

@custom-media --pointer (hover) and (pointer: coarse);
@custom-media --mouse   (hover) and (pointer: fine);

@custom-media --xxs-and-above (width >= 240px);
@custom-media --xxs-and-below (width <= 240px);

حالا که تعریف شده‌اند، می‌توانم از یکی از آنها به این شکل استفاده کنم:

@media (--OSdark) {
  :root {
    
  }
}

لیست کاملی از مدیا کوئری‌های سفارشی که من استفاده می‌کنم را در کتابخانه‌ی ویژگی‌های سفارشی CSS خود به نام Open Props پیدا کنید.

منابع

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

قبل از @nest ، تکرار زیادی در stylesheetها وجود داشت. این امر به ویژه زمانی که selectorها طولانی بودند و هر کدام تفاوت‌های کوچکی را هدف قرار می‌دادند، دست و پا گیر می‌شد. راحتی تودرتوسازی یکی از رایج‌ترین دلایل برای پذیرش یک پیش‌پردازنده است.

بعد از @nest ‎ تکرار از بین می‌رود. تقریباً تمام ویژگی‌های تودرتوسازیِ فعال‌شده توسط پیش‌پردازنده، به‌صورت پیش‌فرض در CSS در دسترس قرار خواهند گرفت.

article {
  color: darkgray;
}

article > a {
  color: var(--link-color);
}

/* with @nest becomes */

article {
  color: darkgray;

  & > a {
    color: var(--link-color);
  }
}

What's most important about nesting to me, besides not repeating article in the nested selector, is the styling context remains within one style block. Instead of bouncing from one selector, and its styles, to another selector with styles (example 1), the reader can remain within the context of an article and see the article owns links inside of it. The relationship and style intent are bundled together, so article gets to appear to own its own styles.

The ownership could also be thought of as centralization. Instead of looking around a stylesheet for relevant styles, they can all be found nested together within a context. This works with parent to child relationships, but also with child to parent relationships.

Consider a component child that wants to adjust itself when in a different parent context, as opposed to the parent owning the style and changing a child:

/* parent owns this, adjusting children */
section:focus-within > article {
  border: 1px solid hotpink;
}

/* with @nest becomes */

/* article owns this, adjusting itself when inside a section:focus-within */
article {
  @nest section:focus-within > & {
     border: 1px solid hotpink;
  }
}

@nest helps overall with healthier style organization, centralization, and ownership. Components can group and own their own styles, instead of having them spread amongst other style blocks. It may seem small in these examples, but it can have very large impacts, for both convenience and legibility.

منابع

Scoping styles is really hard

Browser Support

  • Chrome: 118.
  • Edge: 118.
  • Firefox: 146.
  • Safari: 17.4.

Source

Before @scope , many strategies existed because styles in CSS cascade, inherit, and are globally scoped by default. These features of CSS are very convenient for many things, but for complex sites and applications, with potentially many different styles of components, the global space and nature of the cascade can make styles feel like they're leaking.

After @scope , not only can styles be scoped to only within a context, like a class, they can also articulate where the styles end and do not continue to cascade or inherit.

In the following example, BEM naming convention scoping can be reversed into the actual intent. The BEM selector is attempting to scope the color of a header element to a .card container with naming conventions. This requires that the header has this classname on it, completing the goal. With @scope , no naming conventions are required in order to complete the same goal without marking up the header element:

.card__header {
  color: var(--text);
}

/* with @scope becomes */

@scope (.card) {
  header {
    color: var(--text);
  }
}

Here's another example, less component-specific and more about the global scope nature of CSS. Dark and light themes have to coexist inside a stylesheet, where order matters in determining a winning style. Usually this means dark theme styles come after the light theme; this establishes light as the default and dark as the optional style. Avoid the ordering and scope battling with @scope :

​​@scope (.light-theme) {
  a { color: purple; }
}

@scope (.dark-theme) {
  a { color: plum; }
}

To complete the story here, @scope also allows the establishing of where the style scope ends. This can't be done with any naming convention or preprocessor; it's special and only something CSS built-in to the browser can do. In the following example, img and .content styles are exclusively applied when a child of a .media-block is a sibling or parent of .content :

@scope (.media-block) to (.content) {
  img {
    border-radius: 50%;
  }

  .content {
    padding: 1em;
  }
}

منابع

No CSS way for a masonry layout

Before CSS masonry with grid, JavaScript was the best way to achieve a masonry layout, as any of the CSS methods with columns or flexbox would inaccurately represent the content order.

After CSS masonry with grid, no JavaScript libraries will be required and the content order will be correct.

Screenshot of the masonry layout which shows numbers traveling along the top, then going down.
Image and demo from Smashing Magazine
https://www.smashingmagazine.com/native-css-masonry-layout-css-grid/

The preceding demo is achieved with the following CSS:

.container {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: masonry;
}

It's comforting to know that this is on the radar as a missing layout strategy, plus you can try it today in Firefox .

منابع

CSS can't help users reduce data

Browser Support

  • Chrome: behind a flag.
  • Edge: behind a flag.
  • Firefox: not supported.
  • سافاری: پشتیبانی نمی‌شود.

Source

Before the prefers-reduced-data media query, JavaScript and a server could change their behavior based on a user's operating system or browser "data saver" option, but CSS could not.

After the prefers-reduced-data media query, CSS can join the user experience enhancement and play its part in saving data.

@media (prefers-reduced-data: reduce) {
  picture, video {
    display: none;
  }
}

The preceding CSS is used in this media scroll component and the savings can be huge. Depending on how large the visiting viewport is, the more savings to be had on page load. Saving continues as users interact with the media scrollers. The images all have loading="lazy" attributes on them and that, combined with CSS hiding the element entirely, means a network request for the image is never made.

Screenshot of a TV show carousel interface with many thumbnails and titles shown.

For my testing, on a medium sized viewport, 40 requests and 700kb of resources were initially loaded. As a user scrolls the media selection, more requests and resources are loaded. With CSS and the reduced data media query, 10 requests and 172kb of resources are loaded. That's half a megabyte of savings and the user hasn't even scrolled any of the media, at which point there are no additional requests made.

Screenshot of a TV show carousel interface with no thumbnails and many titles shown.

There are more advantages to this reduced data experience than just data savings. More titles can be seen and there's no distracting cover images to steal attention. Many users browse in a data saver mode because they pay per megabyte of data—it's really nice to see CSS able to help out here.

منابع

Scroll snap features are too limited

Before these scroll snap proposals, writing your own JavaScript to manage a carousel, slider, or gallery could quickly get complex, with all the observers and state management. Also, if not careful, the natural scrolling speeds could get normalized by script, making user interaction feel a bit unnatural and potentially clunky.

New APIs

snapChanging()

As soon as the browser has released a snap child, this event fires. This allows UI to reflect the lack of a snap child and the indeterminate snap state of the scroller, as it's now being used and will land somewhere new.

document.querySelector('.snap-carousel').addEventListener('snapchanging', event => {
  console.log('Snap is changing', event.snappedTargetsList);
});
snapChanged()

As soon as the browser has snapped to a new child and the scroller is rested, this event fires. This lets any UI that depends on the snapped child to update and reflect the connection.

document.querySelector('.snap-carousel').addEventListener('snapchanged', event => {
  console.log('Snap changed', event.snappedTargetsList);
});
scroll-start

Scrolling doesn't always begin at the start. Consider swipeable components where swiping left or right triggers different events, or a search bar that on page load is initially hidden until you scroll to the top. This CSS property lets developers specify that a scroller should begin at a specific point.

:root { --nav-height: 100px }

.snap-scroll-y {
  scroll-start-y: var(--nav-height);
}
:snap-target

This CSS selector will match elements in a scroll snap container that are currently snapped by the browser.

.card {
  --shadow-distance: 5px;
  box-shadow: 0 var(--shadow-distance) 5px hsl(0 0% 0% / 25%);
  transition: box-shadow 350ms ease;
}

.card:snapped {
  --shadow-distance: 30px;
}

After these scroll snap proposals, making a slider, carousel, or gallery is much easier as the browser now offers conveniences for the task, eliminating observers and scroll orchestration code in favor of using built-in APIs.

It's still very early days for these CSS and JS features, but be on the lookout for polyfills that can help adoption, and testing, of them soon.

منابع

Cycling between known states

Before toggle() , only states built into the browser already could be leveraged for styling and interaction. The checkbox input, for example, has :checked , an internally managed browser state for the input that CSS is able to use for changing the element visually.

After toggle() , custom states can be created on any element for CSS to change and use for styling. It allows groups, cycling, directed toggling, and more.

In the following example, the same effect of a list item strikethrough on complete is achieved but without any checkbox elements:

<ul class='ingredients'>
   <li>1 banana
   <li>1 cup blueberries
  ...
</ul>

And the relevant CSS toggle() styles:

li {
  toggle-root: check self;
}

li:toggle(check) {
  text-decoration: line-through;
}

If you're familiar with state machines, you may notice how much crossover there is with toggle() . This feature will let developers build more of their state into CSS, hopefully resulting in clearer and more semantic ways of orchestrating interaction and state.

منابع

Customizing select elements

Before <selectmenu> , CSS didn't have the ability to customize <option> elements with rich HTML or change much about the display of a list of options. This led developers to load external libraries that recreated much of the functionality of a <select> , which ended up being a lot of work.

After <selectmenu> , developers can provide rich HTML for options elements and style them as much as they need, while still meeting accessibility requirements and providing semantic HTML.

In the following example, taken from the <selectmenu> explainer page , a new select menu is created with some basic options:

<selectmenu>
  <option>Option 1</option>
  <option>Option 2</option>
  <option>Option 3</option>
</selectmenu>

CSS can target and style the element's parts:

.my-select-menu::part(button) {
  color: white;
  background-color: red;
  padding: 5px;
  border-radius: 5px;
}

.my-select-menu::part(listbox) {
  padding: 10px;
  margin-top: 5px;
  border: 1px solid red;
  border-radius: 5px;
}

A select looking menu with red accent colors.

You can try the <selectmenu> element on Chromium in Canary with the web experiments flag enabled. Watch out in 2023 and beyond for customizable select menu elements.

منابع

Anchoring an element to another

Before anchor() , position absolute and relative were position strategies provided for developers to have child elements move around within a parent element.

After anchor() , developers can position elements to other elements, regardless of them being a child or not. It also allows developers to specify which edge to position against, and other niceties for creating position relationships between elements.

The explainer has a few great examples and code samples provided, if you're interested in learning more.

منابع