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

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

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

สาธิต

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

ภาพรวม

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

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

เลย์เอาต์

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

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

เพื่อช่องว่าง

เลย์เอาต์ที่ใช้กันมากที่สุดมีดังนี้

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

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

เลย์เอาต์ 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 และตารางกริดสามารถรองรับ align-items หรือ align-content และเมื่อจัดการกับองค์ประกอบการรวม เลย์เอาต์แบบ content การจัดแนวขอบจะกระจายพื้นที่ในกลุ่มเด็ก

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

องค์ประกอบหลักใช้การจัดแนว place-content: center Shorthand ดังนั้น ให้เด็กอยู่กึ่งกลางในแนวตั้งและแนวนอนทั้งในเลย์เอาต์แบบ 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's:

  • เราส่งฟังก์ชัน 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 ขนาดที่แน่นอนหรือขนาดสูงสุดต้องมี ให้ไว้ เราระบุขนาดสูงสุดแล้ว

แล้วทำไมต้องเป็น 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

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

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

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

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

เลอา เวรู

การควบคุมแบบฟอร์มแบบปรับได้พร้อมรูปแบบสี

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

ข้อมูลด้านบนกำลังแสดงถึงผลกระทบของพร็อพเพอร์ตี้จากแผงรูปแบบของ เครื่องมือสำหรับนักพัฒนาเว็บ การสาธิตใช้แท็ก 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;
    }
  }
}

เมื่อหนึ่งในองค์ประกอบย่อยขององค์ประกอบนี้มีจุดโฟกัสอยู่ภายใน:

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

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

จากองค์ประกอบอินพุต 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;
}

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

ติดตามรูปแบบการเติมสี

การออกแบบของฉันต้องใช้ 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 โดย 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 ประการ วิธีแรกคือ ระบุว่าค่าช่องทำเครื่องหมายนั้นใช้สำหรับอะไร โดยตอบคำถามว่า "เปิดหรือปิดสำหรับอะไร" อย่างที่ 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"> ในช่องทำเครื่องหมาย ให้เพิ่มทั้งชื่อและรหัส 2 เท่าไปยัง เพื่อให้แน่ใจว่าเนื้อหาจะได้รับการค้นพบด้วยเครื่องมือและเทคโนโลยีที่หลากหลาย เช่น เมาส์หรือโปรแกรมอ่านหน้าจอ <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-space เล็กน้อย

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

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