ภาพรวมพื้นฐานเกี่ยวกับวิธีสร้างมินิและเมกะโมดอลที่ปรับสีตามธีม ตอบสนอง และเข้าถึงได้ด้วยองค์ประกอบ <dialog>
ในโพสต์นี้ ฉันต้องการแชร์ความคิดเห็นเกี่ยวกับวิธีสร้างมินิและเมกะโมดอลที่ปรับสีได้
ตอบสนอง และเข้าถึงได้ด้วยองค์ประกอบ <dialog>
ลองใช้เดโมและดู
แหล่งที่มา
หากต้องการดูวิดีโอ โปรดดูโพสต์นี้ใน YouTube
ภาพรวม
องค์ประกอบ
<dialog>
เหมาะสําหรับข้อมูลตามบริบทหรือการกระทําในหน้าเว็บ พิจารณาว่าเมื่อใดที่ประสบการณ์ของผู้ใช้จะได้รับประโยชน์จากการดำเนินการในหน้าเดียวกันแทนที่จะเป็นการดำเนินการแบบหลายหน้า อาจเป็นเพราะแบบฟอร์มมีขนาดเล็กหรือการดำเนินการเดียวที่ผู้ใช้ต้องทำคือยืนยันหรือยกเลิก
องค์ประกอบ <dialog>
เพิ่งกลายเป็นองค์ประกอบที่เสถียรในเบราว์เซอร์ต่างๆ
ฉันพบว่าองค์ประกอบนี้ขาดหายไปบางอย่าง ดังนั้นในGUI Challenge นี้ ฉันจึงเพิ่มรายการประสบการณ์ของนักพัฒนาซอฟต์แวร์ ที่ฉันคาดหวัง ได้แก่ เหตุการณ์เพิ่มเติม การปิดอย่างรวดเร็ว ภาพเคลื่อนไหวที่กำหนดเอง และประเภทมินิ และเมกะ
Markup
องค์ประกอบสำคัญของ<dialog>
มีดังนี้ ระบบจะซ่อนองค์ประกอบโดยอัตโนมัติและมีสไตล์ในตัวเพื่อวางซ้อนเนื้อหา
<dialog>
…
</dialog>
เราสามารถปรับปรุงเกณฑ์พื้นฐานนี้ได้
โดยปกติแล้ว องค์ประกอบกล่องโต้ตอบจะมีความคล้ายคลึงกับโมดอลเป็นอย่างมาก และมักจะใช้ชื่อแทนกันได้
ฉันใช้กล่องโต้ตอบทั้งสำหรับป๊อปอัปกล่องโต้ตอบขนาดเล็ก (มินิ) และกล่องโต้ตอบแบบเต็มหน้า (เมกะ) ฉันตั้งชื่อว่าเมกะและมินิ โดยปรับแต่งทั้ง 2 ไดอะล็อกเล็กน้อยให้เหมาะกับกรณีการใช้งานที่แตกต่างกัน
ฉันได้เพิ่มแอตทริบิวต์ modal-mode
เพื่อให้คุณระบุประเภทได้
<dialog id="MegaDialog" modal-mode="mega"></dialog>
<dialog id="MiniDialog" modal-mode="mini"></dialog>
โดยทั่วไปแล้ว ระบบจะใช้องค์ประกอบกล่องโต้ตอบเพื่อรวบรวมข้อมูลการโต้ตอบบางอย่าง แบบฟอร์มภายในองค์ประกอบกล่องโต้ตอบจะทำงานร่วมกัน
คุณควรให้องค์ประกอบของแบบฟอร์มห่อหุ้มเนื้อหากล่องโต้ตอบเพื่อให้ JavaScript เข้าถึงข้อมูลที่ผู้ใช้ป้อนได้ นอกจากนี้ ปุ่มภายใน
แบบฟอร์มที่ใช้ method="dialog"
ยังปิดกล่องโต้ตอบได้โดยไม่ต้องใช้ JavaScript และส่ง
ข้อมูล
<dialog id="MegaDialog" modal-mode="mega">
<form method="dialog">
…
<button value="cancel">Cancel</button>
<button value="confirm">Confirm</button>
</form>
</dialog>
กล่องโต้ตอบ Mega
กล่องโต้ตอบขนาดใหญ่มีองค์ประกอบ 3 อย่างภายในแบบฟอร์ม ได้แก่
<header>
<article>
และ
<footer>
ซึ่งทำหน้าที่เป็นคอนเทนเนอร์เชิงความหมาย รวมถึงเป็นเป้าหมายสไตล์สำหรับการ
นำเสนอของกล่องโต้ตอบ ส่วนหัวจะตั้งชื่อโมดอลและมีปุ่มปิด
บทความนี้มีไว้สำหรับข้อมูลและการป้อนข้อมูลในแบบฟอร์ม ส่วนท้ายมี<menu>
ของ
ปุ่มการทำงาน
<dialog id="MegaDialog" modal-mode="mega">
<form method="dialog">
<header>
<h3>Dialog title</h3>
<button onclick="this.closest('dialog').close('close')"></button>
</header>
<article>...</article>
<footer>
<menu>
<button autofocus type="reset" onclick="this.closest('dialog').close('cancel')">Cancel</button>
<button type="submit" value="confirm">Confirm</button>
</menu>
</footer>
</form>
</dialog>
ปุ่มเมนูแรกมี
autofocus
และตัวแฮนเดิลเหตุการณ์ในบรรทัด onclick
แอตทริบิวต์ autofocus
จะได้รับโฟกัสเมื่อเปิดกล่องโต้ตอบ และฉันคิดว่าแนวทางปฏิบัติแนะนำคือการวางแอตทริบิวต์นี้ไว้ที่ปุ่มยกเลิก ไม่ใช่ปุ่มยืนยัน วิธีนี้ช่วยให้มั่นใจได้ว่าการยืนยันเป็นไปโดย
ตั้งใจและไม่ได้เกิดจากความผิดพลาด
กล่องโต้ตอบขนาดเล็ก
มินิไดอะล็อกคล้ายกับเมกะไดอะล็อกมาก เพียงแต่ไม่มีองค์ประกอบ
<header>
ซึ่งช่วยให้มีขนาดเล็กลงและอยู่ในบรรทัดเดียวกันมากขึ้น
<dialog id="MiniDialog" modal-mode="mini">
<form method="dialog">
<article>
<p>Are you sure you want to remove this user?</p>
</article>
<footer>
<menu>
<button autofocus type="reset" onclick="this.closest('dialog').close('cancel')">Cancel</button>
<button type="submit" value="confirm">Confirm</button>
</menu>
</footer>
</form>
</dialog>
องค์ประกอบกล่องโต้ตอบเป็นรากฐานที่แข็งแกร่งสำหรับองค์ประกอบวิวพอร์ตแบบเต็มที่ สามารถรวบรวมข้อมูลและการโต้ตอบของผู้ใช้ได้ ซึ่งจะช่วยให้เกิดการโต้ตอบที่น่าสนใจและมีประสิทธิภาพในเว็บไซต์หรือแอป
การช่วยเหลือพิเศษ
องค์ประกอบกล่องโต้ตอบมีการช่วยเหลือพิเศษในตัวที่ดีมาก ฟีเจอร์เหล่านี้ มีอยู่แล้วโดยที่คุณไม่ต้องเพิ่มเหมือนที่เคย
การคืนค่าโฟกัส
เช่นเดียวกับที่เราทำด้วยตนเองในการสร้างคอมโพเนนต์แถบนำทางด้านข้าง สิ่งสำคัญคือการเปิดและปิดสิ่งต่างๆ อย่างถูกต้องจะทำให้โฟกัสไปที่ปุ่มเปิดและปิดที่เกี่ยวข้อง เมื่อเปิดแถบนำทางด้านข้าง ระบบจะโฟกัสที่ปุ่มปิด เมื่อกด ปุ่มปิด ระบบจะคืนค่าโฟกัสไปยังปุ่มที่เปิดไว้
เมื่อใช้องค์ประกอบกล่องโต้ตอบ ลักษณะการทำงานเริ่มต้นในตัวจะเป็นดังนี้
น่าเสียดายที่หากต้องการทำให้กล่องโต้ตอบเคลื่อนไหวเข้าและออก ฟังก์ชันนี้ จะหายไป ในส่วน JavaScript เราจะกู้คืนฟังก์ชันนั้น
การดักโฟกัส
องค์ประกอบกล่องโต้ตอบจะจัดการ
inert
ให้คุณในเอกสาร ก่อน inert
มีการใช้ JavaScript เพื่อดูว่าโฟกัส
ออกจากองค์ประกอบหรือไม่ ซึ่งในจุดนี้ JavaScript จะสกัดกั้นและนำโฟกัสกลับไป
หลังจากinert
แล้ว คุณจะ "ตรึง" ส่วนใดก็ได้ของเอกสารเพื่อไม่ให้เป็นเป้าหมายโฟกัสหรือโต้ตอบด้วยเมาส์ได้อีก แทนที่จะดักจับ
โฟกัส ระบบจะนำโฟกัสไปยังส่วนแบบอินเทอร์แอกทีฟเพียงส่วนเดียวของเอกสาร
เปิดและโฟกัสอัตโนมัติที่องค์ประกอบ
โดยค่าเริ่มต้น องค์ประกอบกล่องโต้ตอบจะกำหนดโฟกัสให้กับองค์ประกอบแรกที่โฟกัสได้
ในการมาร์กอัปกล่องโต้ตอบ หากไม่ใช่ช่องที่ผู้ใช้ควรใช้เป็นค่าเริ่มต้น
ให้ใช้แอตทริบิวต์ autofocus
ดังที่ได้อธิบายไว้ก่อนหน้านี้ เราพบว่าแนวทางปฏิบัติแนะนำ
คือการใส่ข้อความนี้ไว้ในปุ่มยกเลิก ไม่ใช่ปุ่มยืนยัน วิธีนี้ช่วยให้มั่นใจได้ว่า
การยืนยันนั้นตั้งใจทำและไม่ได้เกิดจากความผิดพลาด
ปิดด้วยปุ่ม Escape
คุณควรทำให้ปิดองค์ประกอบที่อาจขัดจังหวะนี้ได้ง่าย โชคดีที่องค์ประกอบกล่องโต้ตอบจะจัดการปุ่ม Escape ให้คุณ ซึ่งช่วยให้คุณไม่ต้องกังวลเรื่องการประสานงาน
รูปแบบ
มีเส้นทางที่ง่ายและยากในการจัดรูปแบบองค์ประกอบกล่องโต้ตอบ เราใช้วิธีง่ายๆ
โดยไม่เปลี่ยนพร็อพเพอร์ตี้การแสดงผลของกล่องโต้ตอบและทำงาน
ภายใต้ข้อจำกัดของกล่องโต้ตอบ ฉันจึงเลือกเส้นทางที่ยากเพื่อสร้างภาพเคลื่อนไหวที่กำหนดเองสำหรับ
การเปิดและปิดกล่องโต้ตอบ การครอบครองพร็อพเพอร์ตี้ display
และอื่นๆ
การจัดรูปแบบด้วย Open Props
เพื่อเร่งการใช้สีที่ปรับเปลี่ยนได้และความสอดคล้องของการออกแบบโดยรวม ฉันจึงได้นำคลังตัวแปร CSS Open Props มาใช้ นอกเหนือจากตัวแปรที่ให้มาฟรีแล้ว ฉันยังนำเข้าไฟล์ normalize และปุ่มบางปุ่มด้วย ซึ่งทั้ง 2 อย่างนี้ Open Props มีให้เป็นตัวเลือกในการนำเข้า การนำเข้าเหล่านี้ช่วยให้ฉันมุ่งเน้นไปที่การปรับแต่งกล่องโต้ตอบและการสาธิตโดยไม่ต้องใช้สไตล์มากมายเพื่อรองรับและทำให้ดูดี
การจัดรูปแบบองค์ประกอบ <dialog>
การเป็นเจ้าของพร็อพเพอร์ตี้ Display
ลักษณะการทำงานเริ่มต้นในการแสดงและซ่อนองค์ประกอบกล่องโต้ตอบจะสลับพร็อพเพอร์ตี้การแสดงผล
จาก block
เป็น none
ซึ่งหมายความว่าคุณจะเคลื่อนไหวเข้าออกไม่ได้ ทำได้เพียงเคลื่อนไหวเข้าเท่านั้น ฉันต้องการสร้างภาพเคลื่อนไหวทั้งเข้าและออก ขั้นตอนแรกคือ
การตั้งค่าพร็อพเพอร์ตี้display ของฉันเอง
dialog {
display: grid;
}
การเปลี่ยนค่าพร็อพเพอร์ตี้การแสดงผลและเป็นเจ้าของค่าดังกล่าวตามที่แสดงใน ข้อมูลโค้ด CSS ด้านบน จะต้องมีการจัดการสไตล์จำนวนมากเพื่อ อำนวยความสะดวกให้ผู้ใช้ได้รับประสบการณ์ที่เหมาะสม ก่อนอื่น สถานะเริ่มต้นของกล่องโต้ตอบคือ ปิด คุณสามารถแสดงสถานะนี้ด้วยภาพและป้องกันไม่ให้กล่องโต้ตอบรับการโต้ตอบด้วยรูปแบบต่อไปนี้
dialog:not([open]) {
pointer-events: none;
opacity: 0;
}
ตอนนี้กล่องโต้ตอบจะมองไม่เห็นและโต้ตอบด้วยไม่ได้เมื่อไม่ได้เปิดอยู่ ต่อมา
ฉันจะเพิ่ม JavaScript บางส่วนเพื่อจัดการแอตทริบิวต์ inert
ในกล่องโต้ตอบ เพื่อให้มั่นใจว่า
ผู้ใช้แป้นพิมพ์และโปรแกรมอ่านหน้าจอก็เข้าถึงกล่องโต้ตอบที่ซ่อนอยู่ไม่ได้เช่นกัน
การกำหนดธีมสีที่ปรับเปลี่ยนได้ให้กับกล่องโต้ตอบ
แม้ว่า color-scheme
จะเลือกใช้ธีมสีที่ปรับเปลี่ยนได้ซึ่งเบราว์เซอร์มีให้ในเอกสารของคุณตามค่ากำหนดของระบบสำหรับธีมสว่างและมืด แต่ฉันต้องการปรับแต่งองค์ประกอบกล่องโต้ตอบให้มากกว่านั้น Open Props มีสีพื้นผิว 2-3 สีที่ปรับให้เข้ากับค่ากำหนดของระบบธีมสว่างและธีมมืดโดยอัตโนมัติ คล้ายกับการใช้ color-scheme
ซึ่งเหมาะอย่างยิ่งสำหรับการสร้างเลเยอร์ในการออกแบบ และฉันชอบใช้สีเพื่อช่วย
สนับสนุนลักษณะที่ปรากฏของพื้นผิวเลเยอร์นี้ด้วยภาพ สีพื้นหลังคือ
var(--surface-1)
หากต้องการวางบนเลเยอร์นั้น ให้ใช้ var(--surface-2)
dialog {
…
background: var(--surface-2);
color: var(--text-1);
}
@media (prefers-color-scheme: dark) {
dialog {
border-block-start: var(--border-size-1) solid var(--surface-3);
}
}
เราจะเพิ่มสีที่ปรับเปลี่ยนได้มากขึ้นในภายหลังสำหรับองค์ประกอบย่อย เช่น ส่วนหัว และส่วนท้าย ฉันถือว่าไอคอนเหล่านี้เป็นส่วนเสริมสำหรับองค์ประกอบของกล่องโต้ตอบ แต่มีความสำคัญอย่างยิ่งในการ สร้างการออกแบบกล่องโต้ตอบที่น่าสนใจและออกแบบมาอย่างดี
การกำหนดขนาดกล่องโต้ตอบที่ปรับเปลี่ยนตามอุปกรณ์
กล่องโต้ตอบจะกำหนดขนาดตามเนื้อหาโดยค่าเริ่มต้น ซึ่งโดยทั่วไปแล้วถือเป็นเรื่องดี
เป้าหมายของฉันคือการจำกัด
max-inline-size
ให้มีขนาดที่อ่านได้ (--size-content-3
= 60ch
) หรือ 90% ของความกว้างของวิวพอร์ต ซึ่งจะช่วยให้มั่นใจได้ว่ากล่องโต้ตอบจะไม่ขยายจนสุดขอบในอุปกรณ์เคลื่อนที่ และจะไม่กว้างจนเกินไปในหน้าจอเดสก์ท็อปจนอ่านได้ยาก จากนั้นฉันก็เพิ่ม
max-block-size
เพื่อให้กล่องโต้ตอบไม่เกินความสูงของหน้า นอกจากนี้ เรายังต้องระบุตำแหน่งของพื้นที่ที่เลื่อนได้ของกล่องโต้ตอบด้วย ในกรณีที่เป็นองค์ประกอบกล่องโต้ตอบที่สูง
dialog {
…
max-inline-size: min(90vw, var(--size-content-3));
max-block-size: min(80vh, 100%);
max-block-size: min(80dvb, 100%);
overflow: hidden;
}
สังเกตไหมว่าฉันมี max-block-size
2 ครั้ง โดยตัวแรกใช้ 80vh
ซึ่งเป็นหน่วย
พอร์ตแสดงผลจริง สิ่งที่ฉันต้องการจริงๆ คือการเก็บกล่องโต้ตอบไว้ภายในโฟลว์ที่เกี่ยวข้อง
สำหรับผู้ใช้ในต่างประเทศ ฉันจึงใช้หน่วย dvb
ที่สมเหตุสมผล ใหม่กว่า และรองรับเพียงบางส่วน
ในการประกาศครั้งที่ 2 เมื่อหน่วยดังกล่าวมีความเสถียรมากขึ้น
การวางตำแหน่งกล่องโต้ตอบขนาดใหญ่
หากต้องการช่วยในการจัดวางองค์ประกอบของกล่องโต้ตอบ คุณควรแบ่งออกเป็น 2 ส่วน ได้แก่ ฉากหลังแบบเต็มหน้าจอและคอนเทนเนอร์กล่องโต้ตอบ ฉากหลังต้องครอบคลุมทุกอย่าง โดยมีเอฟเฟกต์เฉดสีเพื่อช่วยยืนยันว่ากล่องโต้ตอบนี้อยู่ด้านหน้าและเนื้อหาด้านหลังไม่สามารถเข้าถึงได้ คอนเทนเนอร์กล่องโต้ตอบสามารถจัดกึ่งกลางเหนือฉากหลังนี้และใช้รูปร่างใดก็ได้ตามที่เนื้อหาต้องการ
รูปแบบต่อไปนี้จะแก้ไของค์ประกอบกล่องโต้ตอบในหน้าต่าง ยืดองค์ประกอบไปยังแต่ละมุม และใช้ margin: auto
เพื่อจัดกึ่งกลางเนื้อหา
dialog {
…
margin: auto;
padding: 0;
position: fixed;
inset: 0;
z-index: var(--layer-important);
}
รูปแบบกล่องโต้ตอบขนาดใหญ่บนอุปกรณ์เคลื่อนที่
ใน Viewport ขนาดเล็ก ฉันจะจัดรูปแบบเมกะโมดอลแบบเต็มหน้าเว็บนี้แตกต่างออกไปเล็กน้อย ฉัน
ตั้งค่าระยะขอบด้านล่างเป็น 0
ซึ่งจะนำเนื้อหาของกล่องโต้ตอบไปไว้ที่ด้านล่างของ
วิวพอร์ต การปรับสไตล์เพียงเล็กน้อยก็ช่วยให้ฉันเปลี่ยนกล่องโต้ตอบเป็น
แผ่นการดำเนินการที่อยู่ใกล้กับนิ้วหัวแม่มือของผู้ใช้มากขึ้นได้
@media (max-width: 768px) {
dialog[modal-mode="mega"] {
margin-block-end: 0;
border-end-end-radius: 0;
border-end-start-radius: 0;
}
}
การวางตำแหน่งกล่องโต้ตอบขนาดเล็ก
เมื่อใช้ Viewport ที่ใหญ่ขึ้น เช่น ในคอมพิวเตอร์เดสก์ท็อป ฉันเลือกที่จะวางกล่องโต้ตอบขนาดเล็กไว้เหนือ องค์ประกอบที่เรียกกล่องโต้ตอบนั้น ฉันต้องใช้ JavaScript เพื่อทำสิ่งนี้ คุณดูเทคนิคที่ฉันใช้ได้ที่นี่ แต่ฉันคิดว่าเทคนิคนี้อยู่นอกขอบเขตของบทความนี้ หากไม่มี JavaScript กล่องโต้ตอบขนาดเล็กจะปรากฏตรงกลางหน้าจอเหมือนกับกล่องโต้ตอบขนาดใหญ่
ทำให้โดดเด่น
สุดท้าย เพิ่มลูกเล่นให้กับกล่องโต้ตอบเพื่อให้ดูเหมือนพื้นผิวที่นุ่มซึ่งอยู่สูงเหนือหน้าเว็บ ความนุ่มนวลเกิดจากการปัดมุมของกล่องโต้ตอบ ความลึกเกิดจากพร็อพ shadow ที่สร้างขึ้นอย่างพิถีพิถันของ Open Props
dialog {
…
border-radius: var(--radius-3);
box-shadow: var(--shadow-6);
}
การปรับแต่งองค์ประกอบเสมือนของฉากหลัง
ฉันเลือกที่จะทำงานกับฉากหลังอย่างเบาๆ โดยเพิ่มเอฟเฟกต์เบลอด้วย
backdrop-filter
ลงในกล่องโต้ตอบขนาดใหญ่เท่านั้น
dialog[modal-mode="mega"]::backdrop {
backdrop-filter: blur(25px);
}
นอกจากนี้ ฉันยังเลือกใส่ทรานซิชันใน backdrop-filter
โดยหวังว่าเบราว์เซอร์
จะอนุญาตให้เปลี่ยนองค์ประกอบฉากหลังในอนาคต
dialog::backdrop {
transition: backdrop-filter .5s ease;
}
ส่วนเสริมการจัดรูปแบบ
ฉันเรียกส่วนนี้ว่า "ส่วนเสริม" เพราะเกี่ยวข้องกับองค์ประกอบกล่องโต้ตอบ สาธิตมากกว่าองค์ประกอบกล่องโต้ตอบทั่วไป
การจำกัดขอบเขตการเลื่อน
เมื่อกล่องโต้ตอบแสดงขึ้น ผู้ใช้จะยังเลื่อนหน้าเว็บที่อยู่ด้านหลังได้ ซึ่งฉันไม่ต้องการ
โดยปกติแล้ว
overscroll-behavior
จะเป็นวิธีแก้ปัญหาที่ฉันใช้เป็นประจำ แต่ตาม
ข้อกำหนด
แล้ว คำสั่งนี้จะไม่มีผลกับกล่องโต้ตอบเนื่องจากไม่ใช่พอร์ตเลื่อน กล่าวคือ ไม่ใช่
ตัวเลื่อนจึงไม่มีอะไรที่ต้องป้องกัน ฉันสามารถใช้ JavaScript เพื่อดู
เหตุการณ์ใหม่จากคำแนะนำนี้ เช่น "ปิด" และ "เปิด" และสลับ
overflow: hidden
ในเอกสาร หรือจะรอให้ :has()
เสถียรใน
เบราว์เซอร์ทั้งหมดก็ได้
html:has(dialog[open][modal-mode="mega"]) {
overflow: hidden;
}
ตอนนี้เมื่อเปิดกล่องโต้ตอบขนาดใหญ่ เอกสาร HTML จะมี overflow: hidden
เลย์เอาต์ <form>
นอกเหนือจากการเป็นองค์ประกอบที่สำคัญมากสำหรับการรวบรวมข้อมูลการโต้ตอบจากผู้ใช้แล้ว ฉันยังใช้ที่นี่เพื่อจัดวางองค์ประกอบส่วนหัว ส่วนท้าย และบทความด้วย เลย์เอาต์นี้มีจุดประสงค์เพื่อระบุองค์ประกอบย่อยของบทความเป็นพื้นที่ที่เลื่อนได้ ฉันทำสิ่งนี้ด้วย
grid-template-rows
องค์ประกอบบทความมี 1fr
และแบบฟอร์มมีค่าความสูงสูงสุดเท่ากับองค์ประกอบกล่องโต้ตอบ
การตั้งค่าความสูงคงที่และขนาดแถวคงที่คือสิ่งที่
ช่วยให้องค์ประกอบบทความถูกจำกัดและเลื่อนได้เมื่อมีเนื้อหาล้น
dialog > form {
display: grid;
grid-template-rows: auto 1fr auto;
align-items: start;
max-block-size: 80vh;
max-block-size: 80dvb;
}
การจัดรูปแบบกล่องโต้ตอบ <header>
บทบาทขององค์ประกอบนี้คือการระบุชื่อสำหรับเนื้อหาในกล่องโต้ตอบและแสดงปุ่มปิดที่ค้นหาได้ง่าย นอกจากนี้ ยังมีการกำหนดสีพื้นผิวเพื่อให้ดูเหมือนอยู่ด้านหลังเนื้อหาบทความในกล่องโต้ตอบ ข้อกำหนดเหล่านี้ทำให้เกิดคอนเทนเนอร์ Flexbox รายการที่จัดแนวตั้งซึ่งเว้นระยะห่างจนถึงขอบ และการ เว้นที่ว่างและช่องว่างบางส่วนเพื่อให้ปุ่มชื่อและปุ่มปิดมีพื้นที่:
dialog > form > header {
display: flex;
gap: var(--size-3);
justify-content: space-between;
align-items: flex-start;
background: var(--surface-2);
padding-block: var(--size-3);
padding-inline: var(--size-5);
}
@media (prefers-color-scheme: dark) {
dialog > form > header {
background: var(--surface-1);
}
}
การจัดรูปแบบปุ่มปิดส่วนหัว
เนื่องจากเดโมใช้ปุ่ม Open Props ปุ่มปิดจึงได้รับการปรับแต่ง ให้เป็นปุ่มไอคอนกลมตรงกลาง ดังนี้
dialog > form > header > button {
border-radius: var(--radius-round);
padding: .75ch;
aspect-ratio: 1;
flex-shrink: 0;
place-items: center;
stroke: currentColor;
stroke-width: 3px;
}
การจัดรูปแบบกล่องโต้ตอบ <article>
องค์ประกอบบทความมีบทบาทพิเศษในกล่องโต้ตอบนี้ ซึ่งเป็นพื้นที่ที่ตั้งใจให้ เลื่อนได้ในกรณีที่กล่องโต้ตอบสูงหรือยาว
ในการดำเนินการนี้ องค์ประกอบแบบฟอร์มระดับบนสุดได้กำหนดค่าสูงสุดบางอย่างสำหรับ
ตัวมันเอง ซึ่งเป็นข้อจำกัดสำหรับองค์ประกอบบทความนี้หากมีความสูงมากเกินไป
ตั้งค่า overflow-y: auto
เพื่อให้แถบเลื่อนแสดงเมื่อจำเป็นเท่านั้น
จำกัดการเลื่อนภายในด้วย overscroll-behavior: contain
และส่วนที่เหลือ
จะเป็นรูปแบบการนำเสนอที่กำหนดเอง
dialog > form > article {
overflow-y: auto;
max-block-size: 100%; /* safari */
overscroll-behavior-y: contain;
display: grid;
justify-items: flex-start;
gap: var(--size-3);
box-shadow: var(--shadow-2);
z-index: var(--layer-1);
padding-inline: var(--size-5);
padding-block: var(--size-3);
}
@media (prefers-color-scheme: light) {
dialog > form > article {
background: var(--surface-1);
}
}
การจัดรูปแบบกล่องโต้ตอบ <footer>
ส่วนท้ายมีหน้าที่แสดงเมนูของปุ่มการทำงาน Flexbox ใช้เพื่อ จัดเนื้อหาไปที่ส่วนท้ายของแกนในบรรทัดของส่วนท้าย จากนั้นเว้นระยะห่างเล็กน้อยเพื่อ ให้ปุ่มมีพื้นที่
dialog > form > footer {
background: var(--surface-2);
display: flex;
flex-wrap: wrap;
gap: var(--size-3);
justify-content: space-between;
align-items: flex-start;
padding-inline: var(--size-5);
padding-block: var(--size-3);
}
@media (prefers-color-scheme: dark) {
dialog > form > footer {
background: var(--surface-1);
}
}
การจัดรูปแบบเมนูส่วนท้ายของกล่องโต้ตอบ
องค์ประกอบ menu
ใช้เพื่อเก็บปุ่มดำเนินการสำหรับกล่องโต้ตอบ โดยใช้เลย์เอาต์ Flexbox แบบตัดคำ
พร้อม gap
เพื่อเว้นที่ว่างระหว่างปุ่ม องค์ประกอบเมนู
มีระยะห่าง เช่น <ul>
และฉันก็นำสไตล์นั้นออกด้วยเพราะไม่จำเป็นต้องใช้
dialog > form > footer > menu {
display: flex;
flex-wrap: wrap;
gap: var(--size-3);
padding-inline-start: 0;
}
dialog > form > footer > menu:only-child {
margin-inline-start: auto;
}
แอนิเมชัน
องค์ประกอบของกล่องโต้ตอบมักจะเคลื่อนไหวเนื่องจากเข้าและออกจากหน้าต่าง การใส่ภาพเคลื่อนไหวที่ช่วยสนับสนุนกล่องโต้ตอบสำหรับการเข้าและออกจะช่วยให้ผู้ใช้ ทราบตำแหน่งของตนเองในโฟลว์
โดยปกติแล้ว องค์ประกอบกล่องโต้ตอบจะเคลื่อนไหวเข้าได้เท่านั้น ไม่ใช่เคลื่อนไหวออก เนื่องจากเบราว์เซอร์สลับพร็อพเพอร์ตี้ display
ในองค์ประกอบ ก่อนหน้านี้ ไกด์
ตั้งค่าการแสดงผลเป็นตารางกริด และไม่เคยตั้งค่าเป็นไม่มี ซึ่งจะช่วยให้คุณ
เคลื่อนไหวเข้าและออกได้
Open Props มาพร้อมกับภาพเคลื่อนไหวคีย์เฟรมมากมายให้ใช้งาน ซึ่งช่วยให้ การจัดระเบียบเป็นเรื่องง่ายและอ่านง่าย เป้าหมายของภาพเคลื่อนไหวและแนวทางแบบเลเยอร์ที่ฉันใช้มีดังนี้
- การเคลื่อนไหวลดลงคือการเปลี่ยนภาพเริ่มต้น ซึ่งเป็นการจางเข้าและจางออกของความทึบแสงแบบง่ายๆ
- หากการเคลื่อนไหวใช้ได้ ระบบจะเพิ่มภาพเคลื่อนไหวแบบสไลด์และปรับขนาด
- เลย์เอาต์อุปกรณ์เคลื่อนที่ที่ปรับเปลี่ยนตามพื้นที่โฆษณาสําหรับกล่องโต้ตอบขนาดใหญ่ได้รับการปรับให้เลื่อนออก
การเปลี่ยนค่าเริ่มต้นที่ปลอดภัยและมีความหมาย
แม้ว่า Open Props จะมีคีย์เฟรมสำหรับการจางเข้าและจางออก แต่ฉันชอบ
วิธีการเปลี่ยนฉากแบบเลเยอร์นี้เป็นค่าเริ่มต้น โดยมีภาพเคลื่อนไหวคีย์เฟรมเป็น
การอัปเกรดที่อาจเกิดขึ้น ก่อนหน้านี้เราได้จัดรูปแบบระดับการเข้าถึงของกล่องโต้ตอบด้วย
ความทึบแสง โดยประสานงาน 1
หรือ 0
ขึ้นอยู่กับแอตทริบิวต์ [open]
หากต้องการ
เปลี่ยนจาก 0% เป็น 100% ให้บอกเบราว์เซอร์ว่าคุณต้องการ
การเปลี่ยนผ่านนานเท่าใดและเป็นแบบใด
dialog {
transition: opacity .5s var(--ease-3);
}
การเพิ่มการเคลื่อนไหวลงในการเปลี่ยน
หากผู้ใช้ตกลงที่จะใช้การเคลื่อนไหว ทั้งกล่องโต้ตอบขนาดใหญ่และขนาดเล็กควรเลื่อนขึ้น
เมื่อเข้าสู่หน้าจอ และขยายออกเมื่อออกจากหน้าจอ คุณทำได้โดยใช้
prefers-reduced-motion
Media Query และ Open Props เพียงไม่กี่รายการ ดังนี้
@media (prefers-reduced-motion: no-preference) {
dialog {
animation: var(--animation-scale-down) forwards;
animation-timing-function: var(--ease-squish-3);
}
dialog[open] {
animation: var(--animation-slide-in-up) forwards;
}
}
การปรับภาพเคลื่อนไหวเมื่อกดออกสำหรับอุปกรณ์เคลื่อนที่
ก่อนหน้านี้ในส่วนการจัดรูปแบบ เราได้ปรับรูปแบบกล่องโต้ตอบขนาดใหญ่สำหรับอุปกรณ์เคลื่อนที่ ให้คล้ายกับชีตการดำเนินการมากขึ้น ราวกับว่ามีกระดาษแผ่นเล็กๆ เลื่อน ขึ้นมาจากด้านล่างของหน้าจอและยังคงติดอยู่กับด้านล่าง ภาพเคลื่อนไหวการออกจากการขยายขนาดไม่เหมาะกับการออกแบบใหม่นี้ และเราสามารถปรับภาพเคลื่อนไหวนี้ได้ด้วย การค้นหาสื่อ 2-3 รายการและ Open Props บางรายการ
@media (prefers-reduced-motion: no-preference) and @media (max-width: 768px) {
dialog[modal-mode="mega"] {
animation: var(--animation-slide-out-down) forwards;
animation-timing-function: var(--ease-squish-2);
}
}
JavaScript
คุณเพิ่มสิ่งต่างๆ ได้มากมายด้วย JavaScript ดังนี้
// dialog.js
export default async function (dialog) {
// add light dismiss
// add closing and closed events
// add opening and opened events
// add removed event
// removing loading attribute
}
การเพิ่มเหล่านี้เกิดจากความต้องการให้มีการปิดอย่างรวดเร็ว (คลิกฉากหลังของกล่องโต้ตอบ) ภาพเคลื่อนไหว และเหตุการณ์เพิ่มเติมบางอย่างเพื่อให้ได้เวลาที่เหมาะสมในการรับข้อมูลแบบฟอร์ม
เพิ่มการปิดไฟ
งานนี้ตรงไปตรงมาและเป็นส่วนเสริมที่ยอดเยี่ยมสำหรับองค์ประกอบกล่องโต้ตอบที่ไม่ได้
เคลื่อนไหว การโต้ตอบจะเกิดขึ้นเมื่อมีการคลิกในองค์ประกอบกล่องโต้ตอบ
และใช้การส่งต่อเหตุการณ์
เพื่อประเมินสิ่งที่คลิก และจะclose()
ก็ต่อเมื่อเป็นองค์ประกอบบนสุดเท่านั้น
export default async function (dialog) {
dialog.addEventListener('click', lightDismiss)
}
const lightDismiss = ({target:dialog}) => {
if (dialog.nodeName === 'DIALOG')
dialog.close('dismiss')
}
ประกาศ dialog.close('dismiss')
ระบบจะเรียกใช้เหตุการณ์และระบุสตริง
JavaScript อื่นๆ สามารถดึงข้อมูลสตริงนี้เพื่อรับข้อมูลเชิงลึกเกี่ยวกับวิธีปิดกล่องโต้ตอบได้ คุณจะเห็นว่าฉันได้ระบุสตริงที่ใกล้เคียงทุกครั้งที่เรียกใช้ฟังก์ชันจากปุ่มต่างๆ เพื่อให้บริบทแก่แอปพลิเคชันเกี่ยวกับการโต้ตอบของผู้ใช้
การเพิ่มกิจกรรมที่กำลังจะปิดและปิดแล้ว
องค์ประกอบกล่องโต้ตอบมาพร้อมกับเหตุการณ์ปิด ซึ่งจะปล่อยออกมาทันทีเมื่อมีการเรียกใช้ฟังก์ชัน
dialog close()
เนื่องจากเรากำลังสร้างภาพเคลื่อนไหวให้กับองค์ประกอบนี้ จึงควรมีเหตุการณ์ก่อนและหลังภาพเคลื่อนไหว เพื่อให้การเปลี่ยนแปลงดึงข้อมูลหรือรีเซ็ตแบบฟอร์มกล่องโต้ตอบ ฉันใช้แอตทริบิวต์นี้ที่นี่เพื่อจัดการการเพิ่มแอตทริบิวต์
inert
ในกล่องโต้ตอบที่ปิด และในเดโม ฉันใช้แอตทริบิวต์เหล่านี้เพื่อแก้ไข
รายการอวตารหากผู้ใช้ส่งรูปภาพใหม่
หากต้องการทําเช่นนี้ ให้สร้างเหตุการณ์ใหม่ 2 รายการชื่อ closing
และ closed
จากนั้น
รอเหตุการณ์ปิดในตัวในกล่องโต้ตอบ จากนั้นตั้งค่ากล่องโต้ตอบเป็น
inert
แล้วส่งเหตุการณ์ closing
งานถัดไปคือรอให้ภาพเคลื่อนไหวและการเปลี่ยนผ่านทำงานบนกล่องโต้ตอบจนเสร็จ จากนั้นส่งclosed
เหตุการณ์
const dialogClosingEvent = new Event('closing')
const dialogClosedEvent = new Event('closed')
export default async function (dialog) {
…
dialog.addEventListener('close', dialogClose)
}
const dialogClose = async ({target:dialog}) => {
dialog.setAttribute('inert', '')
dialog.dispatchEvent(dialogClosingEvent)
await animationsComplete(dialog)
dialog.dispatchEvent(dialogClosedEvent)
}
const animationsComplete = element =>
Promise.allSettled(
element.getAnimations().map(animation =>
animation.finished))
ฟังก์ชัน animationsComplete
ซึ่งใช้ในการสร้างคอมโพเนนต์
ข้อความป๊อปอัปด้วย จะแสดงผล Promise ตาม
Promise ของภาพเคลื่อนไหวและการเปลี่ยนที่เสร็จสมบูรณ์ ด้วยเหตุนี้ dialogClose
จึงเป็นฟังก์ชันแบบอะซิงโครนัส
จากนั้นจะawait
สัญญาที่ส่งคืนและดำเนินการต่อไปยังเหตุการณ์ที่ปิดได้อย่างมั่นใจ
การเพิ่มกิจกรรมที่กำลังจะเปิดและเปิดแล้ว
การเพิ่มเหตุการณ์เหล่านี้ทำได้ยากกว่าเนื่องจากองค์ประกอบกล่องโต้ตอบในตัวไม่ได้ ระบุเหตุการณ์เปิดเหมือนกับที่ทำกับเหตุการณ์ปิด ฉันใช้ MutationObserver เพื่อให้ข้อมูลเชิงลึกเกี่ยวกับการเปลี่ยนแปลงแอตทริบิวต์ของกล่องโต้ตอบ ใน Observer นี้ ฉันจะคอยดูการเปลี่ยนแปลงแอตทริบิวต์ "เปิด" และจัดการเหตุการณ์ที่กำหนดเอง ตามนั้น
สร้างกิจกรรมใหม่ 2 รายการชื่อ opening
และ opened
เช่นเดียวกับวิธีที่เราเริ่มกิจกรรมที่กำลังจะปิดและปิดไปแล้ว ในที่ที่เราเคยรอฟังเหตุการณ์ปิดกล่องโต้ตอบ
คราวนี้ให้ใช้ Mutation Observer ที่สร้างขึ้นเพื่อดูแอตทริบิวต์ของกล่องโต้ตอบ
…
const dialogOpeningEvent = new Event('opening')
const dialogOpenedEvent = new Event('opened')
export default async function (dialog) {
…
dialogAttrObserver.observe(dialog, {
attributes: true,
})
}
const dialogAttrObserver = new MutationObserver((mutations, observer) => {
mutations.forEach(async mutation => {
if (mutation.attributeName === 'open') {
const dialog = mutation.target
const isOpen = dialog.hasAttribute('open')
if (!isOpen) return
dialog.removeAttribute('inert')
// set focus
const focusTarget = dialog.querySelector('[autofocus]')
focusTarget
? focusTarget.focus()
: dialog.querySelector('button').focus()
dialog.dispatchEvent(dialogOpeningEvent)
await animationsComplete(dialog)
dialog.dispatchEvent(dialogOpenedEvent)
}
})
})
ระบบจะเรียกใช้ฟังก์ชัน Callback ของ Mutation Observer เมื่อมีการเปลี่ยนแปลงแอตทริบิวต์ของกล่องโต้ตอบ
โดยจะแสดงรายการการเปลี่ยนแปลงเป็นอาร์เรย์ วนซ้ำการเปลี่ยนแปลงแอตทริบิวต์ โดยมองหา attributeName
ที่เปิดอยู่ จากนั้นให้ตรวจสอบว่าองค์ประกอบมีแอตทริบิวต์หรือไม่ ซึ่งจะแจ้งให้ทราบว่ากล่องโต้ตอบเปิดอยู่หรือไม่ หากเปิดอยู่ ให้นำแอตทริบิวต์ inert
ออก แล้วตั้งค่าโฟกัส
ไปที่องค์ประกอบที่ขอ
autofocus
หรือองค์ประกอบ button
แรกที่พบในกล่องโต้ตอบ สุดท้ายนี้ เช่นเดียวกับเหตุการณ์ปิดและเหตุการณ์ปิด ให้ส่งเหตุการณ์เปิดทันที รอให้ภาพเคลื่อนไหว
เสร็จสิ้น แล้วจึงส่งเหตุการณ์เปิด
การเพิ่มกิจกรรมที่นำออก
ในแอปพลิเคชันหน้าเว็บเดียว มักจะมีการเพิ่มและนำกล่องโต้ตอบออกตามเส้นทาง หรือความต้องการและสถานะอื่นๆ ของแอปพลิเคชัน ซึ่งอาจมีประโยชน์ในการล้างข้อมูลเหตุการณ์หรือ ข้อมูลเมื่อนำกล่องโต้ตอบออก
คุณทำได้โดยใช้ Mutation Observer อื่น คราวนี้เราจะสังเกตองค์ประกอบย่อยขององค์ประกอบ body แทนที่จะสังเกตแอตทริบิวต์ในองค์ประกอบ dialog และดูว่ามีการนำองค์ประกอบ dialog ออกหรือไม่
…
const dialogRemovedEvent = new Event('removed')
export default async function (dialog) {
…
dialogDeleteObserver.observe(document.body, {
attributes: false,
subtree: false,
childList: true,
})
}
const dialogDeleteObserver = new MutationObserver((mutations, observer) => {
mutations.forEach(mutation => {
mutation.removedNodes.forEach(removedNode => {
if (removedNode.nodeName === 'DIALOG') {
removedNode.removeEventListener('click', lightDismiss)
removedNode.removeEventListener('close', dialogClose)
removedNode.dispatchEvent(dialogRemovedEvent)
}
})
})
})
ระบบจะเรียกใช้การเรียกกลับของ Mutation Observer ทุกครั้งที่มีการเพิ่มหรือนำองค์ประกอบย่อยออกจากเนื้อหาของเอกสาร
การเปลี่ยนแปลงที่เฉพาะเจาะจงที่กำลังสังเกตคือการเปลี่ยนแปลงของ
removedNodes
ที่มี
nodeName
ของ
กล่องโต้ตอบ หากนำกล่องโต้ตอบออก ระบบจะนำเหตุการณ์คลิกและปิดออกเพื่อ
เพิ่มพื้นที่ว่างในหน่วยความจำ และจะส่งเหตุการณ์ที่นำออกที่กำหนดเอง
การนำแอตทริบิวต์การโหลดออก
เราได้เพิ่มแอตทริบิวต์การโหลดลงในกล่องโต้ตอบเพื่อป้องกันไม่ให้ภาพเคลื่อนไหวของกล่องโต้ตอบเล่นภาพเคลื่อนไหวขาออกเมื่อเพิ่มลงในหน้าเว็บหรือเมื่อโหลดหน้าเว็บ สคริปต์ต่อไปนี้จะรอให้ภาพเคลื่อนไหวของกล่องโต้ตอบทำงานเสร็จ แล้วจึงนำแอตทริบิวต์ออก ตอนนี้กล่องโต้ตอบจะเคลื่อนไหวเข้าและออกได้อย่างอิสระ และเราได้ซ่อนภาพเคลื่อนไหวที่อาจทำให้เสียสมาธิได้อย่างมีประสิทธิภาพ
export default async function (dialog) {
…
await animationsComplete(dialog)
dialog.removeAttribute('loading')
}
ดูข้อมูลเพิ่มเติมเกี่ยวกับปัญหาการป้องกันภาพเคลื่อนไหวคีย์เฟรมเมื่อโหลดหน้าเว็บ ที่นี่
ทั้งหมด
ต่อไปนี้คือ dialog.js
ทั้งหมดหลังจากที่เราได้อธิบายแต่ละส่วน
แยกกันแล้ว
// custom events to be added to <dialog>
const dialogClosingEvent = new Event('closing')
const dialogClosedEvent = new Event('closed')
const dialogOpeningEvent = new Event('opening')
const dialogOpenedEvent = new Event('opened')
const dialogRemovedEvent = new Event('removed')
// track opening
const dialogAttrObserver = new MutationObserver((mutations, observer) => {
mutations.forEach(async mutation => {
if (mutation.attributeName === 'open') {
const dialog = mutation.target
const isOpen = dialog.hasAttribute('open')
if (!isOpen) return
dialog.removeAttribute('inert')
// set focus
const focusTarget = dialog.querySelector('[autofocus]')
focusTarget
? focusTarget.focus()
: dialog.querySelector('button').focus()
dialog.dispatchEvent(dialogOpeningEvent)
await animationsComplete(dialog)
dialog.dispatchEvent(dialogOpenedEvent)
}
})
})
// track deletion
const dialogDeleteObserver = new MutationObserver((mutations, observer) => {
mutations.forEach(mutation => {
mutation.removedNodes.forEach(removedNode => {
if (removedNode.nodeName === 'DIALOG') {
removedNode.removeEventListener('click', lightDismiss)
removedNode.removeEventListener('close', dialogClose)
removedNode.dispatchEvent(dialogRemovedEvent)
}
})
})
})
// wait for all dialog animations to complete their promises
const animationsComplete = element =>
Promise.allSettled(
element.getAnimations().map(animation =>
animation.finished))
// click outside the dialog handler
const lightDismiss = ({target:dialog}) => {
if (dialog.nodeName === 'DIALOG')
dialog.close('dismiss')
}
const dialogClose = async ({target:dialog}) => {
dialog.setAttribute('inert', '')
dialog.dispatchEvent(dialogClosingEvent)
await animationsComplete(dialog)
dialog.dispatchEvent(dialogClosedEvent)
}
// page load dialogs setup
export default async function (dialog) {
dialog.addEventListener('click', lightDismiss)
dialog.addEventListener('close', dialogClose)
dialogAttrObserver.observe(dialog, {
attributes: true,
})
dialogDeleteObserver.observe(document.body, {
attributes: false,
subtree: false,
childList: true,
})
// remove loading attribute
// prevent page load @keyframes playing
await animationsComplete(dialog)
dialog.removeAttribute('loading')
}
การใช้โมดูล dialog.js
ฟังก์ชันที่ส่งออกจากโมดูลคาดว่าจะได้รับการเรียกใช้และส่งผ่านองค์ประกอบ Dialog ที่ต้องการเพิ่มเหตุการณ์และฟังก์ชันการทำงานใหม่ต่อไปนี้
import GuiDialog from './dialog.js'
const MegaDialog = document.querySelector('#MegaDialog')
const MiniDialog = document.querySelector('#MiniDialog')
GuiDialog(MegaDialog)
GuiDialog(MiniDialog)
เพียงเท่านี้ ไดอะล็อกทั้ง 2 รายการก็จะได้รับการอัปเกรดให้มีฟีเจอร์การปิดแบบเบา การแก้ไขการโหลดภาพเคลื่อนไหว และเหตุการณ์อื่นๆ ที่ใช้ได้
การฟังเหตุการณ์ที่กำหนดเองใหม่
ตอนนี้องค์ประกอบกล่องโต้ตอบที่อัปเกรดแต่ละรายการสามารถรอฟังเหตุการณ์ใหม่ 5 รายการได้แล้ว เช่น
MegaDialog.addEventListener('closing', dialogClosing)
MegaDialog.addEventListener('closed', dialogClosed)
MegaDialog.addEventListener('opening', dialogOpening)
MegaDialog.addEventListener('opened', dialogOpened)
MegaDialog.addEventListener('removed', dialogRemoved)
ต่อไปนี้เป็นตัวอย่าง 2 รายการของการจัดการเหตุการณ์เหล่านั้น
const dialogOpening = ({target:dialog}) => {
console.log('Dialog opening', dialog)
}
const dialogClosed = ({target:dialog}) => {
console.log('Dialog closed', dialog)
console.info('Dialog user action:', dialog.returnValue)
if (dialog.returnValue === 'confirm') {
// do stuff with the form values
const dialogFormData = new FormData(dialog.querySelector('form'))
console.info('Dialog form data', Object.fromEntries(dialogFormData.entries()))
// then reset the form
dialog.querySelector('form')?.reset()
}
}
ในการสาธิตที่ฉันสร้างด้วยองค์ประกอบกล่องโต้ตอบ ฉันใช้เหตุการณ์ที่ปิดและ ข้อมูลแบบฟอร์มเพื่อเพิ่มองค์ประกอบอวาตาร์ใหม่ลงในรายการ ช่วงเวลาที่เหมาะสมคือ กล่องโต้ตอบได้แสดงภาพเคลื่อนไหวขาออกจนเสร็จแล้ว จากนั้นสคริปต์บางรายการจะแสดงภาพเคลื่อนไหว ในอวตารใหม่ เหตุการณ์ใหม่ช่วยให้การจัดระเบียบประสบการณ์ของผู้ใช้ ราบรื่นยิ่งขึ้น
ข้อความแจ้ง dialog.returnValue
: ข้อความนี้มีสตริงปิดที่ส่งเมื่อมีการเรียกเหตุการณ์
กล่องโต้ตอบ close()
ซึ่งเป็นสิ่งสำคัญในdialogClosed
เหตุการณ์เพื่อ
ทราบว่ากล่องโต้ตอบถูกปิด ยกเลิก หรือยืนยัน หากยืนยันแล้ว สคริปต์จะดึงค่าแบบฟอร์มและรีเซ็ตแบบฟอร์ม การรีเซ็ตมีประโยชน์เพื่อให้เมื่อกล่องโต้ตอบแสดงอีกครั้ง กล่องโต้ตอบจะว่างเปล่าและพร้อมสำหรับการส่งใหม่
บทสรุป
ตอนนี้คุณรู้วิธีที่ฉันใช้แล้ว คุณจะทำอย่างไร 🙂
มาลองใช้แนวทางที่หลากหลายและเรียนรู้วิธีต่างๆ ในการสร้างสรรค์บนเว็บกัน
สร้างการสาธิต ทวีตลิงก์มาให้ฉัน แล้วฉันจะเพิ่มลิงก์นั้น ลงในส่วนรีมิกซ์ของชุมชนด้านล่าง
รีมิกซ์ของชุมชน
- @GrimLink พร้อมกล่องโต้ตอบ 3-in-1
- @mikemai2awesome ที่มีรีมิกซ์
เจ๋งๆ ซึ่งไม่เปลี่ยนแปลงพร็อพเพอร์ตี้
display
- @geoffrich_ ด้วย Svelte และ Svelte FLIP ที่สวยงาม
แหล่งข้อมูล
- ซอร์สโค้ดใน GitHub
- อวาตาร์ Doodle