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

ภาพรวมพื้นฐานเกี่ยวกับวิธีสร้าง<button>คอมโพเนนต์ที่ปรับสีตามบริบท ตอบสนอง และเข้าถึงได้

ในโพสต์นี้ ฉันอยากจะแชร์ความคิดเห็นเกี่ยวกับวิธีสร้างองค์ประกอบ <button> ที่ปรับสีได้ ตอบสนอง และเข้าถึงได้ ลองใช้เดโมและดู แหล่งที่มา

ปุ่มจะโต้ตอบผ่านแป้นพิมพ์และเมาส์ในธีมสว่างและธีมมืด

หากต้องการดูวิดีโอ โปรดดูโพสต์นี้ใน YouTube

ภาพรวม

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

Source

องค์ประกอบ <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>
เครื่องมือสำหรับนักพัฒนาเว็บใน Chrome แสดงแผนผังการช่วยเหลือพิเศษสำหรับปุ่ม ทรีจะละเว้นรูปภาพปุ่มเนื่องจากมีการตั้งค่า aria-hidden เป็น true
เครื่องมือสำหรับนักพัฒนาเว็บใน Chrome แสดงโครงสร้างการช่วยเหลือพิเศษสำหรับปุ่ม ต้นไม้ไม่สนใจรูปภาพปุ่มเนื่องจากมีการตั้งค่า aria-hidden เป็น true

รูปแบบ

ในส่วนถัดไปนี้ ฉันจะสร้างระบบพร็อพเพอร์ตี้ที่กำหนดเองเพื่อจัดการ สไตล์ที่ปรับเปลี่ยนได้ของปุ่มก่อน พร็อพเพอร์ตี้ที่กำหนดเองเหล่านั้นช่วยให้ฉันเริ่ม เลือกองค์ประกอบและปรับแต่งลักษณะที่ปรากฏได้

กลยุทธ์พร็อพเพอร์ตี้ที่กําหนดเองแบบปรับได้

กลยุทธ์พร็อพเพอร์ตี้ที่กำหนดเองที่ใช้ใน 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;
}

ปุ่มขนาดใหญ่จะแสดงข้างปุ่มที่กำหนดเอง โดยมีขนาดใหญ่กว่าประมาณ 150 เท่า

ปุ่มไอคอน

เอฟเฟกต์ไอคอนนี้ไม่เกี่ยวข้องกับสไตล์ปุ่มของเรา แต่จะแสดงวิธีสร้างเอฟเฟกต์ด้วยพร็อพเพอร์ตี้ 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));
}

ปุ่มที่มีไอคอนจะแสดงในธีมสว่างและธีมมืด

บทสรุป

ตอนนี้คุณรู้วิธีที่ฉันใช้แล้ว คุณจะทำอย่างไร 🙂

มาลองใช้แนวทางที่หลากหลายและเรียนรู้วิธีต่างๆ ในการสร้างสรรค์บนเว็บกัน

สร้างการสาธิต ทวีตลิงก์มาให้ฉัน แล้วฉันจะเพิ่มลิงก์นั้น ลงในส่วนรีมิกซ์ของชุมชนด้านล่าง

รีมิกซ์ของชุมชน

ยังไม่มีอะไรให้ดูที่นี่

แหล่งข้อมูล