إنشاء أحد مكونات الإعدادات

نظرة عامة أساسية حول كيفية إنشاء مكوّن إعدادات من أشرطة التمرير مربّعات الاختيار

في هذه المشاركة، أريد مشاركة أفكار حول إنشاء عنصر "الإعدادات" لتطبيق الويب الذي يكون سريع الاستجابة ويتوافق مع إدخالات الأجهزة المتعددة ويعمل على جميع المتصفّحات. جرِّب الإصدار التجريبي.

العرض التوضيحي

إذا كنت تفضّل الفيديو أو أردت معاينة واجهة المستخدم/تجربة المستخدم لما ننشئه، يمكنك الاطّلاع على walkthrough أقصر على YouTube:

نظرة عامة

لقد قسمت جوانب هذا المكوّن إلى الأقسام التالية:

  1. التنسيقات
  2. اللون
  3. إدخال نطاق مخصّص
  4. إدخال مربّع اختيار مخصّص
  5. اعتبارات تسهيل الاستخدام
  6. JavaScript

التنسيقات

هذا هو أول عرض توضيحي لتحدّي واجهة المستخدم الرسومية يستخدم شبكة CSS بالكامل. فيما يلي كل شبكة مميزة باستخدام أدوات مطوري البرامج في Chrome للشبكة:

حدود ملونة وتراكبات لمساحة التباعد تساعد في عرض كل المربّعات التي تشكّل تنسيق الإعدادات

للاستخدام في حالة عدم توفّر بيانات

التنسيق الأكثر شيوعًا:

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

أُطلق على هذا التنسيق اسم "فقط للفاصل" لأنّه يستخدم الشبكة فقط لإضافة فواصل بين الكتل.

تستخدِم خمسة تنسيقات هذه الاستراتيجية، وإليك جميعها:

تصاميم شبكات رأسية مميّزة بخطوط خارجية ومملوءة بالفراغات

يستخدم عنصر fieldset، الذي يحتوي على كل مجموعة إدخال (.fieldset-itemgap: 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 وشبكة الشبكة إمكانات align-items أو align-content، وعند التعامل مع العناصر التي يتم لفها، ستوزّع محاذاة content التنسيق المسافة بين العناصر الفرعية كمجموعة.

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

العنصر الرئيسي هو استخدام place-content: center اختصار alignment ليكون بالإمكان توسيط العناصر الثانوية عموديًا وأفقيًا في تنسيقات الأعمدة الواحدة والاثنين.

شاهِد الفيديو أعلاه لمعرفة كيف يبقى "المحتوى" في المنتصف، حتى بعد التفاف المحتوى .

تكرار الحد الأدنى والحد الأقصى للملاءمة التلقائية

يستخدم <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.

هناك 3 إضافات خاصة في تنسيقنا، إذا قارنت بينه وبين تنسيق Una:

  • نمرر دالة min() إضافية.
  • نحدد align-items: flex-start.
  • هناك أسلوب max-width: 89vw.

وصف إيفان مينتو الدالة min() الإضافية بشكل جيد في مدوّنته في المشاركة Intrinsically Responsive CSS Grid with minmax() and min(). ننصحك بقراءة هذه المشاركة. يهدف تصحيح المحاذاة flex-start إلى إزالة تأثير التمدد التلقائي، لكي لا يحتاج العناصر الفرعية لهذا التنسيق إلى أن تكون ارتفاعاتها متساوية، بل يمكن أن يكون لها ارتفاعات طبيعية أساسية. يعرض فيديو YouTube شرحًا سريعًا لهذه الإضافة.

يستحقّ 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 وCSS @nest وبنية المستوى 5 من @media. في ما يلي مثال على مجموعة الأنماط لتنسيق <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);
    }
  }
}

شبكة تتضمّن محتوى في المنتصف، مع مساحة فارغة معتدلة تلقائيًا (مثلاً على الأجهزة الجوّالة) ولكن مع توفّر المزيد من مساحة إطار العرض، يتم توزيع المحتوى على الشاشة من خلال زيادة المسافة البادئة. يبدو أنّ استراتيجية 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.

في هذا العرض التوضيحي، لنركّز على البنية والقيم التي سأغيّرها لإنشاء وضعَي الإضاءة الفاتحة والداكنة. لنلقِ نظرة على سطح واحد ولون نص واحد:

: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، أي رمادي داكن جدًا بدون لون. بعد ذلك، في طلب البحث عن الوسائط للوضع الفاتح، يتم قلب 90% باستخدام --surface1: lch(90 0 0);. وهذا هو مضمون الاستراتيجية. ابدأ بتغيير درجة السطوع بين المظهرَين، مع الحفاظ على ratiosشدة التباين التي يتطلبها التصميم أو ما يمكن أن يحافظ على سهولة الاستخدام.

وأفضل ما في lch() هنا هو أنّ الإضاءة موجَّهة البشرية، ويمكننا أن نشعر بالرضا تجاه تغيير % إليها، إذ سيختلف % من الناحية المرئية والمتسقة. على سبيل المثال، hsl() ليس بقدرٍ مماثل موثوقًا.

يمكنك الاطّلاع على مزيد من المعلومات حول مساحات الألوان وlch() إذا كنت مهتمًا بذلك. قريباً.

لا يمكن لخدمة CSS الوصول إلى هذه الألوان مطلقًا. سأكرّر ما سبق: لا يمكننا الوصول إلى ثلث الألوان في معظم الشاشات الحديثة. وهذه ليست أي ألوان، بل هي الألوان الأكثر سطوعًا التي يمكن للشاشة عرضها. لم تعُد مواقعنا الإلكترونية متأخرة بسبب تطوُّر أجهزة المراقبة بشكل أسرع من مواصفات CSS وعمليات تنفيذ المتصفّحات.

Lea Verou

عناصر التحكّم التكيّفية في النماذج مع مخطّط الألوان

توفّر العديد من المتصفّحات عناصر التحكّم في المظهر الداكن، مثل Safari وChromium حاليًا، ولكن عليك تحديد ما إذا كان تصميمك يستخدمها في CSS أو HTML.

يوضّح المثال أعلاه تأثير الموقع من لوحة "الأنماط" في أدوات مطوّري البرامج. يستخدم العرض التوضيحي علامة 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 على Linux لعلامات مربّعات وردية

صورة مع تأثير البقع الملونة مع تدرجات ثابتة وتركيز بالداخل

تبرز الألوان بشكل أكبر عند استخدامها بشكل مقتصد، وإحدى الطرق التي أفضّل اتّباعها لتحقيق ذلك هي من خلال التفاعلات الملونة لواجهة المستخدم.

هناك العديد من طبقات الملاحظات والتفاعلات في واجهة المستخدم في الفيديو أعلاه، ما يساعد في إضفاء طابع شخصي على التفاعل من خلال:

  • إبراز السياق:
  • تقديم ملاحظات لواجهة المستخدم توضح "مدى اكتمال" القيمة ضمن النطاق.
  • تقديم ملاحظات عن واجهة المستخدم بأنّ الحقل يقبل الإدخال

لتقديم ملاحظات عند التفاعل مع أحد العناصر، تستخدم 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. يتم توسيع الرمز <picture> clip-path المُدمَج إلى دائرة كاملة ويتم ملء الخلفية بالتدرّج الثابت والمشرق.

نطاق مخصّص

استنادًا إلى عنصر الإدخال HTML التالي، سأوضّح لك كيفية تخصيص مظهره:

<input type="range">

هناك 3 أجزاء من هذا العنصر يجب تخصيصها:

  1. عنصر النطاق / الحاوية
  2. Track
  3. Thumb

أنماط عناصر النطاق

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;
}

يكمن سرّ ذلك في "إظهار" لون التعبئة الحيوي. ويتم ذلك باستخدام التدرّج اللوني للتوقف التام في الأعلى. يكون التدرّج شفافًا حتى النسبة المئوية للتعبئة، وبعد ذلك يستخدم لون سطح المسار غير المعبّأ. خلف هذه المساحة غير المليئة، هناك لون بعرض كامل، في انتظار الشفافية للكشف عنه.

نمط تعبئة المسار

يتطلّب تصميمي JavaScript للحفاظ على نمط الملء. هناك استراتيجيات خاصة بخدمة مقارنة الأسعار فقط، ولكنّها تتطلّب أن يكون ارتفاع عنصر الصورة المصغّرة مماثلاً لارتفاع المقطع الصوتي، ولم أتمكّن من العثور على تناغم ضمن هذه الحدود.

/* 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));
  })
})

أعتقد أنّ هذا الإجراء سيؤدي إلى تحسين مرئي. يعمل شريط التمرير بشكل رائع بدون JavaScript، ولا يتطلب الأمر استخدام عنصر --track-fill، ولن يكون له نمط ملء إذا لم يكن متوفّرًا. إذا كان JavaScript متاحًا، يمكنك تعبئة السمة المخصّصة مع مراقبة أي تغييرات يجريها المستخدم، مع مزامنة السمة المخصّصة مع القيمة.

إليك مقالة رائعة بعنوان حيل CSS من تأليف أنا تودور، توضّح حلّاً يعتمد على 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 متوافقًا، يجب إدراج مربّعات الاختيار هذه في مخطّط ألوان العلامة التجارية.

تصنيفات مربّعات الاختيار

من المهم توفير تصنيفات لمربّعات الاختيار لسببَين. الغرض الأول هو تمثيل الغرض من استخدام قيمة مربّع الاختيار، للإجابة عن السؤال "تفعيل أو إيقاف ماذا؟" أما السبب الثاني، فهو تجربة المستخدم، فقد اعتاد مستخدمو الويب التفاعل مع مربعات الاختيار من خلال التصنيفات المرتبطة بها.

الإدخال
<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">

يوضّح الفيديو أعلاه مسار قارئ الشاشة على نظام التشغيل Mac. لاحِظ كيف يتم نقل تركيز إدخال مباشرةً من شريط تمرير إلى آخر. ويعود السبب في ذلك إلى أنّنا أخفينا الرمز الذي ربما كان نقطة توقف في الطريق إلى شريط التمرير التالي. بدون هذه السمة، يحتاج المستخدم إلى التوقف والاستماع إلى الصورة التي قد لا يتمكّن من رؤيتها والانتقال إلى ما بعدها.

ملف 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 المحدَّدة بوضوح، ما يجعل اختبارات النموذج تتم بنجاح على الماوس ولوحة المفاتيح وأجهزة التحكّم في ألعاب الفيديو وبرامج قراءة الشاشة.

JavaScript

لقد سبق أن أوضحت كيفية إدارة لون تعبئة المسار من JavaScript، لنلقِ نظرة الآن على رمز JavaScript ذي الصلة <form>:

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

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

في كل مرة يتم فيها التفاعل مع النموذج وتغييره، تسجِّل وحدة التحكّم النموذج كأحد العناصر في جدول لتسهيل مراجعته قبل إرساله إلى الخادم.

لقطة شاشة لنتائج console.table()، حيث يتم عرض بيانات النموذج في جدول

الخاتمة

الآن بعد أن عرفت كيف فعلت ذلك، كيف ستفعل ذلك؟ هذا يجعل بعض البنية الممتعة للمكونات! من سينشئ الإصدار الأول مع خانات في إطار العمل المفضل لديه؟ 🙂

يمكننا تنويع أساليبنا وتعلُّم جميع طرق إنشاء المحتوى على الويب. أنشئ عرضًا توضيحيًا، وأرسِل إلينا روابط على Twitter، وسنضيفه إلى قسم ريمكسات من إنشاء المنتدى أدناه.

ريمكسات من إنشاء المنتدى