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

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

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

عرض توضيحي

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

نظرة عامة

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

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

التنسيقات

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

مخططات ملونة وتراكبات مسافات بين الفجوة مما يساعد على عرض جميع المربعات التي يتألف منها تنسيق الإعدادات

عرض فاصل

التخطيط الأكثر شيوعًا:

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 والشبكات "align-items" أو align-content، وعند التعامل مع عناصر الالتفاف، يكون التنسيق content ستوزع المحاذاة المساحة بين الأطفال كمجموعة.

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

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

شاهد في الفيديو أعلاه كيف يمكن لـ "المحتوى" يظل في الوسط، على الرغم من أن الالتفاف حدث.

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

يستخدم <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() الإضافية على مدونته ضمن نشر شبكة CSS سريعة الاستجابة بشكل أساسي باستخدام minmax() min(). أنصحك بقراءة ذلك. تصحيح محاذاة flex-start هو بإزالة تأثير التوسيع الافتراضي، بحيث لا تكون العناصر الثانوية لهذا التخطيط يلزم أن يكون لها ارتفاعات متساوية، ويمكن أن يكون لها ارتفاعات طبيعية جوهرية. تشير رسالة الأشكال البيانية ويحتوي فيديو YouTube على تفاصيل سريعة حول إضافة المحاذاة هذه.

تستحق المشاركة max-width: 89vw تحليلاً بسيطًا في هذه المشاركة. لأريك التنسيق مع تطبيق النمط وبدونه:

ماذا يحدث؟ عند تحديد max-width، فإنه يوفر السياق، بالحجم الصريح أو محدد تغيير حجم auto-fit خوارزمية التخطيط لمعرفة مدى والعديد من التكرارات التي يمكن أن تتناسب مع المساحة. وفي حين أنه يبدو واضحًا أن تكون المساحة "بالعرض الكامل"، وفقًا لمواصفات شبكة CSS، يجب أن يكون الحجم المحدّد أو الحد الأقصى للحجم النهج التحليلي. لقد قدمتُ الحد الأقصى للحجم.

إذًا، ما سبب اختيار 89vw؟ لأنّها "نجحت" لتخطيطي. أتحقق أنا واثنين من الأشخاص الآخرين في Chrome من سبب تقديم قيمة معقولة أكثر، مثل 100vw لا تكفي، وإذا كان هذا في الواقع خطأ.

المسافات

يأتي أغلب التناغم في هذا التخطيط من خلال لوحة محدودة من المسافات، على وجه الدقة.

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

مكافأة 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. الإبهام

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

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 للحفاظ على نمط التعبئة. هناك هي استراتيجيات 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));
  })
})

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

إليك المشاركة على CSS-Tricks من آنا التيودورية، التي توضح استخدام حل 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-space.

تسهيل الاستخدام

يقدم مقطع فيديو YouTube عرضًا توضيحيًا رائعًا للماوس ولوحة المفاتيح تفاعلات قارئ الشاشة لمكون الإعدادات هذا. سأذكر بعضًا من التفاصيل هنا.

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

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

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

سمات HTML

يمكننا إخفاء العناصر التي لا تحتاجها برامج قراءة الشاشة، وهو في هذه الحالة الرمز بجوار شريط التمرير:

<picture aria-hidden="true">

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

رسم 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()، حيث يتم عرض بيانات النموذج في جدول

الخاتمة

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

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

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

  • @tomayac مع أسلوبهم بخصوص منطقة التمرير فوق تصنيفات مربّعات الاختيار! لا يحتوي هذا الإصدار على فجوة تمرير بين العناصر: demo المصدر.