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

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

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

ปุ่มต่างๆ ใช้งานได้ผ่านแป้นพิมพ์และเมาส์ในธีมสว่างและธีมมืด

หากต้องการดูวิดีโอ โปรดดูโพสต์เวอร์ชัน YouTube ที่นี่

ภาพรวม

การรองรับเบราว์เซอร์

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

แหล่งที่มา

องค์ประกอบ <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>
 
<svgaria-hidden="true">...</svg>
  Icon Button
</button>
เครื่องมือสำหรับนักพัฒนาเว็บของ Chrome ที่แสดงแผนภูมิการช่วยเหลือพิเศษสำหรับปุ่ม ต้นไม้ไม่สนใจรูปภาพปุ่มเนื่องจากตั้งค่า aria-hidden เป็น &quot;จริง&quot;
เครื่องมือสำหรับนักพัฒนาเว็บของ Chrome ที่แสดงแผนภูมิการช่วยเหลือพิเศษสำหรับปุ่ม ต้นไม้จะไม่สนใจรูปภาพปุ่มเนื่องจากมีการตั้งค่า aria-hidden เป็น true

รูปแบบ

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

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

กลยุทธ์ด้านพร็อพเพอร์ตี้ที่กำหนดเองที่ใช้ในภารกิจ 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 เพื่อให้การคลิกไม่ต้องรอและสังเกตการดับเบิลคลิกที่อาจเกิดขึ้น ซึ่งจะช่วยให้คุณใช้งานปุ่มได้เร็วขึ้น

: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;
}

ปุ่มขนาดใหญ่จะแสดงข้างปุ่มที่กำหนดเอง โดยจะมีขนาดใหญ่กว่าประมาณ 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));
}

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

บทสรุป

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

มาเพิ่มความหลากหลายให้แนวทางของเราและเรียนรู้วิธีทั้งหมดในการสร้างเนื้อหาบนเว็บกัน

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

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

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

แหล่งข้อมูล