ภาพรวมพื้นฐานเกี่ยวกับวิธีสร้างคอมโพเนนต์การตั้งค่าของแถบเลื่อนและช่องทําเครื่องหมาย
ในโพสต์นี้ เราต้องการแชร์แนวคิดในการสร้างคอมโพเนนต์การตั้งค่าสําหรับเว็บที่ปรับเปลี่ยนตามพื้นที่โฆษณา รองรับอินพุตจากอุปกรณ์หลายเครื่อง และทํางานได้กับเบราว์เซอร์หลายประเภท ลองใช้เดโม
หากต้องการดูวิดีโอหรือต้องการดูตัวอย่าง UI/UX ของสิ่งที่เรากำลังสร้าง โปรดดูวิดีโอแนะนำแบบสั้นๆ บน YouTube ต่อไปนี้
ภาพรวม
เราได้แยกแง่มุมต่างๆ ของคอมโพเนนต์นี้ออกเป็นส่วนต่อไปนี้
- เลย์เอาต์
- สี
- การป้อนช่วงที่กำหนดเอง
- อินพุตช่องทําเครื่องหมายที่กําหนดเอง
- ข้อควรพิจารณาเกี่ยวกับการช่วยเหลือพิเศษ
- JavaScript
เลย์เอาต์
นี่เป็นตัวอย่าง GUI Challenge รายการแรกที่เป็น CSS Grid ทั้งหมด ตารางกริดแต่ละตารางที่ไฮไลต์ด้วย Chrome DevTools สําหรับตารางกริดมีดังนี้
เฉพาะสำหรับช่องว่าง
เลย์เอาต์ที่พบบ่อยที่สุด
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
ตัวย่อการจัดตำแหน่งเพื่อให้องค์ประกอบย่อยอยู่กึ่งกลางทั้งแนวตั้งและแนวนอนทั้งในเลย์เอาต์คอลัมน์เดียวและ 2 คอลัมน์
ดูในวิดีโอด้านบนว่า "เนื้อหา" อยู่ตรงกลางอย่างไร แม้ว่าจะมีการตัดขึ้นบรรทัดใหม่แล้วก็ตาม
ปรับขนาดขั้นต่ำและสูงสุดอัตโนมัติซ้ำ
<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 คุณต้องระบุขนาดที่แน่นอนหรือขนาดสูงสุด เราได้ระบุขนาดสูงสุดแล้ว
แล้วทำไมต้องเป็น 89vw
เนื่องจาก "ได้ผล" สำหรับเลย์เอาต์ของฉัน
เราและทีม Chrome อีก 2 คนกำลังตรวจสอบสาเหตุที่ค่าที่เหมาะสมกว่า เช่น 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 ฉันจะพลิกสีเหล่านั้น และสีอ่อนและสีเข้มจะไม่มีความหมาย
ฉันจะพลิกในคําค้นหาสื่อตามค่ากําหนดดังนี้
: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) ซึ่งมีข้อดีตรงที่มนุษย์เขียนได้ง่ายขึ้นและผู้ใช้คนอื่นๆ จะเข้าใจการปรับเหล่านี้
ในวันนี้ เราจะโฟกัสไปที่ไวยากรณ์และค่าที่ฉันจะสลับเพื่อทำให้สว่างและมืด มาดูพื้นผิว 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);
}
ป๊อปสีด้วยการไล่ระดับสีแบบคงที่และโฟกัสภายใน
สีจะโดดเด่นที่สุดเมื่อใช้อย่างจำกัด และวิธีที่เราชอบใช้เพื่อดึงดูดความสนใจด้วยสีคือการใช้การโต้ตอบ 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
- พื้นหลัง
.fieldset-item
ได้รับการกําหนดสีพื้นผิวที่มีความคมชัดสูงกว่า svg
ที่ฝังอยู่จะเติมสีขาวเพื่อให้คอนทราสต์สูงขึ้น<picture>
clip-path
ที่ซ้อนกันจะขยายเป็นวงกลมเต็มรูปแบบ และพื้นหลังจะเต็มไปด้วยไล่ระดับสีแบบคงที่ที่สว่าง
ช่วงที่กำหนดเอง
เราจะแสดงวิธีปรับแต่งลักษณะที่ปรากฏขององค์ประกอบอินพุต HTML ต่อไปนี้
<input type="range">
องค์ประกอบนี้มีส่วนที่ต้องปรับแต่ง 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 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 เท่านั้น แต่กำหนดให้องค์ประกอบภาพปกมีความสูงเท่ากับแทร็ก และเราไม่สามารถหาความสอดคล้องภายในข้อจำกัดเหล่านั้นได้
/* 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 ส่วน ได้แก่
องค์ประกอบช่องทําเครื่องหมาย
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>
สำหรับชื่อที่แสดงเมื่อวางเมาส์เหนือ และความคิดเห็นที่มนุษย์อ่านได้เกี่ยวกับสิ่งที่คณิตศาสตร์สร้างขึ้นกัน
<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);
})
ทุกครั้งที่มีการใช้และเปลี่ยนแปลงแบบฟอร์ม คอนโซลจะบันทึกแบบฟอร์มเป็นออบเจ็กต์ลงในตารางเพื่อให้ตรวจสอบได้ง่ายก่อนที่จะส่งไปยังเซิร์ฟเวอร์
บทสรุป
ตอนนี้คุณรู้วิธีที่เราทําแล้ว คุณจะทําอย่างไร นี่เป็นสถาปัตยกรรมคอมโพเนนต์ที่น่าสนใจ ใครจะสร้างเวอร์ชันที่ 1 ด้วยช่องในเฟรมเวิร์กโปรด 🙂
มาลองใช้แนวทางที่หลากหลายและดูวิธีทั้งหมดในการสร้างบนเว็บกัน สร้างเดโม แล้วทวีตลิงก์มาหาฉัน ฉันจะเพิ่มลงในส่วนรีมิกซ์ของชุมชนด้านล่าง