ภาพรวมพื้นฐานของวิธีสร้างองค์ประกอบการตั้งค่าของแถบเลื่อนและช่องทำเครื่องหมาย
ในโพสต์นี้ ผมอยากจะแชร์ความคิดเกี่ยวกับการสร้างองค์ประกอบการตั้งค่าสำหรับเว็บที่ตอบสนอง รองรับอินพุตของอุปกรณ์หลายรายการ และทำงานในเบราว์เซอร์ต่างๆ ทดลองใช้การสาธิต
หากคุณต้องการดูวิดีโอหรืออยากเห็นตัวอย่าง UI/UX ของสิ่งที่เรากำลังสร้าง เรามีคำแนะนำสั้นๆ ใน YouTube ดังต่อไปนี้
ภาพรวม
ฉันได้แบ่งส่วนต่างๆ ของคอมโพเนนต์นี้ออกเป็นส่วนต่างๆ ดังต่อไปนี้
- เลย์เอาต์
- สี
- อินพุตช่วงที่กำหนดเอง
- อินพุตช่องทำเครื่องหมายที่กำหนดเอง
- ข้อควรพิจารณาเกี่ยวกับการช่วยเหลือพิเศษ
- JavaScript
เลย์เอาต์
นี่เป็นการสาธิตภารกิจ GUI ครั้งแรกที่เป็นตารางกริด 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
เพื่อให้เด็กอยู่กึ่งกลางในแนวตั้งและแนวนอนทั้งในเลย์เอาต์แบบ 1 และ 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()
เพิ่มเติมไว้เป็นอย่างดีในบล็อกของบริษัทใน
โพสต์ Intrinsically การปรับเปลี่ยน CSS Grid with minmax() และ
min()
เราขอแนะนำให้ลองอ่านดู การแก้ไขการจัดข้อความ flex-start
คือการนำเอฟเฟกต์การยืดเริ่มต้นออก เพื่อให้องค์ประกอบย่อยของเลย์เอาต์นี้ไม่จำเป็นต้องมีความสูงเท่ากัน แต่มีความสูงได้ตามธรรมชาติ วิดีโอ YouTube มีรายละเอียดสั้นๆ เกี่ยวกับการเพิ่มความสอดคล้องนี้
max-width: 89vw
มีรายละเอียดเล็กน้อยในโพสต์นี้
ขอแสดงเลย์เอาต์ที่มีและไม่มีการใช้สไตล์
บอกว่าคุณกำลังคิดอะไรอยู่ เมื่อระบุ max-width
จะเป็นการให้บริบท การปรับขนาดแบบโจ่งแจ้ง หรือการกำหนดขนาดที่แน่นอนสำหรับอัลกอริทึมเลย์เอาต์ของ auto-fit
เพื่อให้ทราบจำนวนคำทำซ้ำที่จะใส่ลงในพื้นที่ได้ แม้จะเห็นได้ชัดว่าพื้นที่ว่างเป็น "ความกว้างเต็ม" แต่ตามข้อกำหนดของตาราง CSS จะต้องระบุขนาดที่แน่นอนหรือขนาดสูงสุด ระบุขนาดสูงสุดแล้ว
ทำไมต้องเป็น 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
เพราะในคิวรี่สื่อ ฉันจะสลับสี
ส่วนสีอ่อนและสีเข้มจะไม่สื่อความหมาย
โดยจะพลิกในคำค้นหาสื่อที่ต้องการ ดังนี้
: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 ที่การออกแบบของคุณใช้
รูปภาพด้านบนแสดงให้เห็นผลกระทบของพร็อพเพอร์ตี้จากแผงสไตล์ของเครื่องมือสำหรับนักพัฒนาเว็บ เดโมนี้ใช้แท็ก 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;
}
}
}
เมื่อรายการย่อยอย่างใดอย่างหนึ่งขององค์ประกอบนี้มีโฟกัสจากภายใน:
- พื้นหลัง
.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 */
}
2-3 บรรทัดแรกของ 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 ส่วน ดังนี้
องค์ประกอบช่องทำเครื่องหมาย
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 ซึ่งมีสล็อตในเฟรมเวิร์กโปรด 🙂
มาลองเปลี่ยนแนวทางของเราและเรียนรู้วิธีทั้งหมดเพื่อสร้างเว็บกันเถอะ สร้างเดโม ลิงก์ทวีตฉัน แล้วฉันจะเพิ่มลงในส่วนรีมิกซ์ของชุมชนด้านล่าง
รีมิกซ์ของชุมชน
- @tomayac ด้วยสไตล์เกี่ยวกับพื้นที่ สำหรับการวางเมาส์สำหรับป้ายกำกับช่องทำเครื่องหมาย เวอร์ชันนี้ไม่มีช่องว่างการวางเมาส์ระหว่างองค์ประกอบ: การสาธิตและแหล่งที่มา