ساخت مولفه تنظیمات

یک نمای کلی از نحوه ایجاد یک جزء تنظیمات از لغزنده ها و چک باکس ها.

در این پست می‌خواهم فکری در مورد ساختن یک مؤلفه تنظیمات برای وب به اشتراک بگذارم که واکنش‌گرا باشد، از ورودی‌های متعدد دستگاه پشتیبانی کند و در مرورگرها کار کند. نسخه ی نمایشی را امتحان کنید.

نسخه ی نمایشی

اگر ویدیو را ترجیح می‌دهید یا می‌خواهید یک پیش‌نمایش UI/UX از آنچه در حال ساخت‌مان هستیم داشته باشید، در اینجا توضیح کوتاه‌تری در YouTube آورده شده است:

نمای کلی

من جنبه های این مؤلفه را به بخش های زیر تقسیم کرده ام:

  1. طرح بندی ها
  2. رنگ
  3. ورودی محدوده سفارشی
  4. ورودی چک باکس سفارشی
  5. ملاحظات دسترسی
  6. جاوا اسکریپت

طرح بندی ها

این اولین نسخه نمایشی چالش رابط کاربری گرافیکی است که تماماً CSS Grid است! در اینجا هر شبکه ای است که با Chrome DevTools برای شبکه هایلایت شده است:

خطوط رنگارنگ و پوشش‌های فاصله‌ای که به نشان دادن تمام کادرهایی که چیدمان تنظیمات را تشکیل می‌دهند کمک می‌کند

فقط برای شکاف

رایج ترین چیدمان:

foo {
  display: grid;
  gap: var(--something);
}

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

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

طرح‌بندی‌های شبکه‌ای عمودی با خطوط برجسته برجسته شده و شکاف‌ها را پر می‌کنند

عنصر fieldset ، که شامل هر گروه ورودی ( .fieldset-item ) است، gap: 1px برای ایجاد مرزهای مویی بین عناصر استفاده می کند. بدون راه حل مرزی مشکل!

شکاف پر شد
.grid {
  display: grid;
  gap: 1px;
  background: var(--bg-surface-1);

  & > .fieldset-item {
    background: var(--bg-surface-2);
  }
}
ترفند مرزی
.grid {
  display: grid;

  & > .fieldset-item {
    background: var(--bg-surface-2);

    &:not(:last-child) {
      border-bottom: 1px solid var(--bg-surface-1);
    }
  }
}

بسته بندی توری طبیعی

پیچیده‌ترین طرح‌بندی در نهایت طرح ماکرو بود، سیستم چیدمان منطقی بین <main> و <form> .

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

Flexbox و grid هر دو توانایی‌هایی را برای align-items یا align-content فراهم می‌کنند، و هنگام برخورد با عناصر بسته‌بندی، هم‌ترازی‌های چیدمان content فضا را بین کودکان به‌عنوان یک گروه توزیع می‌کنند.

main {
  display: grid;
  gap: var(--space-xl);
  place-content: center;
}

عنصر اصلی استفاده از place-content: center کوتاه‌نویسی تراز وسط به طوری که کودکان به صورت عمودی و افقی در هر دو طرح بندی یک و دو ستون در مرکز قرار گیرند.

در ویدیوی بالا مشاهده کنید که چگونه "محتوا" در مرکز باقی می ماند، حتی اگر بسته بندی اتفاق افتاده باشد.

تنظیم خودکار Minmax را تکرار کنید

<form> از یک طرح شبکه تطبیقی ​​برای هر بخش استفاده می کند. این طرح بندی بر اساس فضای موجود از یک به دو ستون تغییر می کند.

form {
  display: grid;
  gap: var(--space-xl) var(--space-xxl);
  grid-template-columns: repeat(auto-fit, minmax(min(10ch, 100%), 35ch));
  align-items: flex-start;
  max-width: 89vw;
}

این شبکه مقدار متفاوتی برای row-gap (--space-xl) نسبت به column-gap (--space-xxl) دارد تا آن لمس سفارشی را روی طرح‌بندی پاسخگو اعمال کند. وقتی ستون‌ها روی هم قرار می‌گیرند، یک شکاف بزرگ می‌خواهیم، ​​اما نه به اندازه‌ای که در یک صفحه گسترده هستیم.

ویژگی grid-template-columns از 3 تابع CSS استفاده می کند: repeat() ، minmax() و min() . Una Kravets یک پست وبلاگ طرح بندی عالی در مورد این دارد که آن را RAM می نامد.

اگر آن را با Una مقایسه کنید، 3 افزوده ویژه در چیدمان ما وجود دارد:

  • تابع min() اضافی را پاس می کنیم.
  • ما align-items: flex-start .
  • max-width: 89vw وجود دارد.

تابع min() اضافی به خوبی توسط Evan Minto در وبلاگ خود در پست Intrinsically Responsive CSS Grid با minmax() و min() توضیح داده شده است. توصیه می کنم آن را بخوانید. اصلاح تراز flex-start برای حذف اثر کشش پیش‌فرض است، به طوری که فرزندان این طرح‌بندی نیازی به داشتن ارتفاع‌های برابر نداشته باشند، آنها می‌توانند ارتفاع‌های طبیعی و ذاتی داشته باشند. ویدیوی یوتیوب یک تفکیک سریع از این تراز اضافه شده دارد.

max-width: 89vw ارزش یک تفکیک کوچک در این پست را دارد. اجازه دهید طرح بندی را با و بدون سبک اعمال شده به شما نشان دهم:

چه اتفاقی می افتد؟ هنگامی که max-width مشخص می شود، زمینه، اندازه صریح یا اندازه مشخص را برای الگوریتم چیدمان تنظیم auto-fit فراهم می کند تا بداند چند تکرار می تواند در فضا قرار گیرد. در حالی که واضح به نظر می رسد که فضا "عرض کامل" است، با توجه به مشخصات شبکه CSS، اندازه مشخص یا حداکثر اندازه باید ارائه شود. من یک اندازه حداکثر ارائه کرده ام.

بنابراین، چرا 89vw ؟ چون برای چیدمان من "کار کرد". من و چند نفر دیگر از Chrome در حال بررسی این موضوع هستیم که چرا یک مقدار معقول تر، مانند 100vw کافی نیست، و آیا این در واقع یک اشکال است.

فاصله گذاری

اکثر هماهنگی این چیدمان از یک پالت محدود فاصله، به طور دقیق 7 است.

:root {
  --space-xxs: .25rem;
  --space-xs:  .5rem;
  --space-sm:  1rem;
  --space-md:  1.5rem;
  --space-lg:  2rem;
  --space-xl:  3rem;
  --space-xxl: 6rem;
}

استفاده از این جریان ها با گرید، CSS @nest و نحو سطح 5 رسانه @ بسیار خوب است. در اینجا یک مثال، مجموعه طرح بندی کاملاً <main> از سبک ها آورده شده است.

main {
  display: grid;
  gap: var(--space-xl);
  place-content: center;
  padding: var(--space-sm);

  @media (width >= 540px) {
    & {
      padding: var(--space-lg);
    }
  }

  @media (width >= 800px) {
    & {
      padding: var(--space-xl);
    }
  }
}

شبکه‌ای با محتوای متمرکز که به‌طور پیش‌فرض به‌طور متوسط ​​(مانند تلفن همراه) پر شده است. اما با در دسترس قرار گرفتن فضای نمای بیشتر، با افزایش padding گسترش می یابد. CSS 2021 بسیار خوب به نظر می رسد!

طرح قبلی، "فقط برای شکاف" را به خاطر دارید؟ در اینجا یک نسخه کاملتر از نحوه ظاهر آنها در این مؤلفه آمده است:

header {
  display: grid;
  gap: var(--space-xxs);
}

section {
  display: grid;
  gap: var(--space-md);
}

رنگ

استفاده کنترل شده از رنگ به این طرح کمک کرد تا به عنوان رسا و در عین حال مینیمال برجسته شود. من این کار را به این صورت انجام می دهم:

:root {
  --surface1: lch(10 0 0);
  --surface2: lch(15 0 0);
  --surface3: lch(20 0 0);
  --surface4: lch(25 0 0);

  --text1: lch(95 0 0);
  --text2: lch(75 0 0);
}

من رنگ‌های سطح و متن خود را با اعداد نام‌گذاری می‌کنم، برخلاف نام‌هایی مانند surface-dark و surface-darker ، زیرا در یک جستجوی رسانه‌ای، آنها را ورق می‌زنم، و روشن و تیره معنی‌دار نخواهند بود.

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

:root {
  ...

  @media (prefers-color-scheme: light) {
    & {
      --surface1: lch(90 0 0);
      --surface2: lch(100 0 0);
      --surface3: lch(98 0 0);
      --surface4: lch(85 0 0);

      --text1: lch(20 0 0);
      --text2: lch(40 0 0);
    }
  }
}

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

LCH

بدون اینکه خیلی عمیق به زمین تئوری رنگ بپردازیم، LCH یک نحو مبتنی بر انسان است، که به نحوه درک ما از رنگ توجه می کند، نه اینکه چگونه رنگ را با ریاضی اندازه گیری می کنیم (مانند 255). این به آن یک مزیت متمایز می‌دهد زیرا انسان‌ها می‌توانند آن را راحت‌تر بنویسند و سایر انسان‌ها با این تنظیمات هماهنگ خواهند بود.

تصویری از صفحه وب pod.link/csspodcast، با قسمت Color 2: Perception کشیده شده است
در مورد رنگ ادراکی (و بیشتر!) در پادکست CSS بیاموزید

برای امروز، در این نسخه ی نمایشی، بیایید بر روی نحو و مقادیری که برای ایجاد روشن و تاریک ورق می زنم تمرکز کنیم. بیایید به 1 سطح و 1 رنگ متن نگاه کنیم:

:root {
  --surface1: lch(10 0 0);
  --text1:    lch(95 0 0);

  @media (prefers-color-scheme: light) {
    & {
      --surface1: lch(90 0 0);
      --text1:    lch(40 0 0);
    }
  }
}

--surface1: lch(10 0 0) به 10% روشنایی، 0 رنگ و 0 رنگ ترجمه می شود: یک خاکستری بی رنگ بسیار تیره. سپس، در جستجوی رسانه برای حالت نور، روشنایی با --surface1: lch(90 0 0); به 90% تغییر می کند. . و این اصل استراتژی است. فقط با تغییر سبکی بین 2 تم، حفظ نسبت کنتراست مورد نیاز طراحی یا آنچه که می تواند دسترسی را حفظ کند، شروع کنید.

امتیاز lch() در اینجا این است که سبکی انسان محور است، و ما می توانیم در مورد تغییر % نسبت به آن احساس خوبی داشته باشیم، این که از نظر ادراکی و پیوسته آن % متفاوت خواهد بود. برای مثال hsl() چندان قابل اعتماد نیست .

در صورت علاقه ، اطلاعات بیشتری در مورد فضاهای رنگی و lch() وجود دارد. داره میاد!

CSS در حال حاضر به هیچ وجه نمی تواند به این رنگ ها دسترسی داشته باشد . اجازه دهید تکرار کنم: ما در اکثر مانیتورهای مدرن به یک سوم رنگ ها دسترسی نداریم. و اینها هر رنگی نیستند، بلکه زنده ترین رنگ هایی هستند که صفحه نمایش می تواند نمایش دهد . وب سایت های ما از بین رفته اند زیرا سخت افزار مانیتور سریعتر از مشخصات CSS و پیاده سازی مرورگر تکامل یافته است.

لیا ورو

کنترل های فرم تطبیقی ​​با طرح رنگ

بسیاری از مرورگرها کنترل های تم تیره را ارسال می کنند، در حال حاضر Safari و Chromium، اما باید در CSS یا HTML مشخص کنید که طراحی شما از آنها استفاده می کند.

موارد فوق تأثیر ویژگی را از پانل Styles DevTools نشان می دهد. دمو از تگ HTML استفاده می کند که به نظر من به طور کلی مکان بهتری است:

<meta name="color-scheme" content="dark light">

در این مقاله color-scheme توسط توماس اشتاینر همه چیز را در مورد آن بیاموزید. چیزهای بیشتری از ورودی های چک باکس تیره برای به دست آوردن وجود دارد!

CSS accent-color

اخیراً فعالیت‌هایی در مورد accent-color روی عناصر فرم صورت گرفته است، که یک سبک CSS است که می‌تواند رنگ رنگ مورد استفاده در عنصر ورودی مرورگر را تغییر دهد. اطلاعات بیشتر در مورد آن را اینجا در GitHub بخوانید. من آن را در سبک های خود برای این جزء گنجانده ام. از آنجایی که مرورگرها از آن پشتیبانی می‌کنند، چک باکس‌های من بیشتر با مضمون با رنگ‌های صورتی و بنفش ظاهر می‌شوند.

input[type="checkbox"] {
  accent-color: var(--brand);
}

اسکرین شات از Chromium در لینوکس از چک باکس های صورتی

رنگ با گرادیان های ثابت و فوکوس درونی ظاهر می شود

رنگ ها زمانی که کم استفاده می شوند بیشتر ظاهر می شوند و یکی از راه هایی که من دوست دارم به آن برسم از طریق تعاملات رنگارنگ UI است.

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

  • برجسته کردن زمینه
  • ارائه بازخورد رابط کاربری در مورد «چقدر کامل» مقدار در محدوده است.
  • ارائه بازخورد رابط کاربری مبنی بر اینکه یک فیلد ورودی را می‌پذیرد.

برای ارائه بازخورد زمانی که یک عنصر در حال تعامل با یک عنصر است، CSS از کلاس :focus-within برای تغییر ظاهر عناصر مختلف استفاده می کند، بیایید .fieldset-item را تجزیه کنیم، بسیار جالب است:

.fieldset-item {
  ...

  &:focus-within {
    background: var(--surface2);

    & svg {
      fill: white;
    }

    & picture {
      clip-path: circle(50%);
      background: var(--brand-bg-gradient) fixed;
    }
  }
}

هنگامی که یکی از فرزندان این عنصر دارای تمرکز- درون است:

  1. به پس زمینه .fieldset-item رنگ سطح کنتراست بالاتری نسبت داده می شود.
  2. svg تودرتو برای کنتراست بالاتر به رنگ سفید پر شده است.
  3. clip-path <picture> به یک دایره کامل گسترش می یابد و پس زمینه با گرادیان ثابت روشن پر می شود.

محدوده سفارشی

با توجه به عنصر ورودی HTML زیر، به شما نشان خواهم داد که چگونه ظاهر آن را سفارشی کردم:

<input type="range">

3 بخش در این عنصر وجود دارد که باید آن را سفارشی کنیم:

  1. عنصر / ظرف محدوده
  2. آهنگ
  3. انگشت شست

سبک های عناصر محدوده

input[type="range"] {
  /* style setting variables */
  --track-height: .5ex;
  --track-fill: 0%;
  --thumb-size: 3ex;
  --thumb-offset: -1.25ex;
  --thumb-highlight-size: 0px;

  appearance: none;         /* clear styles, make way for mine */
  display: block;
  inline-size: 100%;        /* fill container */
  margin: 1ex 0;            /* ensure thumb isn't colliding with sibling content */
  background: transparent;  /* bg is in the track */
  outline-offset: 5px;      /* focus styles have space */
}

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

سبک های ردیابی

input[type="range"]::-webkit-slider-runnable-track {
  appearance: none; /* clear styles, make way for mine */
  block-size: var(--track-height);
  border-radius: 5ex;
  background:
    /* hard stop gradient:
        - half transparent (where colorful fill we be)
        - half dark track fill
        - 1st background image is on top
    */
    linear-gradient(
      to right,
      transparent var(--track-fill),
      var(--surface1) 0%
    ),
    /* colorful fill effect, behind track surface fill */
    var(--brand-bg-gradient) fixed;
}

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

سبک پر کردن آهنگ

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

/* grab sliders on page */
const sliders = document.querySelectorAll('input[type="range"]')

/* take a slider element, return a percentage string for use in CSS */
const rangeToPercent = slider => {
  const max = slider.getAttribute('max') || 10;
  const percent = slider.value / max * 100;

  return `${parseInt(percent)}%`;
};

/* on page load, set the fill amount */
sliders.forEach(slider => {
  slider.style.setProperty('--track-fill', rangeToPercent(slider));

  /* when a slider changes, update the fill prop */
  slider.addEventListener('input', e => {
    e.target.style.setProperty('--track-fill', rangeToPercent(e.target));
  })
})

من فکر می کنم این یک ارتقاء بصری خوب را ایجاد می کند. نوار لغزنده بدون جاوا اسکریپت عالی کار می کند، پروپ --track-fill مورد نیاز نیست، اگر وجود نداشته باشد به سادگی سبک پر نخواهد داشت. اگر جاوا اسکریپت در دسترس است، ویژگی سفارشی را پر کنید و در عین حال تغییرات کاربر را مشاهده کنید و ویژگی سفارشی را با مقدار همگام کنید.

در اینجا یک پست عالی در CSS-Tricks توسط Ana Tudor وجود دارد که تنها راه حل CSS را برای پر کردن مسیر نشان می دهد. من همچنین این عنصر range را بسیار الهام بخش یافتم.

سبک های انگشت شست

input[type="range"]::-webkit-slider-thumb {
  appearance: none; /* clear styles, make way for mine */
  cursor: ew-resize; /* cursor style to support drag direction */
  border: 3px solid var(--surface3);
  block-size: var(--thumb-size);
  inline-size: var(--thumb-size);
  margin-top: var(--thumb-offset);
  border-radius: 50%;
  background: var(--brand-bg-gradient) fixed;
}

اکثر این سبک ها برای ایجاد یک دایره زیبا هستند. دوباره گرادیان پس‌زمینه ثابت را در آنجا می‌بینید که رنگ‌های پویا انگشت‌های شست، آهنگ‌ها و عناصر SVG مرتبط را یکپارچه می‌کند. برای کمک به جداسازی تکنیک box-shadow که برای برجسته کردن شناور استفاده می‌شود، سبک‌های تعامل را جدا کردم:

@custom-media --motionOK (prefers-reduced-motion: no-preference);

::-webkit-slider-thumb {
  

  /* shadow spread is initally 0 */
  box-shadow: 0 0 0 var(--thumb-highlight-size) var(--thumb-highlight-color);

  /* if motion is OK, transition the box-shadow change */
  @media (--motionOK) {
    & {
      transition: box-shadow .1s ease;
    }
  }

  /* on hover/active state of parent, increase size prop */
  @nest input[type="range"]:is(:hover,:active) & {
    --thumb-highlight-size: 10px;
  }
}

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

اگر فقط جلوه برجسته در چک باکس ها به این راحتی بود…

انتخابگرهای مرورگر متقابل

دریافتم که برای دستیابی به سازگاری بین مرورگرها به این انتخابگرهای -webkit- و -moz- نیاز دارم:

input[type="range"] {
  &::-webkit-slider-runnable-track {}
  &::-moz-range-track {}
  &::-webkit-slider-thumb {}
  &::-moz-range-thumb {}
}

چک باکس سفارشی

با توجه به عنصر ورودی HTML زیر، به شما نشان خواهم داد که چگونه ظاهر آن را سفارشی کردم:

<input type="checkbox">

3 بخش در این عنصر وجود دارد که باید آن را سفارشی کنیم:

  1. عنصر چک باکس
  2. برچسب های مرتبط
  3. جلوه برجسته

عنصر چک باکس

input[type="checkbox"] {
  inline-size: var(--space-sm);   /* increase width */
  block-size: var(--space-sm);    /* increase height */
  outline-offset: 5px;            /* focus style enhancement */
  accent-color: var(--brand);     /* tint the input */
  position: relative;             /* prepare for an absolute pseudo element */
  transform-style: preserve-3d;   /* create a 3d z-space stacking context */
  margin: 0;
  cursor: pointer;
}

transform-style و position برای شبه عنصری که بعداً برای استایل دادن به هایلایت معرفی خواهیم کرد، آماده می شوند. در غیر این صورت، اکثراً چیزهای سبک نظری جزئی از من است. من دوست دارم مکان نما نشانگر باشد، من از خطوط طرح خارج شده خوشم می آید، چک باکس های پیش فرض خیلی کوچک هستند، و اگر accent-color پشتیبانی می شود، این چک باکس ها را در طرح رنگ برند بیاورید.

برچسب‌های چک باکس

به 2 دلیل مهم است که برای چک باکس ها برچسب ارائه کنید. اولین مورد این است که نشان دهد مقدار چک باکس برای چه چیزی استفاده می شود، برای پاسخ به "روشن یا خاموش برای چه؟" دوم این که برای UX، کاربران وب به تعامل با چک باکس ها از طریق برچسب های مرتبط خود عادت کرده اند.

ورودی
<input
  type="checkbox"
  id="text-notifications"
  name="text-notifications"
>
برچسب
<label for="text-notifications">
  <h3>Text Messages</h3>
  <small>Get notified about all text messages sent to your device</small>
</label>

روی برچسب خود، یک ویژگی for قرار دهید که با شناسه به کادر انتخاب اشاره می کند: <label for="text-notifications"> . در کادر تأیید، نام و شناسه را دو برابر کنید تا مطمئن شوید که با ابزارها و فناوری‌های مختلف مانند ماوس یا صفحه‌خوان پیدا می‌شود: <input type="checkbox" id="text-notifications" name="text-notifications"> . :hover ، :active و موارد دیگر به صورت رایگان با اتصال ارائه می شوند و راه های تعامل با فرم شما را افزایش می دهند.

برجسته کردن کادر انتخاب

من می‌خواهم رابط‌هایم را ثابت نگه دارم، و عنصر لغزنده دارای یک تصویر کوچک برجسته است که می‌خواهم با کادر انتخاب از آن استفاده کنم. تصویر بند انگشتی می‌توانست box-shadow استفاده کند و خاصیت spread برای افزایش و پایین‌کردن یک سایه دارد. با این حال، این اثر در اینجا کار نمی کند زیرا چک باکس های ما مربع هستند و باید باشند .

من توانستم به همان جلوه بصری با یک عنصر شبه و مقدار تاسف بار CSS دست پیدا کنم:

@custom-media --motionOK (prefers-reduced-motion: no-preference);

input[type="checkbox"]::before {
  --thumb-scale: .01;                        /* initial scale of highlight */
  --thumb-highlight-size: var(--space-xl);

  content: "";
  inline-size: var(--thumb-highlight-size);
  block-size: var(--thumb-highlight-size);
  clip-path: circle(50%);                     /* circle shape */
  position: absolute;                         /* this is why position relative on parent */
  top: 50%;                                   /* pop and plop technique (https://web.dev/centering-in-css#5-pop-and-plop) */
  left: 50%;
  background: var(--thumb-highlight-color);
  transform-origin: center center;            /* goal is a centered scaling circle */
  transform:                                  /* order here matters!! */
    translateX(-50%)                          /* counter balances left: 50% */
    translateY(-50%)                          /* counter balances top: 50% */
    translateZ(-1px)                          /* PUTS IT BEHIND THE CHECKBOX */
    scale(var(--thumb-scale))                 /* value we toggle for animation */
  ;
  will-change: transform;

  @media (--motionOK) {                       /* transition only if motion is OK */
    & {
      transition: transform .2s ease;
    }
  }
}

/* on hover, set scale custom property to "in" state */
input[type="checkbox"]:hover::before {
  --thumb-scale: 1;
}

ایجاد یک شبه عنصر دایره کار ساده ای است، اما قرار دادن آن در پشت عنصری که به آن متصل است سخت تر بود. قبل و بعد از اینکه درستش کردم اینجاست:

این قطعاً یک تعامل خرد است، اما برای من حفظ ثبات بصری مهم است. تکنیک مقیاس‌بندی انیمیشن همان است که در جاهای دیگر از آن استفاده کرده‌ایم. ما یک ویژگی سفارشی را روی یک مقدار جدید تنظیم می کنیم و به CSS اجازه می دهیم آن را بر اساس اولویت های حرکت انتقال دهد. ویژگی کلیدی در اینجا translateZ(-1px) است. والدین یک فضای سه بعدی ایجاد کردند و این فرزند شبه عنصر با قرار دادن کمی خود در فضای z به آن ضربه زد.

دسترسی

ویدیوی YouTube نمایش خوبی از تعامل ماوس، صفحه‌کلید و صفحه‌خوان را برای این مؤلفه تنظیمات نشان می‌دهد. من برخی از جزئیات را در اینجا فرا خواهم خواند.

انتخاب عناصر HTML

<form>
<header>
<fieldset>
<picture>
<label>
<input>

هر یک از این موارد حاوی نکات و نکاتی برای ابزار مرور کاربر است. برخی از عناصر نکات تعاملی را ارائه می‌دهند، برخی تعامل را به هم متصل می‌کنند و برخی به شکل‌دهی درخت دسترس‌پذیری که یک صفحه‌خوان پیمایش می‌کند کمک می‌کنند.

ویژگی های HTML

ما می‌توانیم عناصری را که صفحه‌خوان‌ها به آنها نیاز ندارند، پنهان کنیم، در این مورد نماد کنار نوار لغزنده:

<picture aria-hidden="true">

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

SVG یک دسته از ریاضیات است، بیایید یک عنصر <title> برای عنوان شناور رایگان ماوس و یک نظر قابل خواندن برای انسان در مورد آنچه ریاضی ایجاد می کند اضافه کنیم:

<svg viewBox="0 0 24 24">
  <title>A note icon</title>
  <path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/>
</svg>

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

جاوا اسکریپت

من قبلاً نحوه مدیریت رنگ پر کردن آهنگ از جاوا اسکریپت را پوشش داده ام، بنابراین اجازه دهید اکنون به جاوا اسکریپت مربوط به <form> نگاه کنیم:

const form = document.querySelector('form');

form.addEventListener('input', event => {
  const formData = Object.fromEntries(new FormData(form));
  console.table(formData);
})

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

یک اسکرین شات از console.table() به دست می آید که در آن داده های فرم در یک جدول نشان داده شده است

نتیجه گیری

حالا که می دانی من چگونه این کار را انجام دادم، شما چطور؟! این باعث می شود معماری اجزای سرگرم کننده ای ایجاد شود! چه کسی می خواهد نسخه اول را با اسلات در چارچوب مورد علاقه خود بسازد؟ 🙂

بیایید رویکردهای خود را متنوع کنیم و همه راه‌های ساخت در وب را بیاموزیم. یک نسخه نمایشی ایجاد کنید، پیوندها را برای من توییت کنید ، و من آن را به بخش ریمیکس های انجمن در زیر اضافه می کنم!

ریمیکس های انجمن

  • @tomayac با سبک خود در مورد ناحیه شناور برای برچسب‌های چک باکس! این نسخه هیچ شکاف شناور بین عناصر: نسخه ی نمایشی و منبع ندارد.
،

یک نمای کلی از نحوه ایجاد یک جزء تنظیمات از لغزنده ها و چک باکس ها.

در این پست می‌خواهم فکری در مورد ساختن یک مؤلفه تنظیمات برای وب به اشتراک بگذارم که واکنش‌گرا باشد، از ورودی‌های متعدد دستگاه پشتیبانی کند و در مرورگرها کار کند. نسخه ی نمایشی را امتحان کنید.

نسخه ی نمایشی

اگر ویدیو را ترجیح می‌دهید یا می‌خواهید یک پیش‌نمایش UI/UX از آنچه در حال ساخت‌مان هستیم داشته باشید، در اینجا توضیح کوتاه‌تری در YouTube آورده شده است:

نمای کلی

من جنبه های این مؤلفه را به بخش های زیر تقسیم کرده ام:

  1. طرح بندی ها
  2. رنگ
  3. ورودی محدوده سفارشی
  4. ورودی چک باکس سفارشی
  5. ملاحظات دسترسی
  6. جاوا اسکریپت

طرح بندی ها

این اولین نسخه نمایشی چالش رابط کاربری گرافیکی است که تماماً CSS Grid است! در اینجا هر شبکه ای است که با Chrome DevTools برای شبکه هایلایت شده است:

خطوط رنگارنگ و پوشش‌های فاصله‌ای که به نشان دادن تمام کادرهایی که چیدمان تنظیمات را تشکیل می‌دهند کمک می‌کند

فقط برای شکاف

رایج ترین چیدمان:

foo {
  display: grid;
  gap: var(--something);
}

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

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

طرح‌بندی‌های شبکه‌ای عمودی با خطوط برجسته برجسته شده و شکاف‌ها را پر می‌کنند

عنصر fieldset ، که شامل هر گروه ورودی ( .fieldset-item ) است، gap: 1px برای ایجاد مرزهای مویی بین عناصر استفاده می کند. بدون راه حل مرزی مشکل!

شکاف پر شد
.grid {
  display: grid;
  gap: 1px;
  background: var(--bg-surface-1);

  & > .fieldset-item {
    background: var(--bg-surface-2);
  }
}
ترفند مرزی
.grid {
  display: grid;

  & > .fieldset-item {
    background: var(--bg-surface-2);

    &:not(:last-child) {
      border-bottom: 1px solid var(--bg-surface-1);
    }
  }
}

بسته بندی توری طبیعی

پیچیده‌ترین طرح‌بندی در نهایت طرح ماکرو بود، سیستم چیدمان منطقی بین <main> و <form> .

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

Flexbox و grid هر دو توانایی‌هایی را برای align-items یا align-content فراهم می‌کنند، و هنگام برخورد با عناصر بسته‌بندی، هم‌ترازی‌های چیدمان content فضا را بین کودکان به‌عنوان یک گروه توزیع می‌کنند.

main {
  display: grid;
  gap: var(--space-xl);
  place-content: center;
}

عنصر اصلی استفاده از place-content: center کوتاه‌نویسی تراز وسط به طوری که کودکان به صورت عمودی و افقی در هر دو طرح بندی یک و دو ستون در مرکز قرار گیرند.

در ویدیوی بالا مشاهده کنید که چگونه "محتوا" در مرکز باقی می ماند، حتی اگر بسته بندی اتفاق افتاده باشد.

تنظیم خودکار Minmax را تکرار کنید

<form> از یک طرح شبکه تطبیقی ​​برای هر بخش استفاده می کند. این طرح بندی بر اساس فضای موجود از یک به دو ستون تغییر می کند.

form {
  display: grid;
  gap: var(--space-xl) var(--space-xxl);
  grid-template-columns: repeat(auto-fit, minmax(min(10ch, 100%), 35ch));
  align-items: flex-start;
  max-width: 89vw;
}

این شبکه مقدار متفاوتی برای row-gap (--space-xl) نسبت به column-gap (--space-xxl) دارد تا آن لمس سفارشی را روی طرح‌بندی پاسخگو اعمال کند. وقتی ستون‌ها روی هم قرار می‌گیرند، یک شکاف بزرگ می‌خواهیم، ​​اما نه به اندازه‌ای که در یک صفحه گسترده هستیم.

ویژگی grid-template-columns از 3 تابع CSS استفاده می کند: repeat() ، minmax() و min() . Una Kravets یک پست وبلاگ طرح بندی عالی در مورد این دارد که آن را RAM می نامد.

اگر آن را با Una مقایسه کنید، 3 افزوده ویژه در چیدمان ما وجود دارد:

  • تابع min() اضافی را پاس می کنیم.
  • ما align-items: flex-start .
  • max-width: 89vw وجود دارد.

تابع min() اضافی به خوبی توسط Evan Minto در وبلاگ خود در پست Intrinsically Responsive CSS Grid با minmax() و min() توضیح داده شده است. توصیه می کنم آن را بخوانید. اصلاح تراز flex-start برای حذف اثر کشش پیش‌فرض است، به طوری که فرزندان این طرح‌بندی نیازی به داشتن ارتفاع‌های برابر نداشته باشند، آنها می‌توانند ارتفاع‌های طبیعی و ذاتی داشته باشند. ویدیوی یوتیوب یک تفکیک سریع از این تراز اضافه شده دارد.

max-width: 89vw ارزش یک تفکیک کوچک در این پست را دارد. اجازه دهید طرح بندی را با و بدون سبک اعمال شده به شما نشان دهم:

چه اتفاقی می افتد؟ هنگامی که max-width مشخص می شود، زمینه، اندازه صریح یا اندازه مشخص را برای الگوریتم چیدمان تنظیم auto-fit فراهم می کند تا بداند چند تکرار می تواند در فضا قرار گیرد. در حالی که واضح به نظر می رسد که فضا "عرض کامل" است، با توجه به مشخصات شبکه CSS، اندازه مشخص یا حداکثر اندازه باید ارائه شود. من یک اندازه حداکثر ارائه کرده ام.

بنابراین، چرا 89vw ؟ چون برای چیدمان من "کار کرد". من و چند نفر دیگر از Chrome در حال بررسی این موضوع هستیم که چرا یک مقدار معقول تر، مانند 100vw کافی نیست، و آیا این در واقع یک اشکال است.

فاصله گذاری

اکثر هماهنگی این چیدمان از یک پالت محدود فاصله، به طور دقیق 7 است.

:root {
  --space-xxs: .25rem;
  --space-xs:  .5rem;
  --space-sm:  1rem;
  --space-md:  1.5rem;
  --space-lg:  2rem;
  --space-xl:  3rem;
  --space-xxl: 6rem;
}

استفاده از این جریان ها با گرید، CSS @nest و نحو سطح 5 رسانه @ بسیار خوب است. در اینجا یک مثال، مجموعه طرح بندی کاملاً <main> از سبک ها آورده شده است.

main {
  display: grid;
  gap: var(--space-xl);
  place-content: center;
  padding: var(--space-sm);

  @media (width >= 540px) {
    & {
      padding: var(--space-lg);
    }
  }

  @media (width >= 800px) {
    & {
      padding: var(--space-xl);
    }
  }
}

شبکه‌ای با محتوای متمرکز که به‌طور پیش‌فرض به‌طور متوسط ​​(مانند تلفن همراه) پر شده است. اما با در دسترس قرار گرفتن فضای نمای بیشتر، با افزایش padding گسترش می یابد. CSS 2021 بسیار خوب به نظر می رسد!

طرح قبلی، "فقط برای شکاف" را به خاطر دارید؟ در اینجا یک نسخه کاملتر از نحوه ظاهر آنها در این مؤلفه آمده است:

header {
  display: grid;
  gap: var(--space-xxs);
}

section {
  display: grid;
  gap: var(--space-md);
}

رنگ

استفاده کنترل شده از رنگ به این طرح کمک کرد تا به عنوان رسا و در عین حال مینیمال برجسته شود. من این کار را به این صورت انجام می دهم:

:root {
  --surface1: lch(10 0 0);
  --surface2: lch(15 0 0);
  --surface3: lch(20 0 0);
  --surface4: lch(25 0 0);

  --text1: lch(95 0 0);
  --text2: lch(75 0 0);
}

من رنگ‌های سطح و متن خود را با اعداد نام‌گذاری می‌کنم، برخلاف نام‌هایی مانند surface-dark و surface-darker ، زیرا در یک جستجوی رسانه‌ای، آنها را ورق می‌زنم، و روشن و تیره معنی‌دار نخواهند بود.

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

:root {
  ...

  @media (prefers-color-scheme: light) {
    & {
      --surface1: lch(90 0 0);
      --surface2: lch(100 0 0);
      --surface3: lch(98 0 0);
      --surface4: lch(85 0 0);

      --text1: lch(20 0 0);
      --text2: lch(40 0 0);
    }
  }
}

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

LCH

بدون اینکه خیلی عمیق به زمین تئوری رنگ بپردازیم، LCH یک نحو مبتنی بر انسان است، که به نحوه درک ما از رنگ توجه می کند، نه اینکه چگونه رنگ را با ریاضی اندازه گیری می کنیم (مانند 255). این به آن یک مزیت متمایز می‌دهد زیرا انسان‌ها می‌توانند آن را راحت‌تر بنویسند و سایر انسان‌ها با این تنظیمات هماهنگ خواهند بود.

تصویری از صفحه وب pod.link/csspodcast، با قسمت Color 2: Perception کشیده شده است
در مورد رنگ ادراکی (و بیشتر!) در پادکست CSS بیاموزید

برای امروز، در این نسخه ی نمایشی، بیایید بر روی نحو و مقادیری که برای ایجاد روشن و تاریک ورق می زنم تمرکز کنیم. بیایید به 1 سطح و 1 رنگ متن نگاه کنیم:

:root {
  --surface1: lch(10 0 0);
  --text1:    lch(95 0 0);

  @media (prefers-color-scheme: light) {
    & {
      --surface1: lch(90 0 0);
      --text1:    lch(40 0 0);
    }
  }
}

--surface1: lch(10 0 0) به 10% روشنایی، 0 رنگ و 0 رنگ ترجمه می شود: یک خاکستری بی رنگ بسیار تیره. سپس، در جستجوی رسانه برای حالت نور، روشنایی با --surface1: lch(90 0 0); به 90% تغییر می کند. . و این اصل استراتژی است. فقط با تغییر سبکی بین 2 تم، حفظ نسبت کنتراست مورد نیاز طراحی یا آنچه که می تواند دسترسی را حفظ کند، شروع کنید.

امتیاز lch() در اینجا این است که سبکی انسان محور است، و ما می توانیم در مورد تغییر % نسبت به آن احساس خوبی داشته باشیم، این که از نظر ادراکی و پیوسته آن % متفاوت خواهد بود. برای مثال hsl() چندان قابل اعتماد نیست .

در صورت علاقه ، اطلاعات بیشتری در مورد فضاهای رنگی و lch() وجود دارد. داره میاد!

CSS در حال حاضر به هیچ وجه نمی تواند به این رنگ ها دسترسی داشته باشد . اجازه دهید تکرار کنم: ما در اکثر مانیتورهای مدرن به یک سوم رنگ ها دسترسی نداریم. و اینها هر رنگی نیستند، بلکه زنده ترین رنگ هایی هستند که صفحه نمایش می تواند نمایش دهد . وب سایت های ما از بین رفته اند زیرا سخت افزار مانیتور سریعتر از مشخصات CSS و پیاده سازی مرورگر تکامل یافته است.

لیا ورو

کنترل های فرم تطبیقی ​​با طرح رنگ

بسیاری از مرورگرها کنترل های تم تیره را ارسال می کنند، در حال حاضر Safari و Chromium، اما باید در CSS یا HTML مشخص کنید که طراحی شما از آنها استفاده می کند.

موارد فوق تأثیر ویژگی را از پانل Styles DevTools نشان می دهد. دمو از تگ HTML استفاده می کند که به نظر من به طور کلی مکان بهتری است:

<meta name="color-scheme" content="dark light">

در این مقاله color-scheme توسط توماس اشتاینر همه چیز را در مورد آن بیاموزید. چیزهای بیشتری از ورودی های چک باکس تیره برای به دست آوردن وجود دارد!

CSS accent-color

اخیراً فعالیت‌هایی در مورد accent-color روی عناصر فرم صورت گرفته است، که یک سبک CSS است که می‌تواند رنگ رنگ مورد استفاده در عنصر ورودی مرورگر را تغییر دهد. اطلاعات بیشتر در مورد آن را اینجا در GitHub بخوانید. من آن را در سبک های خود برای این جزء گنجانده ام. از آنجایی که مرورگرها از آن پشتیبانی می‌کنند، چک باکس‌های من بیشتر با مضمون با رنگ‌های صورتی و بنفش ظاهر می‌شوند.

input[type="checkbox"] {
  accent-color: var(--brand);
}

اسکرین شات از Chromium در لینوکس از چک باکس های صورتی

رنگ با گرادیان های ثابت و فوکوس درونی ظاهر می شود

رنگ ها زمانی که کم استفاده می شوند بیشتر ظاهر می شوند و یکی از راه هایی که من دوست دارم به آن برسم از طریق تعاملات رنگارنگ UI است.

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

  • برجسته کردن زمینه
  • ارائه بازخورد رابط کاربری در مورد «چقدر کامل» مقدار در محدوده است.
  • ارائه بازخورد رابط کاربری مبنی بر اینکه یک فیلد ورودی را می‌پذیرد.

برای ارائه بازخورد زمانی که یک عنصر در حال تعامل با یک عنصر است، CSS از کلاس :focus-within برای تغییر ظاهر عناصر مختلف استفاده می کند، بیایید .fieldset-item را تجزیه کنیم، بسیار جالب است:

.fieldset-item {
  ...

  &:focus-within {
    background: var(--surface2);

    & svg {
      fill: white;
    }

    & picture {
      clip-path: circle(50%);
      background: var(--brand-bg-gradient) fixed;
    }
  }
}

هنگامی که یکی از فرزندان این عنصر دارای تمرکز- درون است:

  1. به پس زمینه .fieldset-item رنگ سطح کنتراست بالاتری نسبت داده می شود.
  2. svg تودرتو برای کنتراست بالاتر به رنگ سفید پر شده است.
  3. clip-path <picture> به یک دایره کامل گسترش می یابد و پس زمینه با گرادیان ثابت روشن پر می شود.

محدوده سفارشی

با توجه به عنصر ورودی HTML زیر، به شما نشان خواهم داد که چگونه ظاهر آن را سفارشی کردم:

<input type="range">

3 بخش در این عنصر وجود دارد که باید آن را سفارشی کنیم:

  1. عنصر / ظرف محدوده
  2. آهنگ
  3. انگشت شست

سبک های عناصر محدوده

input[type="range"] {
  /* style setting variables */
  --track-height: .5ex;
  --track-fill: 0%;
  --thumb-size: 3ex;
  --thumb-offset: -1.25ex;
  --thumb-highlight-size: 0px;

  appearance: none;         /* clear styles, make way for mine */
  display: block;
  inline-size: 100%;        /* fill container */
  margin: 1ex 0;            /* ensure thumb isn't colliding with sibling content */
  background: transparent;  /* bg is in the track */
  outline-offset: 5px;      /* focus styles have space */
}

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

سبک های ردیابی

input[type="range"]::-webkit-slider-runnable-track {
  appearance: none; /* clear styles, make way for mine */
  block-size: var(--track-height);
  border-radius: 5ex;
  background:
    /* hard stop gradient:
        - half transparent (where colorful fill we be)
        - half dark track fill
        - 1st background image is on top
    */
    linear-gradient(
      to right,
      transparent var(--track-fill),
      var(--surface1) 0%
    ),
    /* colorful fill effect, behind track surface fill */
    var(--brand-bg-gradient) fixed;
}

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

سبک پر کردن آهنگ

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

/* grab sliders on page */
const sliders = document.querySelectorAll('input[type="range"]')

/* take a slider element, return a percentage string for use in CSS */
const rangeToPercent = slider => {
  const max = slider.getAttribute('max') || 10;
  const percent = slider.value / max * 100;

  return `${parseInt(percent)}%`;
};

/* on page load, set the fill amount */
sliders.forEach(slider => {
  slider.style.setProperty('--track-fill', rangeToPercent(slider));

  /* when a slider changes, update the fill prop */
  slider.addEventListener('input', e => {
    e.target.style.setProperty('--track-fill', rangeToPercent(e.target));
  })
})

من فکر می کنم این یک ارتقاء بصری خوب را ایجاد می کند. نوار لغزنده بدون جاوا اسکریپت عالی کار می کند، پروپ --track-fill مورد نیاز نیست، اگر وجود نداشته باشد به سادگی سبک پر نخواهد داشت. اگر جاوا اسکریپت در دسترس است، ویژگی سفارشی را پر کنید و در عین حال تغییرات کاربر را مشاهده کنید و ویژگی سفارشی را با مقدار همگام کنید.

در اینجا یک پست عالی در CSS-Tricks توسط Ana Tudor وجود دارد که تنها راه حل CSS را برای پر کردن مسیر نشان می دهد. من همچنین این عنصر range را بسیار الهام بخش یافتم.

سبک های انگشت شست

input[type="range"]::-webkit-slider-thumb {
  appearance: none; /* clear styles, make way for mine */
  cursor: ew-resize; /* cursor style to support drag direction */
  border: 3px solid var(--surface3);
  block-size: var(--thumb-size);
  inline-size: var(--thumb-size);
  margin-top: var(--thumb-offset);
  border-radius: 50%;
  background: var(--brand-bg-gradient) fixed;
}

اکثر این سبک ها برای ایجاد یک دایره زیبا هستند. دوباره گرادیان پس‌زمینه ثابت را در آنجا می‌بینید که رنگ‌های پویا انگشت‌های شست، آهنگ‌ها و عناصر SVG مرتبط را یکپارچه می‌کند. برای کمک به جداسازی تکنیک box-shadow که برای برجسته کردن شناور استفاده می‌شود، سبک‌های تعامل را جدا کردم:

@custom-media --motionOK (prefers-reduced-motion: no-preference);

::-webkit-slider-thumb {
  

  /* shadow spread is initally 0 */
  box-shadow: 0 0 0 var(--thumb-highlight-size) var(--thumb-highlight-color);

  /* if motion is OK, transition the box-shadow change */
  @media (--motionOK) {
    & {
      transition: box-shadow .1s ease;
    }
  }

  /* on hover/active state of parent, increase size prop */
  @nest input[type="range"]:is(:hover,:active) & {
    --thumb-highlight-size: 10px;
  }
}

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

اگر فقط جلوه برجسته در چک باکس ها به این راحتی بود…

انتخابگرهای مرورگر متقابل

دریافتم که برای دستیابی به سازگاری بین مرورگرها به این انتخابگرهای -webkit- و -moz- نیاز دارم:

input[type="range"] {
  &::-webkit-slider-runnable-track {}
  &::-moz-range-track {}
  &::-webkit-slider-thumb {}
  &::-moz-range-thumb {}
}

چک باکس سفارشی

با توجه به عنصر ورودی HTML زیر، به شما نشان خواهم داد که چگونه ظاهر آن را سفارشی کردم:

<input type="checkbox">

3 بخش در این عنصر وجود دارد که باید آن را سفارشی کنیم:

  1. عنصر چک باکس
  2. برچسب های مرتبط
  3. جلوه برجسته

عنصر چک باکس

input[type="checkbox"] {
  inline-size: var(--space-sm);   /* increase width */
  block-size: var(--space-sm);    /* increase height */
  outline-offset: 5px;            /* focus style enhancement */
  accent-color: var(--brand);     /* tint the input */
  position: relative;             /* prepare for an absolute pseudo element */
  transform-style: preserve-3d;   /* create a 3d z-space stacking context */
  margin: 0;
  cursor: pointer;
}

transform-style و position برای شبه عنصری که بعداً برای استایل دادن به هایلایت معرفی خواهیم کرد، آماده می شوند. در غیر این صورت، اکثراً چیزهای سبک نظری جزئی از من است. من دوست دارم مکان نما نشانگر باشد، من از خطوط طرح خارج شده خوشم می آید، چک باکس های پیش فرض خیلی کوچک هستند، و اگر accent-color پشتیبانی می شود، این چک باکس ها را در طرح رنگ برند بیاورید.

برچسب‌های چک باکس

به 2 دلیل مهم است که برای چک باکس ها برچسب ارائه کنید. اولین مورد این است که نشان دهد مقدار چک باکس برای چه چیزی استفاده می شود، برای پاسخ به "روشن یا خاموش برای چه؟" دوم این که برای UX، کاربران وب به تعامل با چک باکس ها از طریق برچسب های مرتبط خود عادت کرده اند.

ورودی
<input
  type="checkbox"
  id="text-notifications"
  name="text-notifications"
>
برچسب زدن
<label for="text-notifications">
  <h3>Text Messages</h3>
  <small>Get notified about all text messages sent to your device</small>
</label>

روی برچسب خود، یک ویژگی for قرار دهید که با شناسه به کادر انتخاب اشاره می کند: <label for="text-notifications"> . در کادر تأیید، نام و شناسه را دو برابر کنید تا مطمئن شوید که با ابزارها و فناوری‌های مختلف مانند ماوس یا صفحه‌خوان پیدا می‌شود: <input type="checkbox" id="text-notifications" name="text-notifications"> . :hover ، :active و موارد دیگر به صورت رایگان با اتصال ارائه می شوند و راه های تعامل با فرم شما را افزایش می دهند.

برجسته کردن کادر انتخاب

من می‌خواهم رابط‌هایم را ثابت نگه دارم، و عنصر لغزنده دارای یک تصویر کوچک برجسته است که می‌خواهم با کادر انتخاب از آن استفاده کنم. تصویر بند انگشتی می‌توانست box-shadow استفاده کند و خاصیت spread برای افزایش و پایین‌کردن یک سایه دارد. با این حال، این اثر در اینجا کار نمی کند زیرا چک باکس های ما مربع هستند و باید باشند .

من توانستم به همان جلوه بصری با یک عنصر شبه و مقدار تاسف بار CSS دست پیدا کنم:

@custom-media --motionOK (prefers-reduced-motion: no-preference);

input[type="checkbox"]::before {
  --thumb-scale: .01;                        /* initial scale of highlight */
  --thumb-highlight-size: var(--space-xl);

  content: "";
  inline-size: var(--thumb-highlight-size);
  block-size: var(--thumb-highlight-size);
  clip-path: circle(50%);                     /* circle shape */
  position: absolute;                         /* this is why position relative on parent */
  top: 50%;                                   /* pop and plop technique (https://web.dev/centering-in-css#5-pop-and-plop) */
  left: 50%;
  background: var(--thumb-highlight-color);
  transform-origin: center center;            /* goal is a centered scaling circle */
  transform:                                  /* order here matters!! */
    translateX(-50%)                          /* counter balances left: 50% */
    translateY(-50%)                          /* counter balances top: 50% */
    translateZ(-1px)                          /* PUTS IT BEHIND THE CHECKBOX */
    scale(var(--thumb-scale))                 /* value we toggle for animation */
  ;
  will-change: transform;

  @media (--motionOK) {                       /* transition only if motion is OK */
    & {
      transition: transform .2s ease;
    }
  }
}

/* on hover, set scale custom property to "in" state */
input[type="checkbox"]:hover::before {
  --thumb-scale: 1;
}

ایجاد یک شبه عنصر دایره کار ساده ای است، اما قرار دادن آن در پشت عنصری که به آن متصل است سخت تر بود. قبل و بعد از اینکه درستش کردم اینجاست:

این قطعاً یک تعامل خرد است، اما برای من حفظ ثبات بصری مهم است. تکنیک مقیاس‌بندی انیمیشن همان است که در جاهای دیگر از آن استفاده کرده‌ایم. ما یک ویژگی سفارشی را روی یک مقدار جدید تنظیم می کنیم و به CSS اجازه می دهیم آن را بر اساس اولویت های حرکت انتقال دهد. ویژگی کلیدی در اینجا translateZ(-1px) است. والدین یک فضای سه بعدی ایجاد کردند و این فرزند شبه عنصر با قرار دادن کمی خود در فضای z به آن ضربه زد.

دسترسی

ویدیوی YouTube نمایش خوبی از تعامل ماوس، صفحه‌کلید و صفحه‌خوان را برای این مؤلفه تنظیمات نشان می‌دهد. من برخی از جزئیات را در اینجا فرا خواهم خواند.

انتخاب عناصر HTML

<form>
<header>
<fieldset>
<picture>
<label>
<input>

هر یک از این موارد حاوی نکات و نکاتی برای ابزار مرور کاربر است. برخی از عناصر نکات تعاملی را ارائه می‌دهند، برخی تعامل را به هم متصل می‌کنند و برخی به شکل‌دهی درخت دسترس‌پذیری که یک صفحه‌خوان پیمایش می‌کند کمک می‌کنند.

ویژگی های HTML

ما می‌توانیم عناصری را که صفحه‌خوان‌ها به آنها نیاز ندارند، پنهان کنیم، در این مورد نماد کنار نوار لغزنده:

<picture aria-hidden="true">

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

SVG یک دسته از ریاضیات است، بیایید یک عنصر <title> برای عنوان شناور رایگان ماوس و یک نظر قابل خواندن برای انسان در مورد آنچه ریاضی ایجاد می کند اضافه کنیم:

<svg viewBox="0 0 24 24">
  <title>A note icon</title>
  <path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/>
</svg>

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

جاوا اسکریپت

من قبلاً نحوه مدیریت رنگ پر کردن آهنگ از جاوا اسکریپت را پوشش داده ام، بنابراین اجازه دهید اکنون به جاوا اسکریپت مربوط به <form> نگاه کنیم:

const form = document.querySelector('form');

form.addEventListener('input', event => {
  const formData = Object.fromEntries(new FormData(form));
  console.table(formData);
})

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

یک اسکرین شات از console.table() به دست می آید که در آن داده های فرم در یک جدول نشان داده شده است

نتیجه گیری

حالا که می دانی من چگونه این کار را انجام دادم، شما چطور؟! این باعث می شود معماری اجزای سرگرم کننده ای ایجاد شود! چه کسی می خواهد نسخه اول را با اسلات در چارچوب مورد علاقه خود بسازد؟ 🙂

بیایید رویکردهای خود را متنوع کنیم و همه راه‌های ساخت در وب را بیاموزیم. یک نسخه نمایشی ایجاد کنید، پیوندها را برای من توییت کنید ، و من آن را به بخش ریمیکس های انجمن در زیر اضافه می کنم!

ریمیکس های انجمن

  • @tomayac با سبک خود در مورد ناحیه شناور برای برچسب‌های چک باکس! این نسخه هیچ شکاف شناور بین عناصر: نسخه ی نمایشی و منبع ندارد.
،

یک نمای کلی از نحوه ایجاد یک جزء تنظیمات از لغزنده ها و چک باکس ها.

در این پست می‌خواهم فکری در مورد ساختن یک مؤلفه تنظیمات برای وب به اشتراک بگذارم که واکنش‌گرا باشد، از ورودی‌های متعدد دستگاه پشتیبانی کند و در مرورگرها کار کند. نسخه ی نمایشی را امتحان کنید.

نسخه ی نمایشی

اگر ویدیو را ترجیح می‌دهید یا می‌خواهید یک پیش‌نمایش UI/UX از آنچه در حال ساخت‌مان هستیم داشته باشید، در اینجا توضیح کوتاه‌تری در YouTube آورده شده است:

نمای کلی

من جنبه های این مؤلفه را به بخش های زیر تقسیم کرده ام:

  1. طرح بندی ها
  2. رنگ
  3. ورودی محدوده سفارشی
  4. ورودی چک باکس سفارشی
  5. ملاحظات دسترسی
  6. جاوا اسکریپت

طرح بندی ها

این اولین نسخه نمایشی چالش رابط کاربری گرافیکی است که تماماً CSS Grid است! در اینجا هر شبکه ای است که با Chrome DevTools برای شبکه هایلایت شده است:

خطوط رنگارنگ و پوشش‌های فاصله‌ای که به نشان دادن تمام کادرهایی که چیدمان تنظیمات را تشکیل می‌دهند کمک می‌کند

فقط برای شکاف

رایج ترین چیدمان:

foo {
  display: grid;
  gap: var(--something);
}

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

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

طرح‌بندی‌های شبکه‌ای عمودی با خطوط برجسته برجسته شده و شکاف‌ها را پر می‌کنند

عنصر fieldset ، که شامل هر گروه ورودی ( .fieldset-item ) است، gap: 1px برای ایجاد مرزهای مویی بین عناصر استفاده می کند. بدون راه حل مرزی مشکل!

شکاف پر شد
.grid {
  display: grid;
  gap: 1px;
  background: var(--bg-surface-1);

  & > .fieldset-item {
    background: var(--bg-surface-2);
  }
}
ترفند مرزی
.grid {
  display: grid;

  & > .fieldset-item {
    background: var(--bg-surface-2);

    &:not(:last-child) {
      border-bottom: 1px solid var(--bg-surface-1);
    }
  }
}

بسته بندی توری طبیعی

پیچیده‌ترین طرح‌بندی در نهایت طرح ماکرو بود، سیستم چیدمان منطقی بین <main> و <form> .

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

Flexbox و grid هر دو توانایی‌هایی را برای align-items یا align-content فراهم می‌کنند، و هنگام برخورد با عناصر بسته‌بندی، هم‌ترازی‌های چیدمان content فضا را بین کودکان به‌عنوان یک گروه توزیع می‌کنند.

main {
  display: grid;
  gap: var(--space-xl);
  place-content: center;
}

عنصر اصلی استفاده از place-content: center کوتاه‌نویسی تراز وسط به طوری که کودکان به صورت عمودی و افقی در هر دو طرح بندی یک و دو ستون در مرکز قرار گیرند.

در ویدیوی بالا مشاهده کنید که چگونه "محتوا" در مرکز باقی می ماند، حتی اگر بسته بندی اتفاق افتاده باشد.

تنظیم خودکار Minmax را تکرار کنید

<form> از یک طرح شبکه تطبیقی ​​برای هر بخش استفاده می کند. این طرح بندی بر اساس فضای موجود از یک به دو ستون تغییر می کند.

form {
  display: grid;
  gap: var(--space-xl) var(--space-xxl);
  grid-template-columns: repeat(auto-fit, minmax(min(10ch, 100%), 35ch));
  align-items: flex-start;
  max-width: 89vw;
}

این شبکه مقدار متفاوتی برای row-gap (--space-xl) نسبت به column-gap (--space-xxl) دارد تا آن لمس سفارشی را روی طرح‌بندی پاسخگو اعمال کند. وقتی ستون‌ها روی هم قرار می‌گیرند، یک شکاف بزرگ می‌خواهیم، ​​اما نه به اندازه‌ای که در یک صفحه گسترده هستیم.

ویژگی grid-template-columns از 3 تابع CSS استفاده می کند: repeat() ، minmax() و min() . Una Kravets یک پست وبلاگ طرح بندی عالی در مورد این دارد که آن را RAM می نامد.

اگر آن را با Una مقایسه کنید، 3 افزوده ویژه در چیدمان ما وجود دارد:

  • تابع min() اضافی را پاس می کنیم.
  • ما align-items: flex-start .
  • max-width: 89vw وجود دارد.

تابع min() اضافی به خوبی توسط Evan Minto در وبلاگ خود در پست Intrinsically Responsive CSS Grid با minmax() و min() توضیح داده شده است. توصیه می کنم آن را بخوانید. اصلاح تراز flex-start برای حذف اثر کشش پیش‌فرض است، به طوری که فرزندان این طرح‌بندی نیازی به داشتن ارتفاع‌های برابر نداشته باشند، آنها می‌توانند ارتفاع‌های طبیعی و ذاتی داشته باشند. ویدیوی یوتیوب یک تفکیک سریع از این تراز اضافه شده دارد.

max-width: 89vw ارزش یک تفکیک کوچک در این پست را دارد. اجازه دهید طرح بندی را با و بدون سبک اعمال شده به شما نشان دهم:

چه اتفاقی می افتد؟ هنگامی که max-width مشخص می شود، زمینه، اندازه صریح یا اندازه مشخص را برای الگوریتم چیدمان تنظیم auto-fit فراهم می کند تا بداند چند تکرار می تواند در فضا قرار گیرد. در حالی که واضح به نظر می رسد که فضا "عرض کامل" است، با توجه به مشخصات شبکه CSS، اندازه مشخص یا حداکثر اندازه باید ارائه شود. من یک اندازه حداکثر ارائه کرده ام.

بنابراین، چرا 89vw ؟ چون برای چیدمان من "کار کرد". من و چند نفر دیگر از Chrome در حال بررسی این موضوع هستیم که چرا یک مقدار معقول تر، مانند 100vw کافی نیست، و آیا این در واقع یک اشکال است.

فاصله گذاری

اکثر هماهنگی این چیدمان از یک پالت محدود فاصله، به طور دقیق 7 است.

:root {
  --space-xxs: .25rem;
  --space-xs:  .5rem;
  --space-sm:  1rem;
  --space-md:  1.5rem;
  --space-lg:  2rem;
  --space-xl:  3rem;
  --space-xxl: 6rem;
}

استفاده از این جریان ها با گرید، CSS @nest و نحو سطح 5 رسانه @ بسیار خوب است. در اینجا یک مثال، مجموعه طرح بندی کاملاً <main> از سبک ها آورده شده است.

main {
  display: grid;
  gap: var(--space-xl);
  place-content: center;
  padding: var(--space-sm);

  @media (width >= 540px) {
    & {
      padding: var(--space-lg);
    }
  }

  @media (width >= 800px) {
    & {
      padding: var(--space-xl);
    }
  }
}

شبکه‌ای با محتوای متمرکز که به‌طور پیش‌فرض به‌طور متوسط ​​(مانند تلفن همراه) پر شده است. اما با در دسترس قرار گرفتن فضای نمای بیشتر، با افزایش padding گسترش می یابد. CSS 2021 بسیار خوب به نظر می رسد!

طرح قبلی، "فقط برای شکاف" را به خاطر دارید؟ در اینجا یک نسخه کاملتر از نحوه ظاهر آنها در این مؤلفه آمده است:

header {
  display: grid;
  gap: var(--space-xxs);
}

section {
  display: grid;
  gap: var(--space-md);
}

رنگ

استفاده کنترل شده از رنگ به این طرح کمک کرد تا به عنوان رسا و در عین حال مینیمال برجسته شود. من این کار را به این صورت انجام می دهم:

:root {
  --surface1: lch(10 0 0);
  --surface2: lch(15 0 0);
  --surface3: lch(20 0 0);
  --surface4: lch(25 0 0);

  --text1: lch(95 0 0);
  --text2: lch(75 0 0);
}

من رنگ‌های سطح و متن خود را با اعداد نام‌گذاری می‌کنم، برخلاف نام‌هایی مانند surface-dark و surface-darker ، زیرا در یک جستجوی رسانه‌ای، آنها را ورق می‌زنم، و روشن و تیره معنی‌دار نخواهند بود.

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

:root {
  ...

  @media (prefers-color-scheme: light) {
    & {
      --surface1: lch(90 0 0);
      --surface2: lch(100 0 0);
      --surface3: lch(98 0 0);
      --surface4: lch(85 0 0);

      --text1: lch(20 0 0);
      --text2: lch(40 0 0);
    }
  }
}

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

LCH

بدون اینکه خیلی عمیق به زمین تئوری رنگ بپردازیم، LCH یک نحو مبتنی بر انسان است، که به نحوه درک ما از رنگ توجه می کند، نه اینکه چگونه رنگ را با ریاضی اندازه گیری می کنیم (مانند 255). این به آن یک مزیت متمایز می‌دهد زیرا انسان‌ها می‌توانند آن را راحت‌تر بنویسند و سایر انسان‌ها با این تنظیمات هماهنگ خواهند بود.

تصویری از صفحه وب pod.link/csspodcast، با قسمت Color 2: Perception کشیده شده است
در مورد رنگ ادراکی (و بیشتر!) در پادکست CSS بیاموزید

برای امروز، در این نسخه ی نمایشی، بیایید بر روی نحو و مقادیری که برای ایجاد روشن و تاریک ورق می زنم تمرکز کنیم. بیایید به 1 سطح و 1 رنگ متن نگاه کنیم:

:root {
  --surface1: lch(10 0 0);
  --text1:    lch(95 0 0);

  @media (prefers-color-scheme: light) {
    & {
      --surface1: lch(90 0 0);
      --text1:    lch(40 0 0);
    }
  }
}

--surface1: lch(10 0 0) به 10% روشنایی، 0 رنگ و 0 رنگ ترجمه می شود: یک خاکستری بی رنگ بسیار تیره. سپس، در جستجوی رسانه برای حالت نور، روشنایی با --surface1: lch(90 0 0); به 90% تغییر می کند. . و این اصل استراتژی است. فقط با تغییر سبکی بین 2 تم، حفظ نسبت کنتراست مورد نیاز طراحی یا آنچه که می تواند دسترسی را حفظ کند، شروع کنید.

امتیاز lch() در اینجا این است که سبکی انسان محور است، و ما می توانیم در مورد تغییر % نسبت به آن احساس خوبی داشته باشیم، این که از نظر ادراکی و پیوسته آن % متفاوت خواهد بود. برای مثال hsl() چندان قابل اعتماد نیست .

در صورت علاقه ، اطلاعات بیشتری در مورد فضاهای رنگی و lch() وجود دارد. داره میاد!

CSS در حال حاضر به هیچ وجه نمی تواند به این رنگ ها دسترسی داشته باشد . اجازه دهید تکرار کنم: ما در اکثر مانیتورهای مدرن به یک سوم رنگ ها دسترسی نداریم. و اینها هر رنگی نیستند، بلکه زنده ترین رنگ هایی هستند که صفحه نمایش می تواند نمایش دهد . وب سایت های ما از بین رفته اند زیرا سخت افزار مانیتور سریعتر از مشخصات CSS و پیاده سازی مرورگر تکامل یافته است.

لیا ورو

کنترل های فرم تطبیقی ​​با طرح رنگ

بسیاری از مرورگرها کنترل های تم تیره را ارسال می کنند، در حال حاضر Safari و Chromium، اما باید در CSS یا HTML مشخص کنید که طراحی شما از آنها استفاده می کند.

موارد فوق تأثیر ویژگی را از پانل Styles DevTools نشان می دهد. دمو از تگ HTML استفاده می کند که به نظر من به طور کلی مکان بهتری است:

<meta name="color-scheme" content="dark light">

در این مقاله color-scheme توسط توماس اشتاینر همه چیز را در مورد آن بیاموزید. چیزهای بیشتری از ورودی های چک باکس تیره برای به دست آوردن وجود دارد!

CSS accent-color

اخیراً فعالیت‌هایی در مورد accent-color روی عناصر فرم صورت گرفته است، که یک سبک CSS است که می‌تواند رنگ رنگ مورد استفاده در عنصر ورودی مرورگر را تغییر دهد. اطلاعات بیشتر در مورد آن را اینجا در GitHub بخوانید. من آن را در سبک های خود برای این جزء گنجانده ام. از آنجایی که مرورگرها از آن پشتیبانی می‌کنند، چک باکس‌های من بیشتر با مضمون با رنگ‌های صورتی و بنفش ظاهر می‌شوند.

input[type="checkbox"] {
  accent-color: var(--brand);
}

اسکرین شات از Chromium در لینوکس از چک باکس های صورتی

رنگ با گرادیان های ثابت و فوکوس درونی ظاهر می شود

رنگ ها زمانی که کم استفاده می شوند بیشتر ظاهر می شوند و یکی از راه هایی که من دوست دارم به آن برسم از طریق تعاملات رنگارنگ UI است.

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

  • برجسته کردن زمینه
  • ارائه بازخورد رابط کاربری در مورد «چقدر کامل» مقدار در محدوده است.
  • ارائه بازخورد رابط کاربری مبنی بر اینکه یک فیلد ورودی را می‌پذیرد.

برای ارائه بازخورد زمانی که یک عنصر در حال تعامل با یک عنصر است، CSS از کلاس :focus-within برای تغییر ظاهر عناصر مختلف استفاده می کند، بیایید .fieldset-item را تجزیه کنیم، بسیار جالب است:

.fieldset-item {
  ...

  &:focus-within {
    background: var(--surface2);

    & svg {
      fill: white;
    }

    & picture {
      clip-path: circle(50%);
      background: var(--brand-bg-gradient) fixed;
    }
  }
}

هنگامی که یکی از فرزندان این عنصر دارای تمرکز- درون است:

  1. به پس زمینه .fieldset-item رنگ سطح کنتراست بالاتری نسبت داده می شود.
  2. svg تودرتو برای کنتراست بالاتر به رنگ سفید پر شده است.
  3. clip-path <picture> به یک دایره کامل گسترش می یابد و پس زمینه با گرادیان ثابت روشن پر می شود.

محدوده سفارشی

با توجه به عنصر ورودی HTML زیر، به شما نشان خواهم داد که چگونه ظاهر آن را سفارشی کردم:

<input type="range">

3 بخش در این عنصر وجود دارد که باید آن را سفارشی کنیم:

  1. عنصر / ظرف محدوده
  2. آهنگ
  3. انگشت شست

سبک های عناصر محدوده

input[type="range"] {
  /* style setting variables */
  --track-height: .5ex;
  --track-fill: 0%;
  --thumb-size: 3ex;
  --thumb-offset: -1.25ex;
  --thumb-highlight-size: 0px;

  appearance: none;         /* clear styles, make way for mine */
  display: block;
  inline-size: 100%;        /* fill container */
  margin: 1ex 0;            /* ensure thumb isn't colliding with sibling content */
  background: transparent;  /* bg is in the track */
  outline-offset: 5px;      /* focus styles have space */
}

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

سبک های ردیابی

input[type="range"]::-webkit-slider-runnable-track {
  appearance: none; /* clear styles, make way for mine */
  block-size: var(--track-height);
  border-radius: 5ex;
  background:
    /* hard stop gradient:
        - half transparent (where colorful fill we be)
        - half dark track fill
        - 1st background image is on top
    */
    linear-gradient(
      to right,
      transparent var(--track-fill),
      var(--surface1) 0%
    ),
    /* colorful fill effect, behind track surface fill */
    var(--brand-bg-gradient) fixed;
}

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

سبک پر کردن آهنگ

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

/* grab sliders on page */
const sliders = document.querySelectorAll('input[type="range"]')

/* take a slider element, return a percentage string for use in CSS */
const rangeToPercent = slider => {
  const max = slider.getAttribute('max') || 10;
  const percent = slider.value / max * 100;

  return `${parseInt(percent)}%`;
};

/* on page load, set the fill amount */
sliders.forEach(slider => {
  slider.style.setProperty('--track-fill', rangeToPercent(slider));

  /* when a slider changes, update the fill prop */
  slider.addEventListener('input', e => {
    e.target.style.setProperty('--track-fill', rangeToPercent(e.target));
  })
})

من فکر می کنم این یک ارتقاء بصری خوب را ایجاد می کند. نوار لغزنده بدون جاوا اسکریپت عالی کار می کند، پروپ --track-fill مورد نیاز نیست، اگر وجود نداشته باشد به سادگی سبک پر نخواهد داشت. اگر جاوا اسکریپت در دسترس است، ویژگی سفارشی را پر کنید و در عین حال تغییرات کاربر را مشاهده کنید و ویژگی سفارشی را با مقدار همگام کنید.

در اینجا یک پست عالی در CSS-Tricks توسط Ana Tudor وجود دارد که تنها راه حل CSS را برای پر کردن مسیر نشان می دهد. من همچنین این عنصر range را بسیار الهام بخش یافتم.

سبک های انگشت شست

input[type="range"]::-webkit-slider-thumb {
  appearance: none; /* clear styles, make way for mine */
  cursor: ew-resize; /* cursor style to support drag direction */
  border: 3px solid var(--surface3);
  block-size: var(--thumb-size);
  inline-size: var(--thumb-size);
  margin-top: var(--thumb-offset);
  border-radius: 50%;
  background: var(--brand-bg-gradient) fixed;
}

اکثر این سبک ها برای ایجاد یک دایره زیبا هستند. دوباره گرادیان پس‌زمینه ثابت را در آنجا می‌بینید که رنگ‌های پویا انگشت‌های شست، آهنگ‌ها و عناصر SVG مرتبط را یکپارچه می‌کند. برای کمک به جداسازی تکنیک box-shadow که برای برجسته کردن شناور استفاده می‌شود، سبک‌های تعامل را جدا کردم:

@custom-media --motionOK (prefers-reduced-motion: no-preference);

::-webkit-slider-thumb {
  

  /* shadow spread is initally 0 */
  box-shadow: 0 0 0 var(--thumb-highlight-size) var(--thumb-highlight-color);

  /* if motion is OK, transition the box-shadow change */
  @media (--motionOK) {
    & {
      transition: box-shadow .1s ease;
    }
  }

  /* on hover/active state of parent, increase size prop */
  @nest input[type="range"]:is(:hover,:active) & {
    --thumb-highlight-size: 10px;
  }
}

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

اگر فقط جلوه برجسته در چک باکس ها به این راحتی بود…

انتخابگرهای مرورگر متقابل

دریافتم که برای دستیابی به سازگاری بین مرورگرها به این انتخابگرهای -webkit- و -moz- نیاز دارم:

input[type="range"] {
  &::-webkit-slider-runnable-track {}
  &::-moz-range-track {}
  &::-webkit-slider-thumb {}
  &::-moz-range-thumb {}
}

چک باکس سفارشی

با توجه به عنصر ورودی HTML زیر، به شما نشان خواهم داد که چگونه ظاهر آن را سفارشی کردم:

<input type="checkbox">

3 بخش در این عنصر وجود دارد که باید آن را سفارشی کنیم:

  1. عنصر چک باکس
  2. برچسب های مرتبط
  3. جلوه برجسته

عنصر چک باکس

input[type="checkbox"] {
  inline-size: var(--space-sm);   /* increase width */
  block-size: var(--space-sm);    /* increase height */
  outline-offset: 5px;            /* focus style enhancement */
  accent-color: var(--brand);     /* tint the input */
  position: relative;             /* prepare for an absolute pseudo element */
  transform-style: preserve-3d;   /* create a 3d z-space stacking context */
  margin: 0;
  cursor: pointer;
}

transform-style و position برای شبه عنصری که بعداً برای استایل دادن به هایلایت معرفی خواهیم کرد، آماده می شوند. در غیر این صورت، اکثراً چیزهای سبک نظری جزئی از من است. من دوست دارم مکان نما نشانگر باشد، من از خطوط طرح خارج شده خوشم می آید، چک باکس های پیش فرض خیلی کوچک هستند، و اگر accent-color پشتیبانی می شود، این چک باکس ها را در طرح رنگ برند بیاورید.

برچسب‌های چک باکس

به 2 دلیل مهم است که برای چک باکس ها برچسب ارائه کنید. اولین مورد این است که نشان دهد مقدار چک باکس برای چه چیزی استفاده می شود، برای پاسخ به "روشن یا خاموش برای چه؟" دوم این که برای UX، کاربران وب به تعامل با چک باکس ها از طریق برچسب های مرتبط خود عادت کرده اند.

ورودی
<input
  type="checkbox"
  id="text-notifications"
  name="text-notifications"
>
برچسب زدن
<label for="text-notifications">
  <h3>Text Messages</h3>
  <small>Get notified about all text messages sent to your device</small>
</label>

روی برچسب خود، یک ویژگی for قرار دهید که با شناسه به کادر انتخاب اشاره می کند: <label for="text-notifications"> . در کادر تأیید، نام و شناسه را دو برابر کنید تا مطمئن شوید که با ابزارها و فناوری‌های مختلف مانند ماوس یا صفحه‌خوان پیدا می‌شود: <input type="checkbox" id="text-notifications" name="text-notifications"> . :hover ، :active و موارد دیگر به صورت رایگان با اتصال ارائه می شوند و راه های تعامل با فرم شما را افزایش می دهند.

برجسته کردن کادر انتخاب

من می‌خواهم رابط‌هایم را ثابت نگه دارم، و عنصر لغزنده دارای یک تصویر کوچک برجسته است که می‌خواهم با کادر انتخاب از آن استفاده کنم. تصویر بند انگشتی می‌توانست box-shadow استفاده کند و خاصیت spread برای افزایش و پایین‌کردن یک سایه دارد. با این حال، این اثر در اینجا کار نمی کند زیرا چک باکس های ما مربع هستند و باید باشند .

من توانستم به همان جلوه بصری با یک عنصر شبه و مقدار تاسف بار CSS دست پیدا کنم:

@custom-media --motionOK (prefers-reduced-motion: no-preference);

input[type="checkbox"]::before {
  --thumb-scale: .01;                        /* initial scale of highlight */
  --thumb-highlight-size: var(--space-xl);

  content: "";
  inline-size: var(--thumb-highlight-size);
  block-size: var(--thumb-highlight-size);
  clip-path: circle(50%);                     /* circle shape */
  position: absolute;                         /* this is why position relative on parent */
  top: 50%;                                   /* pop and plop technique (https://web.dev/centering-in-css#5-pop-and-plop) */
  left: 50%;
  background: var(--thumb-highlight-color);
  transform-origin: center center;            /* goal is a centered scaling circle */
  transform:                                  /* order here matters!! */
    translateX(-50%)                          /* counter balances left: 50% */
    translateY(-50%)                          /* counter balances top: 50% */
    translateZ(-1px)                          /* PUTS IT BEHIND THE CHECKBOX */
    scale(var(--thumb-scale))                 /* value we toggle for animation */
  ;
  will-change: transform;

  @media (--motionOK) {                       /* transition only if motion is OK */
    & {
      transition: transform .2s ease;
    }
  }
}

/* on hover, set scale custom property to "in" state */
input[type="checkbox"]:hover::before {
  --thumb-scale: 1;
}

ایجاد یک شبه عنصر دایره کار ساده ای است، اما قرار دادن آن در پشت عنصری که به آن متصل است سخت تر بود. قبل و بعد از اینکه درستش کردم اینجاست:

این قطعاً یک تعامل خرد است، اما برای من حفظ ثبات بصری مهم است. تکنیک مقیاس‌بندی انیمیشن همان است که در جاهای دیگر از آن استفاده کرده‌ایم. ما یک ویژگی سفارشی را روی یک مقدار جدید تنظیم می کنیم و به CSS اجازه می دهیم آن را بر اساس اولویت های حرکت انتقال دهد. ویژگی کلیدی در اینجا translateZ(-1px) است. والدین یک فضای سه بعدی ایجاد کردند و این فرزند شبه عنصر با قرار دادن کمی خود در فضای z به آن ضربه زد.

دسترسی

ویدیوی YouTube نمایش خوبی از تعامل ماوس، صفحه‌کلید و صفحه‌خوان را برای این مؤلفه تنظیمات نشان می‌دهد. من برخی از جزئیات را در اینجا فرا خواهم خواند.

انتخاب عناصر HTML

<form>
<header>
<fieldset>
<picture>
<label>
<input>

هر یک از این موارد حاوی نکات و نکاتی برای ابزار مرور کاربر است. برخی از عناصر نکات تعاملی را ارائه می‌دهند، برخی تعامل را به هم متصل می‌کنند و برخی به شکل‌دهی درخت دسترس‌پذیری که یک صفحه‌خوان پیمایش می‌کند کمک می‌کنند.

ویژگی های HTML

ما می‌توانیم عناصری را که صفحه‌خوان‌ها به آنها نیاز ندارند، پنهان کنیم، در این مورد نماد کنار نوار لغزنده:

<picture aria-hidden="true">

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

SVG یک دسته از ریاضیات است، بیایید یک عنصر <title> برای عنوان شناور رایگان ماوس و یک نظر قابل خواندن برای انسان در مورد آنچه ریاضی ایجاد می کند اضافه کنیم:

<svg viewBox="0 0 24 24">
  <title>A note icon</title>
  <path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/>
</svg>

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

جاوا اسکریپت

من قبلاً نحوه مدیریت رنگ پر کردن آهنگ از جاوا اسکریپت را پوشش داده ام، بنابراین اجازه دهید اکنون به جاوا اسکریپت مربوط به <form> نگاه کنیم:

const form = document.querySelector('form');

form.addEventListener('input', event => {
  const formData = Object.fromEntries(new FormData(form));
  console.table(formData);
})

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

یک اسکرین شات از console.table() به دست می آید که در آن داده های فرم در یک جدول نشان داده شده است

نتیجه گیری

حالا که می دانی من چگونه این کار را انجام دادم، شما چطور؟! این باعث می شود معماری اجزای سرگرم کننده ای ایجاد شود! چه کسی می خواهد نسخه اول را با اسلات در چارچوب مورد علاقه خود بسازد؟ 🙂

بیایید رویکردهای خود را متنوع کنیم و همه راه‌های ساخت در وب را بیاموزیم. یک نسخه نمایشی ایجاد کنید، پیوندها را برای من توییت کنید ، و من آن را به بخش ریمیکس های انجمن در زیر اضافه می کنم!

ریمیکس های انجمن

  • @tomayac با سبک خود در مورد ناحیه شناور برای برچسب‌های چک باکس! این نسخه هیچ شکاف شناور بین عناصر: نسخه ی نمایشی و منبع ندارد.
،

یک نمای کلی از نحوه ایجاد یک جزء تنظیمات از لغزنده ها و چک باکس ها.

در این پست می‌خواهم فکری در مورد ساختن یک مؤلفه تنظیمات برای وب به اشتراک بگذارم که واکنش‌گرا باشد، از ورودی‌های متعدد دستگاه پشتیبانی کند و در مرورگرها کار کند. نسخه ی نمایشی را امتحان کنید.

نسخه ی نمایشی

اگر ویدیو را ترجیح می‌دهید یا می‌خواهید یک پیش‌نمایش UI/UX از آنچه در حال ساخت‌مان هستیم داشته باشید، در اینجا توضیح کوتاه‌تری در YouTube آورده شده است:

نمای کلی

من جنبه های این مؤلفه را به بخش های زیر تقسیم کرده ام:

  1. طرح بندی ها
  2. رنگ
  3. ورودی محدوده سفارشی
  4. ورودی چک باکس سفارشی
  5. ملاحظات دسترسی
  6. جاوا اسکریپت

طرح بندی ها

این اولین نسخه نمایشی چالش رابط کاربری گرافیکی است که تماماً CSS Grid است! در اینجا هر شبکه ای است که با Chrome DevTools برای شبکه هایلایت شده است:

خطوط رنگارنگ و پوشش‌های فاصله‌ای که به نشان دادن تمام کادرهایی که چیدمان تنظیمات را تشکیل می‌دهند کمک می‌کند

فقط برای شکاف

رایج ترین چیدمان:

foo {
  display: grid;
  gap: var(--something);
}

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

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

طرح‌بندی‌های شبکه‌ای عمودی با خطوط برجسته برجسته شده و شکاف‌ها را پر می‌کنند

عنصر fieldset ، که شامل هر گروه ورودی ( .fieldset-item ) است، gap: 1px برای ایجاد مرزهای مویی بین عناصر استفاده می کند. بدون راه حل مرزی مشکل!

شکاف پر شد
.grid {
  display: grid;
  gap: 1px;
  background: var(--bg-surface-1);

  & > .fieldset-item {
    background: var(--bg-surface-2);
  }
}
ترفند مرزی
.grid {
  display: grid;

  & > .fieldset-item {
    background: var(--bg-surface-2);

    &:not(:last-child) {
      border-bottom: 1px solid var(--bg-surface-1);
    }
  }
}

بسته بندی توری طبیعی

پیچیده‌ترین طرح‌بندی در نهایت طرح ماکرو بود، سیستم چیدمان منطقی بین <main> و <form> .

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

Flexbox و grid هر دو توانایی‌هایی را برای align-items یا align-content فراهم می‌کنند، و هنگام برخورد با عناصر بسته‌بندی، هم‌ترازی‌های چیدمان content فضا را بین کودکان به‌عنوان یک گروه توزیع می‌کنند.

main {
  display: grid;
  gap: var(--space-xl);
  place-content: center;
}

عنصر اصلی استفاده از place-content: center کوتاه‌نویسی تراز وسط به طوری که کودکان به صورت عمودی و افقی در هر دو طرح بندی یک و دو ستون در مرکز قرار گیرند.

در ویدیوی بالا مشاهده کنید که چگونه "محتوا" در مرکز باقی می ماند، حتی اگر بسته بندی اتفاق افتاده باشد.

تنظیم خودکار Minmax را تکرار کنید

<form> از یک طرح شبکه تطبیقی ​​برای هر بخش استفاده می کند. این طرح بندی بر اساس فضای موجود از یک به دو ستون تغییر می کند.

form {
  display: grid;
  gap: var(--space-xl) var(--space-xxl);
  grid-template-columns: repeat(auto-fit, minmax(min(10ch, 100%), 35ch));
  align-items: flex-start;
  max-width: 89vw;
}

این شبکه مقدار متفاوتی برای row-gap (--space-xl) نسبت به column-gap (--space-xxl) دارد تا آن لمس سفارشی را روی طرح‌بندی پاسخگو اعمال کند. وقتی ستون‌ها روی هم قرار می‌گیرند، یک شکاف بزرگ می‌خواهیم، ​​اما نه به اندازه‌ای که در یک صفحه گسترده هستیم.

ویژگی grid-template-columns از 3 تابع CSS استفاده می کند: repeat() ، minmax() و min() . Una Kravets یک پست وبلاگ طرح بندی عالی در مورد این دارد که آن را RAM می نامد.

اگر آن را با Una مقایسه کنید، 3 افزوده ویژه در چیدمان ما وجود دارد:

  • تابع min() اضافی را پاس می کنیم.
  • ما align-items: flex-start .
  • max-width: 89vw وجود دارد.

تابع min() اضافی به خوبی توسط Evan Minto در وبلاگ خود در پست Intrinsically Responsive CSS Grid با minmax() و min() توضیح داده شده است. توصیه می کنم آن را بخوانید. اصلاح تراز flex-start برای حذف اثر کشش پیش‌فرض است، به طوری که فرزندان این طرح‌بندی نیازی به داشتن ارتفاع‌های برابر نداشته باشند، آنها می‌توانند ارتفاع‌های طبیعی و ذاتی داشته باشند. ویدیوی یوتیوب یک تفکیک سریع از این تراز اضافه شده دارد.

max-width: 89vw ارزش یک تفکیک کوچک در این پست را دارد. اجازه دهید طرح بندی را با و بدون سبک اعمال شده به شما نشان دهم:

چه اتفاقی می افتد؟ هنگامی که max-width مشخص می شود، زمینه، اندازه صریح یا اندازه مشخص را برای الگوریتم چیدمان تنظیم auto-fit فراهم می کند تا بداند چند تکرار می تواند در فضا قرار گیرد. در حالی که واضح به نظر می رسد که فضا "عرض کامل" است، با توجه به مشخصات شبکه CSS، اندازه مشخص یا حداکثر اندازه باید ارائه شود. من یک اندازه حداکثر ارائه کرده ام.

بنابراین، چرا 89vw ؟ چون برای چیدمان من "کار کرد". من و چند نفر دیگر از Chrome در حال بررسی این موضوع هستیم که چرا یک مقدار معقول تر، مانند 100vw کافی نیست، و آیا این در واقع یک اشکال است.

فاصله گذاری

اکثر هماهنگی این چیدمان از یک پالت محدود فاصله، به طور دقیق 7 است.

:root {
  --space-xxs: .25rem;
  --space-xs:  .5rem;
  --space-sm:  1rem;
  --space-md:  1.5rem;
  --space-lg:  2rem;
  --space-xl:  3rem;
  --space-xxl: 6rem;
}

استفاده از این جریان ها با گرید، CSS @nest و نحو سطح 5 رسانه @ بسیار خوب است. در اینجا یک مثال، مجموعه طرح بندی کاملاً <main> از سبک ها آورده شده است.

main {
  display: grid;
  gap: var(--space-xl);
  place-content: center;
  padding: var(--space-sm);

  @media (width >= 540px) {
    & {
      padding: var(--space-lg);
    }
  }

  @media (width >= 800px) {
    & {
      padding: var(--space-xl);
    }
  }
}

شبکه‌ای با محتوای متمرکز که به‌طور پیش‌فرض به‌طور متوسط ​​(مانند تلفن همراه) پر شده است. اما با در دسترس قرار گرفتن فضای نمای بیشتر، با افزایش padding گسترش می یابد. CSS 2021 بسیار خوب به نظر می رسد!

طرح قبلی، "فقط برای شکاف" را به خاطر دارید؟ در اینجا یک نسخه کاملتر از نحوه ظاهر آنها در این مؤلفه آمده است:

header {
  display: grid;
  gap: var(--space-xxs);
}

section {
  display: grid;
  gap: var(--space-md);
}

رنگ

استفاده کنترل شده از رنگ به این طرح کمک کرد تا به عنوان رسا و در عین حال مینیمال برجسته شود. من این کار را به این صورت انجام می دهم:

:root {
  --surface1: lch(10 0 0);
  --surface2: lch(15 0 0);
  --surface3: lch(20 0 0);
  --surface4: lch(25 0 0);

  --text1: lch(95 0 0);
  --text2: lch(75 0 0);
}

من رنگ‌های سطح و متن خود را با اعداد نام‌گذاری می‌کنم، برخلاف نام‌هایی مانند surface-dark و surface-darker ، زیرا در یک جستجوی رسانه‌ای، آنها را ورق می‌زنم، و روشن و تیره معنی‌دار نخواهند بود.

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

:root {
  ...

  @media (prefers-color-scheme: light) {
    & {
      --surface1: lch(90 0 0);
      --surface2: lch(100 0 0);
      --surface3: lch(98 0 0);
      --surface4: lch(85 0 0);

      --text1: lch(20 0 0);
      --text2: lch(40 0 0);
    }
  }
}

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

LCH

بدون اینکه خیلی عمیق به زمین تئوری رنگ بپردازیم، LCH یک نحو مبتنی بر انسان است، که به نحوه درک ما از رنگ توجه می کند، نه اینکه چگونه رنگ را با ریاضی اندازه گیری می کنیم (مانند 255). این به آن یک مزیت متمایز می‌دهد زیرا انسان‌ها می‌توانند آن را راحت‌تر بنویسند و سایر انسان‌ها با این تنظیمات هماهنگ خواهند بود.

تصویری از صفحه وب pod.link/csspodcast، با قسمت Color 2: Perception کشیده شده است
در مورد رنگ ادراکی (و بیشتر!) در پادکست CSS بیاموزید

برای امروز، در این نسخه ی نمایشی، بیایید بر روی نحو و مقادیری که برای ایجاد روشن و تاریک ورق می زنم تمرکز کنیم. بیایید به 1 سطح و 1 رنگ متن نگاه کنیم:

:root {
  --surface1: lch(10 0 0);
  --text1:    lch(95 0 0);

  @media (prefers-color-scheme: light) {
    & {
      --surface1: lch(90 0 0);
      --text1:    lch(40 0 0);
    }
  }
}

--surface1: lch(10 0 0) به 10% روشنایی، 0 رنگ و 0 رنگ ترجمه می شود: یک خاکستری بی رنگ بسیار تیره. سپس، در جستجوی رسانه برای حالت نور، روشنایی با --surface1: lch(90 0 0); به 90% تغییر می کند. . و این اصل استراتژی است. فقط با تغییر سبکی بین 2 تم، حفظ نسبت کنتراست مورد نیاز طراحی یا آنچه که می تواند دسترسی را حفظ کند، شروع کنید.

امتیاز lch() در اینجا این است که سبکی انسان محور است، و ما می توانیم در مورد تغییر % نسبت به آن احساس خوبی داشته باشیم، این که از نظر ادراکی و پیوسته آن % متفاوت خواهد بود. برای مثال hsl() چندان قابل اعتماد نیست .

در صورت علاقه ، اطلاعات بیشتری در مورد فضاهای رنگی و lch() وجود دارد. داره میاد!

CSS در حال حاضر به هیچ وجه نمی تواند به این رنگ ها دسترسی داشته باشد . اجازه دهید تکرار کنم: ما در اکثر مانیتورهای مدرن به یک سوم رنگ ها دسترسی نداریم. و اینها هر رنگی نیستند، بلکه زنده ترین رنگ هایی هستند که صفحه نمایش می تواند نمایش دهد . وب سایت های ما از بین رفته اند زیرا سخت افزار مانیتور سریعتر از مشخصات CSS و پیاده سازی مرورگر تکامل یافته است.

لیا ورو

کنترل های فرم تطبیقی ​​با طرح رنگ

بسیاری از مرورگرها کنترل های تم تیره را ارسال می کنند، در حال حاضر Safari و Chromium، اما باید در CSS یا HTML مشخص کنید که طراحی شما از آنها استفاده می کند.

موارد فوق تأثیر ویژگی را از پانل Styles DevTools نشان می دهد. دمو از تگ HTML استفاده می کند که به نظر من به طور کلی مکان بهتری است:

<meta name="color-scheme" content="dark light">

در این مقاله color-scheme توسط توماس اشتاینر همه چیز را در مورد آن بیاموزید. چیزهای بیشتری از ورودی های چک باکس تیره برای به دست آوردن وجود دارد!

CSS accent-color

اخیراً فعالیت‌هایی در مورد accent-color روی عناصر فرم صورت گرفته است، که یک سبک CSS است که می‌تواند رنگ رنگ مورد استفاده در عنصر ورودی مرورگر را تغییر دهد. اطلاعات بیشتر در مورد آن را اینجا در GitHub بخوانید. من آن را در سبک های خود برای این جزء گنجانده ام. از آنجایی که مرورگرها از آن پشتیبانی می‌کنند، چک باکس‌های من بیشتر با مضمون با رنگ‌های صورتی و بنفش ظاهر می‌شوند.

input[type="checkbox"] {
  accent-color: var(--brand);
}

اسکرین شات از Chromium در لینوکس از چک باکس های صورتی

رنگ با گرادیان های ثابت و فوکوس درونی ظاهر می شود

رنگ ها زمانی که کم استفاده می شوند بیشتر ظاهر می شوند و یکی از راه هایی که من دوست دارم به آن برسم از طریق تعاملات رنگارنگ UI است.

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

  • برجسته کردن زمینه
  • ارائه بازخورد رابط کاربری در مورد «چقدر کامل» مقدار در محدوده است.
  • ارائه بازخورد رابط کاربری مبنی بر اینکه یک فیلد ورودی را می‌پذیرد.

برای ارائه بازخورد زمانی که یک عنصر در حال تعامل با یک عنصر است، CSS از کلاس :focus-within برای تغییر ظاهر عناصر مختلف استفاده می کند، بیایید .fieldset-item را تجزیه کنیم، بسیار جالب است:

.fieldset-item {
  ...

  &:focus-within {
    background: var(--surface2);

    & svg {
      fill: white;
    }

    & picture {
      clip-path: circle(50%);
      background: var(--brand-bg-gradient) fixed;
    }
  }
}

هنگامی که یکی از فرزندان این عنصر دارای تمرکز- درون است:

  1. به پس زمینه .fieldset-item رنگ سطح کنتراست بالاتری نسبت داده می شود.
  2. svg تودرتو برای کنتراست بالاتر به رنگ سفید پر شده است.
  3. clip-path <picture> به یک دایره کامل گسترش می یابد و پس زمینه با گرادیان ثابت روشن پر می شود.

محدوده سفارشی

با توجه به عنصر ورودی HTML زیر، به شما نشان خواهم داد که چگونه ظاهر آن را سفارشی کردم:

<input type="range">

3 بخش در این عنصر وجود دارد که باید آن را سفارشی کنیم:

  1. عنصر / ظرف محدوده
  2. آهنگ
  3. انگشت شست

سبک های عناصر محدوده

input[type="range"] {
  /* style setting variables */
  --track-height: .5ex;
  --track-fill: 0%;
  --thumb-size: 3ex;
  --thumb-offset: -1.25ex;
  --thumb-highlight-size: 0px;

  appearance: none;         /* clear styles, make way for mine */
  display: block;
  inline-size: 100%;        /* fill container */
  margin: 1ex 0;            /* ensure thumb isn't colliding with sibling content */
  background: transparent;  /* bg is in the track */
  outline-offset: 5px;      /* focus styles have space */
}

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

سبک های ردیابی

input[type="range"]::-webkit-slider-runnable-track {
  appearance: none; /* clear styles, make way for mine */
  block-size: var(--track-height);
  border-radius: 5ex;
  background:
    /* hard stop gradient:
        - half transparent (where colorful fill we be)
        - half dark track fill
        - 1st background image is on top
    */
    linear-gradient(
      to right,
      transparent var(--track-fill),
      var(--surface1) 0%
    ),
    /* colorful fill effect, behind track surface fill */
    var(--brand-bg-gradient) fixed;
}

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

سبک پر کردن آهنگ

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

/* grab sliders on page */
const sliders = document.querySelectorAll('input[type="range"]')

/* take a slider element, return a percentage string for use in CSS */
const rangeToPercent = slider => {
  const max = slider.getAttribute('max') || 10;
  const percent = slider.value / max * 100;

  return `${parseInt(percent)}%`;
};

/* on page load, set the fill amount */
sliders.forEach(slider => {
  slider.style.setProperty('--track-fill', rangeToPercent(slider));

  /* when a slider changes, update the fill prop */
  slider.addEventListener('input', e => {
    e.target.style.setProperty('--track-fill', rangeToPercent(e.target));
  })
})

من فکر می کنم این یک ارتقاء بصری خوب را ایجاد می کند. نوار لغزنده بدون جاوا اسکریپت عالی کار می کند، پروپ --track-fill مورد نیاز نیست، اگر وجود نداشته باشد به سادگی سبک پر نخواهد داشت. اگر جاوا اسکریپت در دسترس است، ویژگی سفارشی را پر کنید و در عین حال تغییرات کاربر را مشاهده کنید و ویژگی سفارشی را با مقدار همگام کنید.

در اینجا یک پست عالی در CSS-Tricks توسط Ana Tudor وجود دارد که تنها راه حل CSS را برای پر کردن مسیر نشان می دهد. من همچنین این عنصر range را بسیار الهام بخش یافتم.

سبک های انگشت شست

input[type="range"]::-webkit-slider-thumb {
  appearance: none; /* clear styles, make way for mine */
  cursor: ew-resize; /* cursor style to support drag direction */
  border: 3px solid var(--surface3);
  block-size: var(--thumb-size);
  inline-size: var(--thumb-size);
  margin-top: var(--thumb-offset);
  border-radius: 50%;
  background: var(--brand-bg-gradient) fixed;
}

اکثر این سبک ها برای ایجاد یک دایره زیبا هستند. دوباره گرادیان پس‌زمینه ثابت را در آنجا می‌بینید که رنگ‌های پویا انگشت‌های شست، آهنگ‌ها و عناصر SVG مرتبط را یکپارچه می‌کند. برای کمک به جداسازی تکنیک box-shadow که برای برجسته کردن شناور استفاده می‌شود، سبک‌های تعامل را جدا کردم:

@custom-media --motionOK (prefers-reduced-motion: no-preference);

::-webkit-slider-thumb {
  

  /* shadow spread is initally 0 */
  box-shadow: 0 0 0 var(--thumb-highlight-size) var(--thumb-highlight-color);

  /* if motion is OK, transition the box-shadow change */
  @media (--motionOK) {
    & {
      transition: box-shadow .1s ease;
    }
  }

  /* on hover/active state of parent, increase size prop */
  @nest input[type="range"]:is(:hover,:active) & {
    --thumb-highlight-size: 10px;
  }
}

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

اگر فقط جلوه برجسته در چک باکس ها به این راحتی بود…

انتخابگرهای مرورگر متقابل

دریافتم که برای دستیابی به سازگاری بین مرورگرها به این انتخابگرهای -webkit- و -moz- نیاز دارم:

input[type="range"] {
  &::-webkit-slider-runnable-track {}
  &::-moz-range-track {}
  &::-webkit-slider-thumb {}
  &::-moz-range-thumb {}
}

چک باکس سفارشی

با توجه به عنصر ورودی HTML زیر، به شما نشان خواهم داد که چگونه ظاهر آن را سفارشی کردم:

<input type="checkbox">

3 بخش در این عنصر وجود دارد که باید آن را سفارشی کنیم:

  1. عنصر چک باکس
  2. برچسب های مرتبط
  3. جلوه برجسته

عنصر چک باکس

input[type="checkbox"] {
  inline-size: var(--space-sm);   /* increase width */
  block-size: var(--space-sm);    /* increase height */
  outline-offset: 5px;            /* focus style enhancement */
  accent-color: var(--brand);     /* tint the input */
  position: relative;             /* prepare for an absolute pseudo element */
  transform-style: preserve-3d;   /* create a 3d z-space stacking context */
  margin: 0;
  cursor: pointer;
}

transform-style و position برای شبه عنصری که بعداً برای استایل دادن به هایلایت معرفی خواهیم کرد، آماده می شوند. در غیر این صورت، اکثراً چیزهای سبک نظری جزئی از من است. من دوست دارم مکان نما نشانگر باشد، من از خطوط طرح خارج شده خوشم می آید، چک باکس های پیش فرض خیلی کوچک هستند، و اگر accent-color پشتیبانی می شود، این چک باکس ها را در طرح رنگ برند بیاورید.

برچسب‌های چک باکس

به 2 دلیل مهم است که برای چک باکس ها برچسب ارائه کنید. اولین مورد این است که نشان دهد مقدار چک باکس برای چه چیزی استفاده می شود، برای پاسخ به "روشن یا خاموش برای چه؟" دوم این که برای UX، کاربران وب به تعامل با چک باکس ها از طریق برچسب های مرتبط خود عادت کرده اند.

ورودی
<input
  type="checkbox"
  id="text-notifications"
  name="text-notifications"
>
برچسب زدن
<label for="text-notifications">
  <h3>Text Messages</h3>
  <small>Get notified about all text messages sent to your device</small>
</label>

روی برچسب خود، یک ویژگی for قرار دهید که با شناسه به کادر انتخاب اشاره می کند: <label for="text-notifications"> . در کادر تأیید، نام و شناسه را دو برابر کنید تا مطمئن شوید که با ابزارها و فناوری‌های مختلف مانند ماوس یا صفحه‌خوان پیدا می‌شود: <input type="checkbox" id="text-notifications" name="text-notifications"> . :hover ، :active و موارد دیگر به صورت رایگان با اتصال ارائه می شوند و راه های تعامل با فرم شما را افزایش می دهند.

برجسته کردن کادر انتخاب

من می‌خواهم رابط‌هایم را ثابت نگه دارم، و عنصر لغزنده دارای یک تصویر کوچک برجسته است که می‌خواهم با کادر انتخاب از آن استفاده کنم. تصویر بند انگشتی می‌توانست box-shadow استفاده کند و خاصیت spread برای افزایش و پایین‌کردن یک سایه دارد. با این حال، این اثر در اینجا کار نمی کند زیرا چک باکس های ما مربع هستند و باید باشند .

من توانستم به همان جلوه بصری با یک عنصر شبه و مقدار تاسف بار CSS دست پیدا کنم:

@custom-media --motionOK (prefers-reduced-motion: no-preference);

input[type="checkbox"]::before {
  --thumb-scale: .01;                        /* initial scale of highlight */
  --thumb-highlight-size: var(--space-xl);

  content: "";
  inline-size: var(--thumb-highlight-size);
  block-size: var(--thumb-highlight-size);
  clip-path: circle(50%);                     /* circle shape */
  position: absolute;                         /* this is why position relative on parent */
  top: 50%;                                   /* pop and plop technique (https://web.dev/centering-in-css#5-pop-and-plop) */
  left: 50%;
  background: var(--thumb-highlight-color);
  transform-origin: center center;            /* goal is a centered scaling circle */
  transform:                                  /* order here matters!! */
    translateX(-50%)                          /* counter balances left: 50% */
    translateY(-50%)                          /* counter balances top: 50% */
    translateZ(-1px)                          /* PUTS IT BEHIND THE CHECKBOX */
    scale(var(--thumb-scale))                 /* value we toggle for animation */
  ;
  will-change: transform;

  @media (--motionOK) {                       /* transition only if motion is OK */
    & {
      transition: transform .2s ease;
    }
  }
}

/* on hover, set scale custom property to "in" state */
input[type="checkbox"]:hover::before {
  --thumb-scale: 1;
}

ایجاد یک شبه عنصر دایره کار ساده ای است، اما قرار دادن آن در پشت عنصری که به آن متصل است سخت تر بود. قبل و بعد از اینکه درستش کردم اینجاست:

این قطعاً یک تعامل خرد است، اما برای من حفظ ثبات بصری مهم است. تکنیک مقیاس‌بندی انیمیشن همان است که در جاهای دیگر از آن استفاده کرده‌ایم. ما یک ویژگی سفارشی را روی یک مقدار جدید تنظیم می کنیم و به CSS اجازه می دهیم آن را بر اساس اولویت های حرکت انتقال دهد. ویژگی کلیدی در اینجا translateZ(-1px) است. والدین یک فضای سه بعدی ایجاد کردند و این فرزند شبه عنصر با قرار دادن کمی خود در فضای z به آن ضربه زد.

دسترسی

ویدیوی YouTube نمایش خوبی از تعامل ماوس، صفحه‌کلید و صفحه‌خوان را برای این مؤلفه تنظیمات نشان می‌دهد. من برخی از جزئیات را در اینجا فرا خواهم خواند.

انتخاب عناصر HTML

<form>
<header>
<fieldset>
<picture>
<label>
<input>

هر یک از این موارد حاوی نکات و نکاتی برای ابزار مرور کاربر است. برخی از عناصر نکات تعاملی را ارائه می‌دهند، برخی تعامل را به هم متصل می‌کنند و برخی به شکل‌دهی درخت دسترس‌پذیری که یک صفحه‌خوان پیمایش می‌کند کمک می‌کنند.

ویژگی های HTML

ما می‌توانیم عناصری را که صفحه‌خوان‌ها به آنها نیاز ندارند، پنهان کنیم، در این مورد نماد کنار نوار لغزنده:

<picture aria-hidden="true">

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

SVG یک دسته از ریاضیات است، بیایید یک عنصر <title> برای عنوان شناور رایگان ماوس و یک نظر قابل خواندن برای انسان در مورد آنچه ریاضی ایجاد می کند اضافه کنیم:

<svg viewBox="0 0 24 24">
  <title>A note icon</title>
  <path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/>
</svg>

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

جاوا اسکریپت

من قبلاً نحوه مدیریت رنگ پر کردن آهنگ از جاوا اسکریپت را پوشش داده ام، بنابراین اجازه دهید اکنون به جاوا اسکریپت مربوط به <form> نگاه کنیم:

const form = document.querySelector('form');

form.addEventListener('input', event => {
  const formData = Object.fromEntries(new FormData(form));
  console.table(formData);
})

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

یک اسکرین شات از console.table() به دست می آید که در آن داده های فرم در یک جدول نشان داده شده است

نتیجه گیری

حالا که می دانی من چگونه این کار را انجام دادم، شما چطور؟! این باعث می شود معماری اجزای سرگرم کننده ای ایجاد شود! چه کسی می خواهد نسخه اول را با اسلات در چارچوب مورد علاقه خود بسازد؟ 🙂

بیایید رویکردهای خود را متنوع کنیم و همه راه‌های ساخت در وب را بیاموزیم. یک نسخه نمایشی ایجاد کنید، پیوندها را برای من توییت کنید ، و من آن را به بخش ریمیکس های انجمن در زیر اضافه می کنم!

ریمیکس های انجمن

  • @tomayac با سبک خود در مورد ناحیه شناور برای برچسب‌های چک باکس! این نسخه هیچ شکاف شناور بین عناصر: نسخه ی نمایشی و منبع ندارد.