การสร้างคอมโพเนนต์การตั้งค่า

ภาพรวมพื้นฐานของวิธีสร้างคอมโพเนนต์การตั้งค่าของแถบเลื่อนและช่องทําเครื่องหมาย

ในโพสต์นี้ ผมอยากจะแชร์แนวคิดในการสร้างคอมโพเนนต์การตั้งค่าสำหรับเว็บที่ตอบสนอง รองรับอินพุตจากอุปกรณ์หลายเครื่อง และทำงานได้ในเบราว์เซอร์ต่างๆ ลองใช้เดโม

การสาธิต

หากต้องการดูวิดีโอหรือดูตัวอย่าง UI/UX ของสิ่งที่เรากำลังสร้าง ให้ดู คำแนะนำแบบสั้นๆ บน YouTube ที่นี่

ภาพรวม

ฉันได้แบ่งแง่มุมของคอมโพเนนต์นี้ออกเป็นส่วนต่างๆ ดังนี้

  1. เลย์เอาต์
  2. สี
  3. การป้อนช่วงที่กำหนดเอง
  4. ช่องทำเครื่องหมายที่กำหนดเอง
  5. ข้อควรพิจารณาเกี่ยวกับการช่วยเหลือพิเศษ
  6. JavaScript

เลย์เอาต์

นี่คือการสาธิต GUI Challenge ครั้งแรกที่ใช้ CSS Grid ทั้งหมด ต่อไปนี้คือแต่ละตารางกริด ที่ไฮไลต์ด้วยเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome สำหรับกริด

ภาพซ้อนทับของเส้นขอบสีสันสดใสและการเว้นช่องว่างที่ช่วยแสดงช่องทั้งหมดที่ประกอบกันเป็นเลย์เอาต์การตั้งค่า

สำหรับช่องว่างเท่านั้น

เลย์เอาต์ที่พบบ่อยที่สุด

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

ฉันเรียกเลย์เอาต์นี้ว่า "just for gap" เพราะใช้เฉพาะกริดเพื่อเพิ่มช่องว่างระหว่างบล็อก

เลย์เอาต์ 5 แบบใช้กลยุทธ์นี้ โดยเลย์เอาต์ทั้งหมดจะแสดงดังนี้

เลย์เอาต์ตารางกริดแนวตั้งที่ไฮไลต์ด้วยเส้นขอบและช่องว่างที่เติม

องค์ประกอบ 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 การจัดแนว แบบย่อเพื่อให้องค์ประกอบย่อยอยู่ตรงกลางทั้งในแนวตั้งและแนวนอนในเลย์เอาต์แบบ 1 และ 2 คอลัมน์

ดูในวิดีโอด้านบนว่า "เนื้อหา" จะอยู่ตรงกลางเสมอแม้ว่าจะมีการตัดคำก็ตาม

ทำซ้ำการปรับพอดีอัตโนมัติ minmax

<form> ใช้เลย์เอาต์ตารางกริดแบบปรับได้สำหรับแต่ละส่วน เลย์เอาต์นี้จะเปลี่ยนจาก 1 คอลัมน์เป็น 2 คอลัมน์ตามพื้นที่ที่มี

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 ใช้ฟังก์ชัน CSS 3 รายการ ได้แก่ repeat(), minmax() และ min() Una Kravets มีบล็อกโพสต์เกี่ยวกับเลย์เอาต์ที่ยอดเยี่ยมในเรื่องนี้ โดยเรียกเลย์เอาต์นี้ว่า RAM

เลย์เอาต์ของเรามีส่วนพิเศษ 3 อย่างเมื่อเทียบกับเลย์เอาต์ของ Una

  • เราส่งฟังก์ชัน min() เพิ่มเติม
  • เราจะระบุ align-items: flex-start
  • มีสไตล์ max-width: 89vw

Evan Minto ได้อธิบายฟังก์ชัน min() เพิ่มเติมไว้ในบล็อกของตนเองในโพสต์กริด CSS ที่ตอบสนองโดยธรรมชาติด้วย minmax() และ min() ฉันขอแนะนำให้คุณอ่านโพสต์ดังกล่าว flex-startการแก้ไขการจัดแนวมีไว้เพื่อ นำเอฟเฟกต์การยืดเริ่มต้นออก เพื่อให้องค์ประกอบย่อยของเลย์เอาต์นี้ไม่ จำเป็นต้องมีความสูงเท่ากัน แต่สามารถมีความสูงตามธรรมชาติได้ วิดีโอ YouTube มีการอธิบายโดยย่อเกี่ยวกับการเพิ่มการจัดแนวนี้

max-width: 89vw ควรมีรายละเอียดเล็กๆ ในโพสต์นี้ เราจะแสดงเลย์เอาต์ที่มีและไม่มีการใช้สไตล์ให้คุณดู

บอกว่าคุณกำลังคิดอะไรอยู่ เมื่อระบุ max-width จะเป็นการให้บริบท การกำหนดขนาดที่ชัดเจน หรือการกำหนด ขนาดที่แน่นอนสำหรับauto-fit อัลกอริทึมเลย์เอาต์เพื่อให้ทราบว่า สามารถทำซ้ำได้กี่ครั้งในพื้นที่ แม้ว่าดูเหมือนว่าช่องว่างจะเป็น "ความกว้างเต็ม" แต่ตามข้อกำหนดของ CSS Grid คุณต้องระบุขนาดที่แน่นอนหรือขนาดสูงสุด ฉันได้ระบุ max-size แล้ว

แล้วทำไมจึงควรใช้ 89vw เพราะ "มันใช้ได้" กับเลย์เอาต์ของฉัน ฉันและทีม Chrome อีก 2-3 คนกำลังตรวจสอบว่าทำไมค่าที่สมเหตุสมผลกว่า เช่น 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 เพราะใน Media Query ฉันจะพลิก สีเหล่านั้น และสีอ่อนและสีเข้มจะไม่มีความหมาย

ฉันพลิกค่าใน Media Query ของค่ากำหนดแบบนี้

: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 Podcast

สําหรับวันนี้ ในการสาธิตนี้ เรามาโฟกัสที่ไวยากรณ์และค่าที่ฉันสลับ เพื่อทําให้เป็นโหมดสว่างและโหมดมืดกัน มาดูพื้นผิว 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 เฉดสี: สีเทาเข้มมากไม่มีสี จากนั้นในคิวรี่สื่อสำหรับโหมดสว่าง ความสว่าง จะเปลี่ยนเป็น 90% ด้วย --surface1: lch(90 0 0); และนี่คือสาระสำคัญของ กลยุทธ์ เริ่มจากการเปลี่ยนความสว่างระหว่าง 2 ธีม โดยรักษาสัดส่วนความคมชัดตามที่การออกแบบต้องการหรือสิ่งที่รักษาระดับการช่วยเหลือพิเศษได้

ข้อดีของ lch() คือความสว่างเป็นสิ่งที่มนุษย์รับรู้ได้ และเราจะรู้สึกดีกับ% ที่เปลี่ยนแปลงไป เพราะจะรับรู้ได้ว่า% แตกต่างกันอย่างสม่ำเสมอ hsl() เช่น ไม่น่าเชื่อถือ

คุณดูข้อมูลเพิ่มเติมเกี่ยวกับ พื้นที่สีและ lch() ได้หากสนใจ กำลังจะมา

ขณะนี้ CSS ไม่สามารถเข้าถึงสีเหล่านี้ได้เลย ขอย้ำอีกครั้งว่าเราไม่มีสิทธิ์เข้าถึงสี 1 ใน 3 ในจอภาพรุ่นใหม่ส่วนใหญ่ และไม่ใช่แค่สีใดก็ได้ แต่เป็นสีที่สดใสที่สุดที่หน้าจอแสดงได้ เว็บไซต์ของเรามีสีซีดจางเนื่องจากฮาร์ดแวร์ของจอภาพพัฒนาไป เร็วกว่าข้อกำหนด CSS และการใช้งานเบราว์เซอร์

Lea Verou

การควบคุมแบบฟอร์มแบบปรับอัตโนมัติที่มีรูปแบบสี

เบราว์เซอร์หลายตัวมีตัวควบคุมธีมมืด เช่น Safari และ Chromium แต่คุณต้องระบุใน CSS หรือ HTML ว่าการออกแบบของคุณใช้ตัวควบคุมเหล่านั้น

ด้านบนแสดงให้เห็นถึงผลลัพธ์ของพร็อพเพอร์ตี้จากแผงรูปแบบของ DevTools การสาธิตใช้แท็ก HTML ซึ่งในความคิดของฉันโดยทั่วไปแล้วเป็นตำแหน่งที่ดีกว่า

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

ดูข้อมูลทั้งหมดเกี่ยวกับเรื่องนี้ได้ในcolor-scheme บทความโดย Thomas Steiner คุณจะได้รับประโยชน์มากกว่า แค่ช่องทำเครื่องหมายสีเข้ม

CSS accent-color

มีกิจกรรมล่าสุดเกี่ยวกับ accent-color ในองค์ประกอบของแบบฟอร์ม ซึ่งเป็นรูปแบบ CSS เดียวที่เปลี่ยนสี เฉดสีที่ใช้ในองค์ประกอบอินพุตของเบราว์เซอร์ได้ อ่านเพิ่มเติมเกี่ยวกับเรื่องนี้ได้ที่นี่ใน GitHub เราได้รวมไว้ใน สไตล์สำหรับคอมโพเนนต์นี้แล้ว เมื่อเบราว์เซอร์รองรับแล้ว ช่องทำเครื่องหมายของฉันจะ สอดคล้องกับธีมที่มีสีชมพูและสีม่วงมากขึ้น

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

ภาพหน้าจอจาก Chromium ใน Linux ของช่องทําเครื่องหมายสีชมพู

ป๊อปสีที่มีการไล่ระดับสีแบบคงที่และโฟกัสภายใน

สีจะโดดเด่นที่สุดเมื่อใช้ในปริมาณที่พอเหมาะ และวิธีหนึ่งที่ฉันชอบใช้เพื่อให้ได้ผลลัพธ์ดังกล่าวคือการโต้ตอบ UI ที่มีสีสัน

วิดีโอด้านบนมีการโต้ตอบและฟีดแบ็ก UI หลายชั้น ซึ่งช่วยให้การโต้ตอบมีเอกลักษณ์เฉพาะตัวด้วยวิธีต่อไปนี้

  • การไฮไลต์บริบท
  • แสดงความคิดเห็นเกี่ยวกับ UI ของ "ระดับ" ค่าในช่วง
  • แสดงความคิดเห็นเกี่ยวกับ 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;
    }
  }
}

เมื่อองค์ประกอบย่อยรายการใดรายการหนึ่งขององค์ประกอบนี้มี focus-within

  1. ระบบจะกำหนดสีพื้นผิวที่มีคอนทราสต์สูงกว่าให้กับพื้นหลัง .fieldset-item
  2. svg ที่ซ้อนกันจะเติมสีขาวเพื่อให้มีคอนทราสต์สูงขึ้น
  3. <picture> clip-path ที่ซ้อนกันจะขยายเป็นวงกลมเต็มวงและ พื้นหลังจะเต็มไปด้วยการไล่ระดับสีแบบคงที่ที่สว่าง

ช่วงที่กำหนดเอง

เมื่อพิจารณาองค์ประกอบอินพุต HTML ต่อไปนี้ ฉันจะแสดงให้คุณเห็นวิธีที่ฉันปรับแต่งลักษณะที่ปรากฏขององค์ประกอบนี้

<input type="range">

องค์ประกอบนี้มี 3 ส่วนที่เราต้องปรับแต่ง ได้แก่

  1. องค์ประกอบ / คอนเทนเนอร์ช่วง
  2. ติดตาม
  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 2-3 บรรทัดแรกคือส่วนที่กำหนดเองของสไตล์ และเราหวังว่าการติดป้ายกำกับอย่างชัดเจนจะช่วยคุณได้ ส่วนรูปแบบที่เหลือส่วนใหญ่เป็นรูปแบบรีเซ็ตเพื่อ เป็นพื้นฐานที่สอดคล้องกันสำหรับการสร้างส่วนที่ซับซ้อนของคอมโพเนนต์

แทร็กสไตล์

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 เท่านั้น แต่ต้องให้องค์ประกอบ Thumb มีความสูงเท่ากับแทร็ก และฉันไม่สามารถหาความสอดคล้องภายในขีดจำกัดเหล่านั้นได้

/* 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 โดย 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) องค์ประกอบหลักที่ผู้ปกครองสร้างขึ้นเป็นพื้นที่ 3 มิติ และองค์ประกอบย่อยเสมือนนี้แตะเข้าไปในพื้นที่ดังกล่าวโดย วางตัวเองไว้ด้านหลังเล็กน้อยในพื้นที่ Z

การช่วยเหลือพิเศษ

วิดีโอ YouTube แสดงให้เห็นถึงการโต้ตอบของเมาส์ คีย์บอร์ด และโปรแกรมอ่านหน้าจอสำหรับคอมโพเนนต์การตั้งค่านี้ได้อย่างยอดเยี่ยม เราจะพูดถึงรายละเอียดบางส่วนที่นี่

ตัวเลือกองค์ประกอบ HTML

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

ซึ่งแต่ละส่วนจะมีคำแนะนำและเคล็ดลับสำหรับเครื่องมือการท่องเว็บของผู้ใช้ องค์ประกอบบางอย่าง ให้คำแนะนำในการโต้ตอบ บางอย่างเชื่อมต่อการโต้ตอบ และบางอย่างช่วยสร้าง โครงสร้างการช่วยเหลือพิเศษที่โปรแกรมอ่านหน้าจอใช้ในการไปยังส่วนต่างๆ

แอตทริบิวต์ HTML

เราสามารถซ่อนองค์ประกอบที่ไม่จำเป็นสำหรับโปรแกรมอ่านหน้าจอได้ ในกรณีนี้คือไอคอนข้างแถบเลื่อน

<picture aria-hidden="true">

วิดีโอด้านบนแสดงขั้นตอนการทำงานของโปรแกรมอ่านหน้าจอใน Mac OS สังเกตว่าโฟกัสของอินพุต จะย้ายจากแถบเลื่อนหนึ่งไปยังแถบเลื่อนถัดไปโดยตรง เนื่องจากเราได้ซ่อน ไอคอนที่อาจเป็นจุดหยุดระหว่างทางไปยังแถบเลื่อนถัดไป หากไม่มีแอตทริบิวต์นี้ ผู้ใช้จะต้องหยุด ฟัง และข้ามรูปภาพที่อาจมองไม่เห็น

SVG เป็นชุดของคณิตศาสตร์ มาเพิ่มองค์ประกอบ <title> สำหรับการวางเมาส์ฟรี 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 ที่มีสไตล์เกี่ยวกับ พื้นที่วางเมาส์สำหรับป้ายกำกับช่องทำเครื่องหมาย เวอร์ชันนี้ไม่มีช่องว่างเมื่อวางเมาส์ระหว่างองค์ประกอบ การสาธิตและ แหล่งที่มา