ภาพรวมพื้นฐานเกี่ยวกับวิธีสร้าง<button>คอมโพเนนต์ที่ปรับสีตามบริบท ตอบสนอง และเข้าถึงได้
ในโพสต์นี้ ฉันอยากจะแชร์ความคิดเห็นเกี่ยวกับวิธีสร้างองค์ประกอบ <button> ที่ปรับสีได้
ตอบสนอง และเข้าถึงได้
ลองใช้เดโมและดู
แหล่งที่มา
หากต้องการดูวิดีโอ โปรดดูโพสต์นี้ใน YouTube
ภาพรวม
องค์ประกอบ
<button>
สร้างขึ้นเพื่อการโต้ตอบของผู้ใช้ clickทริกเกอร์เหตุการณ์จากคีย์บอร์ด
เมาส์ การสัมผัส เสียง และอื่นๆ พร้อมกฎอัจฉริยะเกี่ยวกับ
เวลา นอกจากนี้ ยังมี
สไตล์เริ่มต้นบางอย่างในแต่ละเบราว์เซอร์ด้วย คุณจึงใช้สไตล์เหล่านั้นได้โดยตรงโดยไม่ต้อง
ปรับแต่งใดๆ ใช้ color-scheme เพื่อเลือกใช้ปุ่มธีมสว่างและธีมมืดที่เบราว์เซอร์มีให้ด้วย
นอกจากนี้ยังมีปุ่มประเภทต่างๆ
ซึ่งแต่ละปุ่มจะแสดงในโค้ดที่ฝังใน Codepen ก่อนหน้า <button> ที่ไม่มีประเภทจะ
ปรับให้เข้ากับ <form> โดยเปลี่ยนเป็นประเภทส่ง
<!-- buttons -->
<button></button>
<button type="submit"></button>
<button type="button"></button>
<button type="reset"></button>
<!-- button state -->
<button disabled></button>
<!-- input buttons -->
<input type="button" />
<input type="file">
ในความท้าทายด้าน GUI ของเดือนนี้ ปุ่มแต่ละปุ่มจะมีสไตล์ที่ช่วยให้เห็นความแตกต่างของเจตนา ปุ่มรีเซ็ต จะมีสีคำเตือนเนื่องจากเป็นการดำเนินการที่ทำลายข้อมูล และปุ่มส่ง จะมีข้อความสีน้ำเงินเพื่อเน้นให้ดูโดดเด่นกว่าปุ่มปกติเล็กน้อย
ปุ่มยังมีคลาสเสมือน
สำหรับ CSS ที่ใช้ในการจัดรูปแบบด้วย คลาสเหล่านี้มีฮุก CSS สำหรับปรับแต่ง
ลักษณะของปุ่ม: :hover
เมื่อวางเมาส์เหนือปุ่ม
:active เมื่อกดเมาส์
หรือแป้นพิมพ์ และ
:focus หรือ
:focus-visible
เพื่อช่วยในการจัดรูปแบบเทคโนโลยีความช่วยเหลือ
button:hover {}
button:active {}
button:focus {}
button:focus-visible {}
Markup
นอกเหนือจากประเภทปุ่มที่ระบุไว้ในข้อกำหนด HTML แล้ว ฉันยังได้เพิ่ม
ปุ่มที่มีไอคอนและปุ่มที่มีคลาสที่กำหนดเอง btn-custom
<button>Default</button>
<input type="button" value="<input>"/>
<button>
<svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true">
<path d="..." />
</svg>
Icon
</button>
<button type="submit">Submit</button>
<button type="button">Type Button</button>
<button type="reset">Reset</button>
<button disabled>Disabled</button>
<button class="btn-custom">Custom</button>
<input type="file">
จากนั้นในการทดสอบ ระบบจะวางปุ่มแต่ละปุ่มไว้ในแบบฟอร์ม วิธีนี้จะช่วยให้ฉันมั่นใจได้ว่า รูปแบบได้รับการอัปเดตอย่างเหมาะสมสำหรับปุ่มเริ่มต้น ซึ่งทำงานเป็น ปุ่มส่ง นอกจากนี้ ผมยังเปลี่ยนกลยุทธ์ไอคอนจาก SVG แทรกในบรรทัดเป็น SVG ที่มาสก์ เพื่อให้ทั้ง 2 แบบทำงานได้ดีเท่ากัน
<form>
<button>Default</button>
<input type="button" value="<input>"/>
<button>Icon <span data-icon="cloud"></span></button>
<button type="submit">Submit</button>
<button type="button">Type Button</button>
<button type="reset">Reset</button>
<button disabled>Disabled</button>
<button class="btn-custom btn-large" type="button">Large Custom</button>
<input type="file">
</form>
ตอนนี้เมทริกซ์ของชุดค่าผสมค่อนข้างซับซ้อน ปุ่มมีหลายประเภท มีคลาสเทียม และอาจอยู่ในหรือนอกแบบฟอร์ม ทำให้มีปุ่มรวมกันมากกว่า 20 แบบ โชคดีที่ CSS ช่วยให้เราอธิบายแต่ละรายการได้อย่างชัดเจน
การช่วยเหลือพิเศษ
องค์ประกอบปุ่มสามารถเข้าถึงได้โดยธรรมชาติ แต่ก็มีการปรับปรุงที่พบบ่อยอยู่บ้าง
วางเมาส์และโฟกัสพร้อมกัน
ฉันชอบจัดกลุ่ม :hover และ :focus ไว้ด้วยกันโดยใช้ตัวเลือก:is()ฟังก์ชัน
จำลอง ซึ่งจะช่วยให้มั่นใจได้ว่าอินเทอร์เฟซของฉันจะพิจารณารูปแบบแป้นพิมพ์
และเทคโนโลยีความช่วยเหลืออยู่เสมอ
button:is(:hover, :focus) {
…
}
วงแหวนโฟกัสแบบอินเทอร์แอกทีฟ
ฉันต้องการเคลื่อนไหววงแหวนโฟกัสสำหรับผู้ใช้แป้นพิมพ์และเทคโนโลยีความช่วยเหลือ I โดยทำได้ด้วยการเคลื่อนไหวเส้นขอบออกจากปุ่ม 5 พิกเซล แต่จะทำได้ก็ต่อเมื่อปุ่มไม่ได้ใช้งานอยู่เท่านั้น ซึ่งจะสร้างเอฟเฟกต์ที่ทำให้วงแหวนโฟกัส หดกลับไปเป็นขนาดปุ่มเมื่อกด
:where(button, input):where(:not(:active)):focus-visible {
outline-offset: 5px;
}
การตรวจสอบว่าคอนทราสต์ของสีผ่าน
มีคู่สีที่แตกต่างกันอย่างน้อย 4 คู่ในธีมสว่างและมืดที่ต้องพิจารณาคอนทราสต์ของสี ได้แก่ ปุ่ม ปุ่มส่ง ปุ่มรีเซ็ต และปุ่มที่ปิดใช้ เราใช้ VisBug ที่นี่เพื่อ ตรวจสอบและแสดงคะแนนทั้งหมดพร้อมกัน
ซ่อนไอคอนจากผู้ที่มองไม่เห็น
เมื่อสร้างปุ่มไอคอน ไอคอนควรให้การสนับสนุนด้านภาพแก่ข้อความของปุ่ม ซึ่งหมายความว่าไอคอนนี้ไม่มีประโยชน์สำหรับผู้ที่สูญเสียการมองเห็น โชคดีที่เบราว์เซอร์มีวิธีซ่อนรายการจากเทคโนโลยีโปรแกรมอ่านหน้าจอ เพื่อให้ผู้ที่สูญเสียการมองเห็นไม่ถูกรบกวนด้วยรูปภาพปุ่มตกแต่ง
<button>
<svg … aria-hidden="true">...</svg>
Icon Button
</button>
รูปแบบ
ในส่วนถัดไปนี้ ฉันจะสร้างระบบพร็อพเพอร์ตี้ที่กำหนดเองเพื่อจัดการ สไตล์ที่ปรับเปลี่ยนได้ของปุ่มก่อน พร็อพเพอร์ตี้ที่กำหนดเองเหล่านั้นช่วยให้ฉันเริ่ม เลือกองค์ประกอบและปรับแต่งลักษณะที่ปรากฏได้
กลยุทธ์พร็อพเพอร์ตี้ที่กําหนดเองแบบปรับได้
กลยุทธ์พร็อพเพอร์ตี้ที่กำหนดเองที่ใช้ใน GUI Challenge นี้คล้ายกับกลยุทธ์ที่ใช้ในการสร้างชุดสีเป็นอย่างมาก สำหรับระบบสีสว่างและสีเข้มแบบปรับได้ ระบบจะกำหนดและตั้งชื่อพร็อพเพอร์ตี้ที่กำหนดเองสำหรับแต่ละธีมตามนั้น จากนั้นจะใช้พร็อพเพอร์ตี้ที่กำหนดเองรายการเดียวเพื่อเก็บ ค่าปัจจุบันของธีมและกำหนดให้กับพร็อพเพอร์ตี้ CSS ต่อมา คุณสามารถอัปเดตพร็อพเพอร์ตี้ที่กำหนดเองรายการเดียว เป็นค่าอื่น แล้วอัปเดตสไตล์ปุ่ม
button {
--_bg-light: white;
--_bg-dark: black;
--_bg: var(--_bg-light);
background-color: var(--_bg);
}
@media (prefers-color-scheme: dark) {
button {
--_bg: var(--_bg-dark);
}
}
สิ่งที่ฉันชอบคือธีมสว่างและธีมมืดนั้นชัดเจนและประกาศได้
การเปลี่ยนเส้นทางและการแยกส่วนจะถูกส่งไปยัง--_bgพร็อพเพอร์ตี้ที่กำหนดเอง
ซึ่งตอนนี้เป็นพร็อพเพอร์ตี้ "เชิงโต้ตอบ" เพียงรายการเดียว ส่วน --_bg-light และ --_bg-dark เป็น
แบบคงที่ นอกจากนี้ ยังอ่านได้ชัดเจนว่าธีมสว่างเป็นธีมเริ่มต้นและ
ธีมมืดจะใช้ในบางกรณีเท่านั้น
การเตรียมพร้อมเพื่อความสอดคล้องของการออกแบบ
ตัวเลือกที่แชร์
ตัวเลือกต่อไปนี้ใช้เพื่อกำหนดเป้าหมายปุ่มประเภทต่างๆ ทั้งหมด และอาจ
ดูซับซ้อนในตอนแรก :where() ใช้
ดังนั้นการปรับแต่งปุ่มจึงไม่จำเป็นต้องระบุ ปุ่มมักจะ
ปรับให้เข้ากับสถานการณ์อื่น และ:where() ตัวเลือกจะช่วยให้งาน
ง่ายขึ้น ภายใน :where() จะมีการเลือกปุ่มแต่ละประเภท รวมถึง
::file-selector-button ซึ่งใช้
ไม่ได้
ภายใน :is() หรือ :where()
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
…
}
พร็อพเพอร์ตี้ที่กำหนดเองทั้งหมดจะอยู่ในขอบเขตภายในตัวเลือกนี้ ถึงเวลาตรวจสอบ พร็อพเพอร์ตี้ที่กำหนดเองทั้งหมดแล้ว ปุ่มนี้ใช้คุณสมบัติที่กำหนดเองหลายรายการ ฉันจะอธิบายแต่ละกลุ่มไปเรื่อยๆ แล้วแชร์บริบทของธีมมืดและลดการเคลื่อนไหวที่ท้ายส่วน
สีเน้นของปุ่ม
ปุ่มส่งและไอคอนเป็นจุดที่เหมาะสำหรับการเพิ่มสีสัน
--_accent-light: hsl(210 100% 40%);
--_accent-dark: hsl(210 50% 70%);
--_accent: var(--_accent-light);
สีข้อความบนปุ่ม
สีของข้อความบนปุ่มไม่ใช่สีขาวหรือสีดำ แต่เป็นเวอร์ชันที่เข้มขึ้นหรืออ่อนลง
ของ --_accent โดยใช้
hsl() และ
ยึดตามเฉดสี 210
--_text-light: hsl(210 10% 30%);
--_text-dark: hsl(210 5% 95%);
--_text: var(--_text-light);
สีพื้นของปุ่ม
พื้นหลังของปุ่มจะใช้hsl() รูปแบบเดียวกัน ยกเว้นปุ่มในธีมสว่าง
ซึ่งจะตั้งค่าเป็นสีขาวเพื่อให้พื้นผิวของปุ่มดูเหมือนอยู่ใกล้กับ
ผู้ใช้ หรืออยู่ด้านหน้าพื้นผิวอื่นๆ
--_bg-light: hsl(0 0% 100%);
--_bg-dark: hsl(210 9% 31%);
--_bg: var(--_bg-light);
ช่องพื้นหลังของปุ่ม
สีพื้นหลังนี้ใช้เพื่อทำให้พื้นผิวปรากฏอยู่ด้านหลังพื้นผิวอื่นๆ ซึ่งมีประโยชน์สำหรับพื้นหลังของอินพุตไฟล์
--_input-well-light: hsl(210 16% 87%);
--_input-well-dark: hsl(204 10% 10%);
--_input-well: var(--_input-well-light);
ระยะห่างจากขอบของปุ่ม
การเว้นวรรคข้อความในปุ่มจะทำโดยใช้หน่วย
ch
ซึ่งเป็นความยาวสัมพัทธ์กับขนาดแบบอักษร ซึ่งจะมีความสำคัญอย่างยิ่งเมื่อปุ่มขนาดใหญ่สามารถเพิ่มfont-sizeและขนาดปุ่ม
ตามสัดส่วนได้ง่ายๆ
--_padding-inline: 1.75ch;
--_padding-block: .75ch;
เส้นขอบของปุ่ม
ระบบจะซ่อนรัศมีเส้นขอบปุ่มไว้ในพร็อพเพอร์ตี้ที่กำหนดเองเพื่อให้อินพุตไฟล์ ตรงกับปุ่มอื่นๆ สีเส้นขอบจะเป็นไปตามระบบสีที่ปรับเปลี่ยนได้ ที่กำหนดไว้ ดังนี้
--_border-radius: .5ch;
--_border-light: hsl(210 14% 89%);
--_border-dark: var(--_bg-dark);
--_border: var(--_border-light);
เอฟเฟกต์ไฮไลต์เมื่อวางเมาส์เหนือปุ่ม
พร็อพเพอร์ตี้เหล่านี้จะสร้างพร็อพเพอร์ตี้ขนาดสำหรับการเปลี่ยนเมื่อมีการโต้ตอบ และ
สีไฮไลต์จะเป็นไปตามระบบสีที่ปรับเปลี่ยนได้ เราจะพูดถึงวิธีที่องค์ประกอบเหล่านี้
โต้ตอบกันในภายหลังของโพสต์นี้ แต่โดยสรุปแล้ว องค์ประกอบเหล่านี้ใช้สำหรับbox-shadow
เอฟเฟกต์ต่อไปนี้
--_highlight-size: 0;
--_highlight-light: hsl(210 10% 71% / 25%);
--_highlight-dark: hsl(210 10% 5% / 25%);
--_highlight: var(--_highlight-light);
เงาข้อความบนปุ่ม
ปุ่มแต่ละปุ่มมีสไตล์เงาข้อความที่ละเอียด ซึ่งจะช่วยให้ข้อความอยู่เหนือปุ่ม ปรับปรุงความสามารถในการอ่าน และเพิ่มเลเยอร์การนำเสนอที่สวยงาม
--_ink-shadow-light: 0 1px 0 var(--_border-light);
--_ink-shadow-dark: 0 1px 0 hsl(210 11% 15%);
--_ink-shadow: var(--_ink-shadow-light);
ไอคอนปุ่ม
ไอคอนมีขนาดเท่ากับ 2 อักขระเนื่องจากหน่วยความยาวสัมพัทธ์ ch อีกครั้ง ซึ่งจะช่วยให้ไอคอนปรับขนาดตามสัดส่วนของข้อความปุ่ม สีไอคอนจะอิงตาม --_accent-color เพื่อให้เป็นสีที่ปรับเปลี่ยนได้และอยู่ในธีม
--_icon-size: 2ch;
--_icon-color: var(--_accent);
เงาปุ่ม
หากต้องการให้เงาปรับให้เข้ากับแสงสว่างและความมืดได้อย่างเหมาะสม เงาจะต้องเปลี่ยนทั้งสีและความทึบแสง เงาของธีมสว่างจะดีที่สุดเมื่อมีความละเอียดอ่อนและมีสี เข้ากับสีพื้นผิวที่ซ้อนทับ เงาของธีมมืดต้องมืดและ อิ่มตัวมากขึ้นเพื่อให้ซ้อนทับสีพื้นผิวที่เข้มกว่าได้
--_shadow-color-light: 220 3% 15%;
--_shadow-color-dark: 220 40% 2%;
--_shadow-color: var(--_shadow-color-light);
--_shadow-strength-light: 1%;
--_shadow-strength-dark: 25%;
--_shadow-strength: var(--_shadow-strength-light);
เมื่อใช้สีและความเข้มแบบปรับได้ ฉันสามารถประกอบเงา 2 ระดับได้ดังนี้
--_shadow-1: 0 1px 2px -1px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 9%));
--_shadow-2:
0 3px 5px -2px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 3%)),
0 7px 14px -5px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 5%));
นอกจากนี้ เพื่อให้ปุ่มดูเป็น 3 มิติเล็กน้อย 1px box-shadow
จะสร้างภาพลวงตา ดังนี้
--_shadow-depth-light: 0 1px var(--_border-light);
--_shadow-depth-dark: 0 1px var(--_bg-dark);
--_shadow-depth: var(--_shadow-depth-light);
การเปลี่ยนปุ่ม
ฉันสร้างพร็อพเพอร์ตี้แบบคงที่ 2 รายการเพื่อเก็บตัวเลือกของระบบการออกแบบตามรูปแบบสำหรับสีที่ปรับเปลี่ยนได้ ดังนี้
--_transition-motion-reduce: ;
--_transition-motion-ok:
box-shadow 145ms ease,
outline-offset 145ms ease
;
--_transition: var(--_transition-motion-reduce);
ที่พักทั้งหมดในเครื่องมือเลือก
:where( button, input[type="button"], input[type="submit"], input[type="reset"], input[type="file"] ), :where(input[type="file"])::file-selector-button { --_accent-light: hsl(210 100% 40%); --_accent-dark: hsl(210 50% 70%); --_accent: var(--_accent-light);--_text-light: hsl(210 10% 30%); --_text-dark: hsl(210 5% 95%); --_text: var(--_text-light);
--_bg-light: hsl(0 0% 100%); --_bg-dark: hsl(210 9% 31%); --_bg: var(--_bg-light);
--_input-well-light: hsl(210 16% 87%); --_input-well-dark: hsl(204 10% 10%); --_input-well: var(--_input-well-light);
--_padding-inline: 1.75ch; --_padding-block: .75ch;
--_border-radius: .5ch; --_border-light: hsl(210 14% 89%); --_border-dark: var(--_bg-dark); --_border: var(--_border-light);
--_highlight-size: 0; --_highlight-light: hsl(210 10% 71% / 25%); --_highlight-dark: hsl(210 10% 5% / 25%); --_highlight: var(--_highlight-light);
--_ink-shadow-light: 0 1px 0 hsl(210 14% 89%); --_ink-shadow-dark: 0 1px 0 hsl(210 11% 15%); --_ink-shadow: var(--_ink-shadow-light);
--_icon-size: 2ch; --_icon-color-light: var(--_accent-light); --_icon-color-dark: var(--_accent-dark); --_icon-color: var(--accent, var(--_icon-color-light));
--_shadow-color-light: 220 3% 15%; --_shadow-color-dark: 220 40% 2%; --_shadow-color: var(--_shadow-color-light); --_shadow-strength-light: 1%; --_shadow-strength-dark: 25%; --_shadow-strength: var(--_shadow-strength-light); --_shadow-1: 0 1px 2px -1px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 9%)); --_shadow-2: 0 3px 5px -2px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 3%)), 0 7px 14px -5px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 5%)) ;
--_shadow-depth-light: hsl(210 14% 89%); --_shadow-depth-dark: var(--_bg-dark); --_shadow-depth: var(--_shadow-depth-light);
--_transition-motion-reduce: ; --_transition-motion-ok: box-shadow 145ms ease, outline-offset 145ms ease ; --_transition: var(--_transition-motion-reduce); }

การปรับธีมมืด
ค่าของรูปแบบพร็อพแบบคงที่ -light และ -dark จะชัดเจนเมื่อตั้งค่าพร็อพของธีมมืด
@media (prefers-color-scheme: dark) {
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
--_bg: var(--_bg-dark);
--_text: var(--_text-dark);
--_border: var(--_border-dark);
--_accent: var(--_accent-dark);
--_highlight: var(--_highlight-dark);
--_input-well: var(--_input-well-dark);
--_ink-shadow: var(--_ink-shadow-dark);
--_shadow-depth: var(--_shadow-depth-dark);
--_shadow-color: var(--_shadow-color-dark);
--_shadow-strength: var(--_shadow-strength-dark);
}
}
ซึ่งไม่เพียงอ่านง่ายเท่านั้น แต่ผู้ใช้ปุ่มที่กำหนดเองเหล่านี้ยังใช้พร็อพเปล่าได้อย่างมั่นใจว่าจะปรับให้เข้ากับค่ากำหนดของผู้ใช้อย่างเหมาะสม
การปรับการเคลื่อนไหวลดลง
หากผู้ใช้ที่มาเยี่ยมชมรายนี้อนุญาตให้มีการเคลื่อนไหว ให้กำหนดค่า --_transition เป็น
var(--_transition-motion-ok) ดังนี้
@media (prefers-reduced-motion: no-preference) {
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
--_transition: var(--_transition-motion-ok);
}
}
รูปแบบที่ใช้ร่วมกันบางส่วน
ปุ่มและอินพุตต้องตั้งค่าแบบอักษรเป็น inherit เพื่อให้ตรงกับแบบอักษรอื่นๆ ในหน้าเว็บ ไม่เช่นนั้นเบราว์เซอร์จะจัดรูปแบบให้ นอกจากนี้ยัง
มีผลกับ letter-spacing ด้วย การตั้งค่า line-height เป็น 1.5 จะกำหนดขนาดแถบดำ
เพื่อเว้นพื้นที่ว่างเหนือและใต้ข้อความ
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
/* …CSS variables */
font: inherit;
letter-spacing: inherit;
line-height: 1.5;
border-radius: var(--_border-radius);
}

การจัดรูปแบบปุ่ม
การปรับตัวเลือก
ตัวเลือก input[type="file"] ไม่ใช่ส่วนปุ่มของอินพุต แต่เป็น
องค์ประกอบเสมือน ::file-selector-button ดังนั้นฉันจึงนำ input[type="file"]
ออกจากรายการ
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
}
การปรับเคอร์เซอร์และการสัมผัส
ก่อนอื่นฉันจะจัดรูปแบบเคอร์เซอร์เป็นรูปแบบ pointer ซึ่งจะช่วยให้ปุ่มระบุ
ต่อผู้ใช้เมาส์ว่าปุ่มนี้โต้ตอบได้ จากนั้นฉันก็เพิ่ม touch-action: manipulation เพื่อ
ให้การคลิกไม่ต้องรอและสังเกตการคลิกซ้ำที่อาจเกิดขึ้น ซึ่งจะทำให้
ปุ่มดูเร็วขึ้น
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
cursor: pointer;
touch-action: manipulation;
}
สีและเส้นขอบ
จากนั้นฉันจะปรับแต่งขนาดแบบอักษร พื้นหลัง ข้อความ และสีเส้นขอบ โดยใช้พร็อพเพอร์ตี้ที่กำหนดเองแบบปรับได้บางส่วนที่สร้างไว้ก่อนหน้านี้
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
font-size: var(--_size, 1rem);
font-weight: 700;
background: var(--_bg);
color: var(--_text);
border: 2px solid var(--_border);
}

เงา
ปุ่มต่างๆ มีการใช้เทคนิคที่ยอดเยี่ยม text-shadow
จะปรับให้เข้ากับธีมสว่างและมืด ทำให้ข้อความปุ่ม
ดูดีและกลมกลืนกับพื้นหลัง สำหรับ
box-shadow
จะมีการกำหนดเงา 3 รายการ เงาแรก --_shadow-2 คือเงาในกล่องปกติ
ส่วนเงาที่ 2 เป็นเทคนิคที่ทำให้ปุ่มดูเหมือน
ยกขึ้นเล็กน้อย เงาสุดท้ายใช้สำหรับการไฮไลต์เมื่อวางเมาส์ ซึ่งตอนแรกจะมีขนาดเป็น 0 แต่จะมีการกำหนดขนาดในภายหลังและเปลี่ยนเพื่อให้ดูเหมือนว่าเงาจะขยายออกมาจากปุ่ม
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
box-shadow:
var(--_shadow-2),
var(--_shadow-depth),
0 0 0 var(--_highlight-size) var(--_highlight)
;
text-shadow: var(--_ink-shadow);
}

เลย์เอาต์
ฉันให้เลย์เอาต์ Flexbox แก่ปุ่ม
โดยเฉพาะเลย์เอาต์ inline-flex ที่จะพอดีกับเนื้อหาของปุ่ม จากนั้นฉันก็จัดข้อความ
ให้อยู่ตรงกลาง และจัดองค์ประกอบย่อยในแนวตั้งและแนวนอนให้อยู่ตรงกลาง ซึ่งจะช่วยให้ไอคอนและองค์ประกอบปุ่มอื่นๆ
จัดแนวได้อย่างถูกต้อง
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
display: inline-flex;
justify-content: center;
align-items: center;
text-align: center;
}

การเว้นวรรค
สำหรับระยะห่างของปุ่ม ฉันใช้
gap เพื่อไม่ให้องค์ประกอบที่อยู่ติดกัน
สัมผัสกัน และใช้พร็อพเพอร์ตี้เชิงตรรกะสำหรับระยะห่างจากขอบเพื่อให้ระยะห่างของปุ่ม
ทำงานได้กับเลย์เอาต์ข้อความทั้งหมด
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
gap: 1ch;
padding-block: var(--_padding-block);
padding-inline: var(--_padding-inline);
}

ประสบการณ์การใช้งานแบบสัมผัสและเมาส์
ส่วนถัดไปนี้มีไว้สำหรับผู้ใช้ที่ใช้อุปกรณ์เคลื่อนที่แบบสัมผัสเป็นหลัก พร็อพเพอร์ตี้แรก
user-select
มีไว้สำหรับผู้ใช้ทุกคน โดยจะป้องกันไม่ให้ข้อความไฮไลต์ข้อความปุ่ม โดยส่วนใหญ่จะสังเกตเห็นได้ในอุปกรณ์ระบบสัมผัสเมื่อแตะปุ่มค้างไว้และระบบปฏิบัติการไฮไลต์ข้อความของปุ่ม
โดยทั่วไปแล้ว ฉันพบว่าปุ่มในแอปที่มาพร้อมเครื่องไม่ได้มีประสบการณ์ของผู้ใช้เช่นนี้ จึงปิดใช้งานโดยตั้งค่า user-select เป็น none แตะสีไฮไลต์
(-webkit-tap-highlight-color)
และเมนูตามบริบทของระบบปฏิบัติการ
(-webkit-touch-callout)
เป็นฟีเจอร์ปุ่มอื่นๆ ที่เน้นเว็บเป็นอย่างมากและไม่สอดคล้องกับความคาดหวังของผู้ใช้ปุ่มทั่วไป จึงนำออกด้วย
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
user-select: none;
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
}
ทรานซิชัน
ระบบจะกําหนดตัวแปร --_transition แบบปรับได้ให้กับพร็อพเพอร์ตี้
การเปลี่ยนผ่าน
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
transition: var(--_transition);
}
เมื่อวางเมาส์เหนือปุ่มในขณะที่ผู้ใช้ไม่ได้กดปุ่มอยู่ ให้ปรับขนาดไฮไลต์เงา เพื่อให้ปุ่มดูดีและโฟกัสได้ชัดเจนขึ้น โดยให้ดูเหมือนว่าปุ่ม ขยายออกมาจากภายใน
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
):where(:not(:active):hover) {
--_highlight-size: .5rem;
}
เมื่อโฟกัส ให้เพิ่มออฟเซ็ตเส้นขอบโฟกัสจากปุ่ม และทำให้ปุ่มมี ลักษณะโฟกัสที่ดูดีซึ่งดูเหมือนจะขยายจากภายในปุ่ม
:where(button, input):where(:not(:active)):focus-visible {
outline-offset: 5px;
}
ไอคอน
สำหรับไอคอน ตัวเลือกจะมีตัวเลือก :where() เพิ่มเติมสำหรับ SVG
ลูกโดยตรงหรือองค์ประกอบที่มีแอตทริบิวต์ที่กำหนดเอง data-icon กำหนดขนาดไอคอน
ด้วยพร็อพเพอร์ตี้ที่กำหนดเองโดยใช้พร็อพเพอร์ตี้เชิงตรรกะแบบอินไลน์และแบบบล็อก ตั้งค่าสีเส้นขอบ
รวมถึงdrop-shadow
ให้ตรงกับ text-shadow flex-shrink ถูกตั้งค่าเป็น 0 เพื่อไม่ให้ไอคอน
ถูกบีบ สุดท้าย ฉันเลือกไอคอนแบบเส้นและกำหนดสไตล์เหล่านั้นที่นี่ด้วย
fill: none และ round เส้นปิดและเส้นเชื่อม
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
) > :where(svg, [data-icon]) {
block-size: var(--_icon-size);
inline-size: var(--_icon-size);
stroke: var(--_icon-color);
filter: drop-shadow(var(--_ink-shadow));
flex-shrink: 0;
fill: none;
stroke-linecap: round;
stroke-linejoin: round;
}

การปรับแต่งปุ่มส่ง
ฉันต้องการให้ปุ่มส่งมีลักษณะที่ได้รับการโปรโมตเล็กน้อย และทำได้โดยการกำหนดให้สีข้อความของปุ่มเป็นสีเน้น
:where(
[type="submit"],
form button:not([type],[disabled])
) {
--_text: var(--_accent);
}

ปรับแต่งปุ่มรีเซ็ต
ฉันต้องการให้ปุ่มรีเซ็ตมีสัญญาณเตือนในตัวเพื่อแจ้งให้ผู้ใช้ทราบถึง พฤติกรรมที่อาจสร้างความเสียหาย นอกจากนี้ ฉันยังเลือกจัดรูปแบบปุ่มธีมสว่าง ให้มีสีแดงมากกว่าธีมมืดด้วย การปรับแต่งทำได้โดย เปลี่ยนสีพื้นหลังที่เหมาะสม ไม่ว่าจะเป็นสีอ่อนหรือสีเข้ม และปุ่มจะ อัปเดตสไตล์
:where([type="reset"]) {
--_border-light: hsl(0 100% 83%);
--_highlight-light: hsl(0 100% 89% / 20%);
--_text-light: hsl(0 80% 50%);
--_text-dark: hsl(0 100% 89%);
}
นอกจากนี้ ฉันยังคิดว่าสีของเส้นขอบโฟกัสควรตรงกับสีเน้นที่เป็นสีแดง สีข้อความจะปรับจากสีแดงเข้มเป็นสีแดงอ่อน ฉันกำหนดให้สีของเส้นขอบ
ตรงกับคีย์เวิร์ดนี้
currentColor:
:where([type="reset"]):focus-visible {
outline-color: currentColor;
}

ปรับแต่งปุ่มที่ปิดใช้
ปุ่มที่ปิดใช้มักมีคอนทราสต์ของสีไม่ดีในระหว่าง ความพยายามที่จะลดความสว่างของปุ่มที่ปิดใช้เพื่อให้ดูเหมือนว่าไม่ได้ใช้งาน ฉันทดสอบชุดสีแต่ละชุดและตรวจสอบว่าผ่าน โดยปรับค่าความสว่างของ HSL จนกว่าคะแนนจะผ่านใน DevTools หรือ VisBug
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
)[disabled] {
--_bg: none;
--_text-light: hsl(210 7% 40%);
--_text-dark: hsl(210 11% 71%);
cursor: not-allowed;
box-shadow: var(--_shadow-1);
}

การปรับแต่งปุ่มป้อนข้อมูลไฟล์
ปุ่มป้อนข้อมูลไฟล์เป็นคอนเทนเนอร์สำหรับองค์ประกอบช่วงและปุ่ม CSS สามารถจัดรูปแบบคอนเทนเนอร์อินพุตเล็กน้อย รวมถึงปุ่มที่ซ้อนกัน แต่ไม่สามารถจัดรูปแบบองค์ประกอบ span คอนเทนเนอร์จะได้รับ max-inline-size เพื่อไม่ให้มีขนาดใหญ่กว่าที่จำเป็น ขณะที่ inline-size: 100% จะช่วยให้คอนเทนเนอร์หดตัวและพอดีกับคอนเทนเนอร์ที่มีขนาดเล็กกว่าได้ ส่วนสีพื้นหลังจะตั้งค่าเป็นสีที่ปรับเปลี่ยนได้ซึ่งเข้มกว่าพื้นผิวอื่นๆ เพื่อให้ดูอยู่ด้านหลังปุ่มตัวเลือกไฟล์
:where(input[type="file"]) {
inline-size: 100%;
max-inline-size: max-content;
background-color: var(--_input-well);
}
ปุ่มตัวเลือกไฟล์และปุ่มประเภทอินพุตได้รับการกำหนดค่ามาโดยเฉพาะ
appearance: noneเพื่อนำสไตล์ที่เบราว์เซอร์ระบุไว้ออก
ซึ่งไม่ได้ถูกเขียนทับด้วยสไตล์ปุ่มอื่นๆ
:where(input[type="button"]),
:where(input[type="file"])::file-selector-button {
appearance: none;
}
สุดท้ายนี้ เราจะเพิ่มระยะขอบให้กับ inline-end ของปุ่มเพื่อดันข้อความในองค์ประกอบ span
ออกจากปุ่มเพื่อสร้างพื้นที่ว่าง
:where(input[type="file"])::file-selector-button {
margin-inline-end: var(--_padding-inline);
}

ข้อยกเว้นพิเศษสำหรับธีมมืด
ฉันให้ปุ่มการทำงานหลักมีพื้นหลังสีเข้มขึ้นเพื่อให้ข้อความมีคอนทราสต์สูงขึ้น และทำให้ปุ่มดูโดดเด่นขึ้นเล็กน้อย
@media (prefers-color-scheme: dark) {
:where(
[type="submit"],
[type="reset"],
[disabled],
form button:not([type="button"])
) {
--_bg: var(--_input-well);
}
}

การสร้างตัวแปร
ฉันเลือกที่จะแสดงวิธีสร้างตัวแปร 2-3 รายการเพื่อความสนุกและเนื่องจากเป็นวิธีที่ใช้งานได้จริง ตัวแปรหนึ่งมีสีสดใสมาก คล้ายกับลักษณะที่ปุ่มหลักมักจะ ปรากฏ อีกรูปแบบหนึ่งคือขนาดใหญ่ ส่วนตัวแปรสุดท้ายมีไอคอนที่เติมสีแบบไล่ระดับ
ปุ่มสดใส
เราเขียนทับพร็อพพื้นฐานด้วยสีน้ำเงินโดยตรงเพื่อให้ได้ปุ่มสไตล์นี้ แม้ว่าวิธีนี้จะรวดเร็วและง่ายดาย แต่จะนำพร็อพและรูปลักษณ์ที่ปรับเปลี่ยนได้ออก และจะดูเหมือนกันทั้งในธีมสว่างและธีมมืด
.btn-custom {
--_bg: linear-gradient(hsl(228 94% 67%), hsl(228 81% 59%));
--_border: hsl(228 89% 63%);
--_text: hsl(228 89% 100%);
--_ink-shadow: 0 1px 0 hsl(228 57% 50%);
--_highlight: hsl(228 94% 67% / 20%);
}

ปุ่มขนาดใหญ่
ปุ่มสไตล์นี้สร้างขึ้นได้โดยการแก้ไข--_sizeพร็อพเพอร์ตี้ที่กำหนดเอง
ระยะขอบและองค์ประกอบพื้นที่อื่นๆ จะสัมพันธ์กับขนาดนี้ โดยจะปรับขนาดตามสัดส่วนของขนาดใหม่
.btn-large {
--_size: 1.5rem;
}

ปุ่มไอคอน
เอฟเฟกต์ไอคอนนี้ไม่เกี่ยวข้องกับสไตล์ปุ่มของเรา แต่จะแสดงวิธีสร้างเอฟเฟกต์ด้วยพร็อพเพอร์ตี้ CSS เพียงไม่กี่รายการ และวิธีที่ปุ่มจัดการไอคอนที่ไม่ใช่ SVG แบบอินไลน์
[data-icon="cloud"] {
--icon-cloud: url("https://api.iconify.design/mdi:apple-icloud.svg") center / contain no-repeat;
-webkit-mask: var(--icon-cloud);
mask: var(--icon-cloud);
background: linear-gradient(to bottom, var(--_accent-dark), var(--_accent-light));
}
![]()
บทสรุป
ตอนนี้คุณรู้วิธีที่ฉันใช้แล้ว คุณจะทำอย่างไร 🙂
มาลองใช้แนวทางที่หลากหลายและเรียนรู้วิธีต่างๆ ในการสร้างสรรค์บนเว็บกัน
สร้างการสาธิต ทวีตลิงก์มาให้ฉัน แล้วฉันจะเพิ่มลิงก์นั้น ลงในส่วนรีมิกซ์ของชุมชนด้านล่าง
รีมิกซ์ของชุมชน
ยังไม่มีอะไรให้ดูที่นี่
แหล่งข้อมูล
- ซอร์สโค้ดใน Github