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

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

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

إصدار تجريبي

إذا كنت تفضّل مشاهدة الفيديوهات أو تريد معاينة ما ننشئه عبر واجهة المستخدم/تجربة المستخدم، إليك جولة تفصيلية أقصر على 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 إضافات خاصة في تخطيطنا، إذا قارنته بتخطيط أونا:

  • نمرّر دالة min() إضافية.
  • نحدد align-items: flex-start.
  • يتوفّر نمط max-width: 89vw.

وصف إيفان مينتو دالة min() الإضافية بشكل جيد على مدونته في مشاركة Intrinsically Adaptive CSS Grid مع minmax() و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 @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: 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 تدرج اللون: اللون الرمادي الغامق عديم اللون. بعد ذلك، في الاستعلام عن الوسائط لوضع الإضاءة، يتم قلب الإضاءة إلى 90% باستخدام --surface1: lch(90 0 0);. وهذا هو جوهر الاستراتيجية. ابدأ فقط بتغيير الإضاءة بين الموضوعين، والحفاظ على نسب التباين التي يتطلبها التصميم أو ما يمكن أن يحافظ على سهولة الوصول.

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

هناك المزيد لنتعلمه حول مساحات الألوان وlch() إذا كنت مهتمًا. إنه قادم!

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

الخلاصة

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

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

ريمكسات من المنتدى

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