ภาพรวมพื้นฐานเกี่ยวกับวิธีสร้างคอมโพเนนต์ <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) {
…
}
วงแหวนโฟกัสแบบอินเทอร์แอกทีฟ
ฉันต้องการแสดงภาพเคลื่อนไหวของวงโฟกัสสำหรับผู้ใช้แป้นพิมพ์และเทคโนโลยีความช่วยเหลือพิเศษ เราทำสิ่งนี้ได้โดยทำให้ขอบขยับออกจากปุ่ม 5 พิกเซล แต่เฉพาะในกรณีที่ปุ่มไม่ได้ทำงาน วิธีนี้จะทำให้วงโฟกัสหดกลับเป็นขนาดปุ่มเมื่อกด
:where(button, input):where(:not(:active)):focus-visible {
outline-offset: 5px;
}
ตรวจสอบว่าผ่านเกณฑ์คอนทราสต์ของสี
มีชุดค่าผสมสีอย่างน้อย 4 ชุดในโหมดสว่างและโหมดมืดที่ต้องคำนึงถึงคอนทราสต์สี ได้แก่ ปุ่ม ปุ่มส่ง ปุ่มรีเซ็ต และปุ่มปิดใช้ VisBug ใช้ที่นี่เพื่อตรวจสอบและแสดงคะแนนทั้งหมดพร้อมกัน
การซ่อนไอคอนจากผู้ที่ไม่เห็น
เมื่อสร้างปุ่มไอคอน ไอคอนควรสนับสนุนข้อความปุ่มด้วยภาพ ซึ่งหมายความว่าไอคอนนี้ไม่มีคุณค่าสำหรับผู้ที่สูญเสียการมองเห็น แต่โชคดีที่เบราว์เซอร์มีวิธีซ่อนรายการจากเทคโนโลยีโปรแกรมอ่านหน้าจอเพื่อให้ผู้ที่สูญเสียการมองเห็นไม่ต้องกังวลกับรูปภาพปุ่มตกแต่ง
<button>
<svg … aria-hidden="true">...</svg>
Icon Button
</button>
รูปแบบ
ในส่วนถัดไปนี้ เราจะสร้างระบบพร็อพเพอร์ตี้ที่กำหนดเองเพื่อจัดการสไตล์แบบปรับเปลี่ยนได้ของปุ่ม เมื่อใช้พร็อพเพอร์ตี้ที่กำหนดเองเหล่านั้นแล้ว ฉันจะเริ่มเลือกองค์ประกอบและปรับแต่งลักษณะที่ปรากฏได้
กลยุทธ์พร็อพเพอร์ตี้ที่กำหนดเองแบบปรับเปลี่ยนได้
กลยุทธ์พร็อพเพอร์ตี้ที่กำหนดเองที่ใช้ในโจทย์ GUI นี้คล้ายกับกลยุทธ์ที่ใช้ในการสร้างชุดสี สำหรับระบบสีสว่างและสีเข้มแบบปรับอัตโนมัติ ระบบจะกำหนดและตั้งชื่อพร็อพเพอร์ตี้ที่กำหนดเองสำหรับแต่ละธีม จากนั้นระบบจะใช้พร็อพเพอร์ตี้ที่กำหนดเองรายการเดียวเพื่อเก็บค่าปัจจุบันของธีมและกำหนดให้กับพร็อพเพอร์ตี้ 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%));
นอกจากนี้ 1px
box-shadow
ยังสร้างภาพลวงตาให้ปุ่มดูเป็น 3 มิติเล็กน้อย
--_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);
}
}
รูปแบบที่ใช้ร่วมกัน 2-3 รูปแบบ
ปุ่มและอินพุตต้องตั้งค่าแบบอักษรเป็น 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
เพื่อให้การคลิกไม่ต้องรอและสังเกตการคลิก 2 ครั้ง ซึ่งทำให้ปุ่มทำงานได้เร็วขึ้น
: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);
}
UX ของการสัมผัสและเมาส์
ส่วนถัดไปนี้ส่วนใหญ่สําหรับผู้ใช้ที่สัมผัสบนอุปกรณ์เคลื่อนที่ พร็อพเพอร์ตี้แรก user-select
มีไว้สําหรับผู้ใช้ทุกคน ซึ่งจะป้องกันไม่ให้ข้อความไฮไลต์ข้อความบนปุ่ม ปัญหานี้ส่วนใหญ่จะสังเกตเห็นได้ในอุปกรณ์แบบสัมผัสเมื่อมีการแตะปุ่มค้างไว้และระบบปฏิบัติการไฮไลต์ข้อความของปุ่ม
โดยทั่วไปแล้ว เราพบว่านี่ไม่ใช่ประสบการณ์ของผู้ใช้ที่มีปุ่มในแอปในตัว จึงปิดใช้โดยตั้งค่า user-select
เป็น "ไม่มี" สีไฮไลต์ของปุ่มที่เลือก (-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
แบบปรับเปลี่ยนได้จะได้รับมอบหมายให้กับพร็อพเพอร์ตี้ 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 สามารถจัดรูปแบบคอนเทนเนอร์อินพุตได้เล็กน้อย รวมถึงปุ่มที่ฝังอยู่ แต่จัดรูปแบบสแปนได้ คอนเทนเนอร์จะได้รับ 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
ของปุ่มเพื่อดันข้อความส่วนนั้นออกจากปุ่มเพื่อสร้างพื้นที่ว่าง
: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