- สามารถสร้าง UI ป๊อปโอเวอร์ ที่ลอยอยู่เหนือหน้าเว็บได้ด้วยฟีเจอร์พื้นฐานของเบราว์เซอร์เพียงอย่างเดียว จึงช่วยให้ใช้งานแพตเทิร์นอย่างเมนู ข้อเสนอแนะ และการแจ้งเตือนได้สอดคล้องยิ่งขึ้น
- ป๊อปโอเวอร์ของ Popover API เป็น แบบ non-modal เสมอ ดังนั้นสำหรับ UI ที่ต้องบล็อกการโต้ตอบกับหน้าเว็บ `` จะเหมาะสมกว่า
- การสลับแบบง่ายสามารถจัดการได้ด้วย แอตทริบิวต์ HTML เช่น
popover, popovertarget, popovertargetaction และหากจำเป็นก็ใช้เมธอด JavaScript เพื่อควบคุมสถานะการแสดงผล
- สามารถจัดการสไตล์และการเปลี่ยนแปลงสถานะได้ด้วย
::backdrop, :popover-open, beforetoggle, toggle ฯลฯ และ interest invokers รองรับการแสดงผลเมื่อ hover/focus โดยไม่ต้องใช้ JavaScript
- เป็นฟีเจอร์ Baseline 2025 ที่ใช้งานได้บนอุปกรณ์และเบราว์เซอร์รุ่นใหม่ตั้งแต่มกราคม 2025 แต่ยังต้องตรวจสอบความเข้ากันได้ในสภาพแวดล้อมเก่าหรือรายละเอียดบางส่วนของฟีเจอร์
ปัญหาที่ Popover API แก้ไข
- Popover API มีกลไกมาตรฐานสำหรับแสดงเนื้อหาป๊อปโอเวอร์เหนือคอนเทนต์อื่นในหน้าเว็บ
- ป๊อปโอเวอร์สามารถควบคุมได้ด้วยแอตทริบิวต์ HTML เพียงอย่างเดียว หรือจัดการสถานะแสดง/ซ่อนโดยตรงผ่าน JavaScript API ได้
- ช่วยให้สามารถสร้างแพตเทิร์น UI ที่บนเว็บเคยเรียกกันว่า overlays, popups, popovers, dialogs ฯลฯ ได้สอดคล้องยิ่งขึ้นด้วยฟีเจอร์พื้นฐานของเบราว์เซอร์
หากต้องการ modal ให้ใช้ ``
- UI ป๊อปโอเวอร์แบ่งกว้าง ๆ ได้เป็น modal และ non-modal
- modal คือระหว่างที่ป๊อปโอเวอร์แสดงอยู่ จะโต้ตอบกับส่วนอื่นของหน้าเว็บไม่ได้
- non-modal คือแม้ป๊อปโอเวอร์จะแสดงอยู่ ก็ยังโต้ตอบกับส่วนอื่นของหน้าเว็บต่อได้
- ป๊อปโอเวอร์ที่สร้างด้วย Popover API เป็น non-modal เสมอ
- หากต้องการป๊อปโอเวอร์แบบ modal ที่บล็อกการโต้ตอบกับหน้าเว็บ องค์ประกอบ `` จะเหมาะสมกว่า
- วิธีใช้
popover กับ เช่น ก็ใช้ได้เช่นกัน และสามารถใช้ทั้งการควบคุมป๊อปโอเวอร์ร่วมกับ semantics ของ dialog ได้
วิธีใช้งานพื้นฐาน
- Popover API มักใช้ได้กับ UI ที่ต้องอาศัยการโต้ตอบของผู้ใช้
- เมนูการกระทำ
- การแจ้งเตือน toast แบบกำหนดเอง
- ข้อเสนอแนะสำหรับองค์ประกอบฟอร์ม
- ตัวเลือกคอนเทนต์
- UI เพื่อการสอนใช้งาน
- สามารถสร้างปุ่มสลับป๊อปโอเวอร์อย่างง่ายได้ด้วย HTML เท่านั้น
Toggle the popover
Popover content
- ใน JavaScript ใช้
HTMLElement.togglePopover() เพื่อสลับสถานะแสดง/ซ่อนของป๊อปโอเวอร์
- API นี้ยังมีอีเวนต์สำหรับตอบสนองต่อการเปลี่ยนสถานะของป๊อปโอเวอร์ และฟีเจอร์ CSS ที่ช่วยด้านการจัดสไตล์ให้ด้วย
แอตทริบิวต์ HTML
interestfor
- กำหนดองค์ประกอบ HTML
, , หรือองค์ประกอบ SVG ให้เป็น interest invoker
- ค่าคือ
id ขององค์ประกอบเป้าหมาย และเมื่อ interest แสดงหรือหายไปจากองค์ประกอบ invoker องค์ประกอบเป้าหมายจะได้รับผล
popover
- เป็นแอตทริบิวต์แบบ global ที่เปลี่ยนองค์ประกอบให้เป็นองค์ประกอบป๊อปโอเวอร์
- สามารถรับสถานะเป็นค่า
"auto", "hint", "manual"
popovertarget
- ทำให้องค์ประกอบ
หรือ เป็นปุ่มควบคุมป๊อปโอเวอร์
- ค่าคือ ID ขององค์ประกอบป๊อปโอเวอร์ที่จะควบคุม
popovertargetaction
- ระบุการกระทำที่ปุ่มควบคุมจะทำกับป๊อปโอเวอร์
- ค่าที่เป็นไปได้คือ
"hide", "show", "toggle"
สถานะการแสดงผลที่จัดการด้วย CSS
::backdrop
- เป็น pseudo-element แบบเต็มหน้าจอที่วางอยู่ด้านหลังองค์ประกอบป๊อปโอเวอร์ทันที
- หากจำเป็น สามารถใส่เอฟเฟกต์อย่างการเบลอให้คอนเทนต์ของหน้าเว็บด้านหลังป๊อปโอเวอร์ได้
interest-delay, interest-delay-start, interest-delay-end
- เพิ่ม เวลาหน่วง ระหว่างเวลาที่ผู้ใช้แสดงหรือสูญเสีย interest กับเวลาที่เบราว์เซอร์ตอบสนอง
:interest-source, :interest-target
- สามารถปรับสไตล์ให้ invoker และองค์ประกอบเป้าหมายที่เชื่อมโยงกันตามลำดับได้ในขณะที่ interest แสดงอยู่
:popover-open
- เป็น pseudo-class ที่ match เฉพาะเมื่อองค์ประกอบป๊อปโอเวอร์กำลังแสดงอยู่
- ใช้สำหรับจัดสไตล์ป๊อปโอเวอร์ในสถานะเปิด
อินเทอร์เฟซ JavaScript และส่วนขยาย DOM
InterestEvent
- เป็นออบเจ็กต์อีเวนต์ของอีเวนต์
interest และ loseinterest
- มีพร็อพเพอร์ตี
source ที่เก็บ reference ไปยังองค์ประกอบ interest invoker ที่เชื่อมโยงอยู่
ToggleEvent
- แทนอีเวนต์ที่เกิดขึ้นเมื่อองค์ประกอบป๊อปโอเวอร์สลับระหว่างสถานะแสดงและสถานะซ่อน
- เป็นออบเจ็กต์อีเวนต์ของอีเวนต์
beforetoggle และ toggle
interestForElement
- ใช้ดึงหรือตั้งค่า reference ขององค์ประกอบที่ interest invoker ใช้เป็นเป้าหมาย
- ใช้ได้กับ
HTMLButtonElement, HTMLAnchorElement, HTMLAreaElement, SVGAElement
HTMLElement.popover
- ใช้ดึงหรือตั้งค่าสถานะป๊อปโอเวอร์ขององค์ประกอบด้วย JavaScript
- ใช้ค่า
"auto", "hint", "manual" และยังใช้ตรวจจับฟีเจอร์ได้ด้วย
- สะท้อนค่าของแอตทริบิวต์ global ของ HTML ชื่อ
popover
popoverTargetElement
- ใช้ดึงหรือตั้งค่าองค์ประกอบป๊อปโอเวอร์ที่ปุ่มควบคุมควบคุมอยู่บน
HTMLButtonElement และ HTMLInputElement
- เป็นฟังก์ชันฝั่ง JavaScript ที่สอดคล้องกับแอตทริบิวต์ HTML
popovertarget
popoverTargetAction
- ใช้ดึงหรือตั้งค่าการกระทำของป๊อปโอเวอร์ที่จะทำบน
HTMLButtonElement และ HTMLInputElement
- ใช้ค่า
"hide", "show", "toggle" และสะท้อนแอตทริบิวต์ popovertargetaction
เมธอดและอีเวนต์
HTMLElement.hidePopover()
- นำองค์ประกอบป๊อปโอเวอร์ออกจาก top layer และซ่อนด้วยการจัดสไตล์เป็น
display: none
HTMLElement.showPopover()
- เพิ่มองค์ประกอบป๊อปโอเวอร์เข้าไปใน top layer เพื่อแสดงผล
HTMLElement.togglePopover()
- สลับองค์ประกอบป๊อปโอเวอร์ระหว่างสถานะแสดงและสถานะซ่อน
beforetoggle
- เกิดขึ้นก่อนที่สถานะขององค์ประกอบป๊อปโอเวอร์จะเปลี่ยนระหว่างแสดงและซ่อนทันที
- ใช้เพื่อป้องกันการเปิดป๊อปโอเวอร์ หรืออัปเดตองค์ประกอบอื่นตามสถานะของป๊อปโอเวอร์ได้
toggle
- เกิดขึ้นทันทีหลังจากสถานะขององค์ประกอบป๊อปโอเวอร์เปลี่ยนแล้ว
interest
- เกิดขึ้นเมื่อ interest แสดงบนองค์ประกอบเป้าหมายของ interest invoker
loseinterest
- เกิดขึ้นเมื่อ interest หายไปจากองค์ประกอบเป้าหมายของ interest invoker
ตัวอย่างและลิงก์สเปก
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
Popover API น่าจะสร้างความเปลี่ยนแปลงครั้งใหญ่จริง ๆ เมื่อ การกำหนดตำแหน่งด้วยแองเคอร์ของ CSS (CSS Anchor Positioning) เข้ามาด้วย
การกำหนดตำแหน่งด้วยแองเคอร์ช่วยให้จัดวางองค์ประกอบโดยอ้างอิงจากองค์ประกอบอื่นบนหน้าได้
เมื่อรวมกับ Popover API ก็จะทำทูลทิปแบบกำหนดเองหรือเมนูบริบทได้แบบประกาศ (declarative) และไม่จำเป็นต้องใช้ไลบรารีอย่าง PopperJS อีกต่อไป
https://developer.chrome.com/blog/tether-elements-to-each-ot...
https://popper.js.org/docs/v2/
https://developer.chrome.com/blog/anchor-positioning-api
https://caniuse.com/css-anchor-positioning
สัปดาห์ที่แล้วลองสร้างและปล่อยบางอย่างด้วย Popover API ใหม่ แต่การใช้งานจริงถูกจำกัดไปมากเพราะทุกเบราว์เซอร์ยังขาดการรองรับการกำหนดตำแหน่ง
Firefox ซึ่งเป็นเบราว์เซอร์สุดท้ายก็ดูเหมือนจะใส่การกำหนดตำแหน่งด้วยแองเคอร์ไว้ในเบต้าแล้ว คงอีกไม่นาน
titleถ้าต้องการกล่องโต้ตอบแบบโมดัล ก็มี องค์ประกอบ
<dialog>อยู่แล้วhttps://developer.mozilla.org/en-US/docs/Web/HTML/Element/di...
<details>สำหรับ “ดรอปดาวน์” ได้แปลกตรงที่ต่างจาก
<dialog>หรือ<details>ดูเหมือนว่า<popover>จะไม่สามารถสร้างสถานะopenแบบประกาศได้ด้วยแอตทริบิวต์อย่างเดียวรู้สึกเหมือนเป็นฟีเจอร์ที่ตกหล่นไป และหวังว่าการตัดสินใจนี้จะมีเหตุผลรองรับ
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/de...
ทำได้แน่นอน แต่ไม่ใช่งานเล็กน้อยเลย
การรองรับ Safari ใช้เวลาพอสมควร แต่ตอนนี้ใช้ได้ทุกที่แล้ว
ผมคิดว่าดีกว่าการประกอบแท็กเอง
ถ้าฟีเจอร์นี้ถูกทำร่วมกับ ระบบหน้าต่าง ของระบบปฏิบัติการโฮสต์ ก็ดูเหมือนว่าจำเป็นจริง ๆ
เพราะปัจจุบัน popover ต้องถูกเลียนแบบด้วยวิธีที่ไม่ได้ทำงานดีเสมอไป
เช่น
<select>แบบเนทีฟของเบราว์เซอร์สามารถขยายเลยขอบหน้าต่างเบราว์เซอร์ได้ จึงไม่ต้องกังวลว่าจะถูกตัดโดยหน้าต่าง แต่ select ปลอมสวย ๆ จากทูลคิตอย่าง Quasar ทำแบบนั้นไม่ได้ ทำให้ตัวเลือกในการจัดวางถูกจำกัดถ้าจะทำให้ถูกต้อง บน win32 แต่ละ popover น่าจะต้องมี
HWNDเนทีฟของตัวเอง และบน Cocoa/macOS ก็น่าจะต้องอยู่ในNSViewของตัวเองสงสัยว่าเบราว์เซอร์ตอนนี้ทำแบบนี้จริง ๆ หรือแค่เขียนทับภายในหน้าต่างเบราว์เซอร์เท่านั้น
หากอนุญาตให้เว็บไซต์วาดออกนอกวิวพอร์ตที่กำหนดไว้ได้ ยกเว้นกรณีที่จำกัดมากอย่าง
alert(),confirm(),[title]ก็จะทำให้เลียนแบบกล่องโต้ตอบของเบราว์เซอร์หรือระบบปฏิบัติการได้แนบเนียนขึ้นมากตัวอย่างเช่น หน้าเว็บอาจเลียนแบบวิดเจ็ตปลดล็อกของส่วนขยายจัดการรหัสผ่านได้
นี่เป็นความเสี่ยงด้านความปลอดภัยครั้งใหญ่ และผมคิดว่าไม่คุ้มเมื่อเทียบกับประโยชน์ที่จำกัด
นี่ไม่ใช่ข้อกังวลเชิงทฤษฎี
มิจฉาชีพสร้าง UI ปลอมที่แนบเนียนมากมาหลายปีแล้ว รวมถึงหน้าต่างป๊อปอัปปลอมที่มีโครมของเบราว์เซอร์ และยังลากได้ด้วย
การที่วาดออกนอกขอบเขตวิวพอร์ตไม่ได้แทบจะเป็นข้อจำกัดเดียวที่พวกเขายังหาทางเลี่ยงไม่ได้
บนอุปกรณ์ขนาดเล็ก เว็บเบราว์เซอร์แทบจะเต็มหน้าจอเสมอ และแม้บนจอใหญ่ก็มักจะแตะอย่างน้อยหนึ่งมุมอยู่ดี
ทั้งในด้านการเข้าถึงและการทำให้ครอว์ลได้ รวมถึงถ้าใครอยากทำปลั๊กอิน “ห้ามป๊อปอัป” ก็มีประโยชน์
ฟีเจอร์นี้ถูกเปิดผ่านองค์ประกอบ XUL ที่ใช้ได้เฉพาะใน [X]HTML ที่มีสิทธิ์และเรนเดอร์ในโปรเซสหลักของเบราว์เซอร์เท่านั้น
ผมไม่คิดว่านักพัฒนาเบราว์เซอร์คนไหนอยากให้เว็บเพจทั่วไปมีสิทธิ์สร้างหน้าต่างระบบปฏิบัติการแบบไร้ขอบ
การที่คอนโทรลมาตรฐานบางตัวทำงานแบบนั้นเป็นผลข้างเคียงของการใช้งานเฉพาะแต่ละ OS เพราะถูกทำเป็นเนทีฟของระบบปฏิบัติการ ไม่ได้หมายความว่าจำเป็นต้องทำแบบนั้นเสมอไป
เบราว์เซอร์มีตัวบล็อกป๊อปอัปในตัวอยู่แล้ว เลยตลกนิดหน่อยที่มีการทำ API แบบนี้ขึ้นมา
รู้แหละว่ามันต่างกัน แต่ก็ยังรู้สึกแบบนั้นอยู่ดี
ผมแก่พอที่จะจำ สงครามป๊อปอัป/ป๊อปอันเดอร์ ช่วงปลายยุค 90 และต้นยุค 2000 ได้
ดูเหมือนว่าเราจะชนะศึกนั้นแล้ว แต่สงครามแย่งชิงความสนใจของเรายังอีกยาวไกล
ป๊อปโอเวอร์คือ องค์ประกอบแบบลอย ที่แสดงข้อมูลตามบริบทเมื่อจำเป็น
สิ่งที่พูดถึงนั้นเป็นคนละเรื่องกันโดยสิ้นเชิง
ป๊อปอัปคือการโปรยหน้าต่างขยะลงในระบบปฏิบัติการ และในกรณีเลวร้ายที่สุดก็ขัดขวางการใช้งานคอมพิวเตอร์เลย
ส่วนกล่องโต้ตอบแบบป๊อปโอเวอร์ แค่ปิดแท็บก็จบ
ป๊อปโอเวอร์สไตล์นี้ค่อนข้างมีประโยชน์ในการแสดงข้อมูล และถูกใช้กันมานานแล้ว
มันอาจถูกใช้ให้น่ารำคาญได้ แต่ก็มีกรณีใช้งานจริงมากมายเหมือนกับ modal
ทุกวันนี้ก็ทำป๊อปโอเวอร์ด้วย
divแบบเดิม ๆ ได้อยู่แล้วเช่น: https://getbootstrap.com/docs/5.3/components/popovers/
สิ่งที่เปลี่ยนคือสามารถทำป๊อปโอเวอร์ได้โดยไม่ต้องมีไลบรารีเสริมสารพัด
ต่อให้บล็อกองค์ประกอบ “popover” แบบชัดเจน ผู้คนก็แค่ใช้ไลบรารี custom ต่อไปอยู่ดี
ที่คนเกลียดป๊อปอัปเพราะมันล้ำเส้นและมีหน้าต่างแยกต่างหาก
API นี้มาแทน
divmodal และช่วยลด เวลาและโค้ด ของนักพัฒนาAPI นี้ไม่ได้ทำลายเส้นแบ่งนั้น
ถ้าเส้นแบ่งนั้นถูกทำลาย ความสามารถในการใช้งานและความปลอดภัยของระบบจะลดลง ซึ่งเป็นทิศทางที่เราไม่ต้องการ
มีบอกว่า “ป๊อปโอเวอร์ที่สร้างด้วย Popover API จะเป็น non-modal เสมอ ถ้าต้องการทำ modal popover ควรใช้
<dialog>element” แต่ไม่เข้าใจว่าทำไมนี่เป็นกรณีใช้งานที่ชอบธรรมของป๊อปโอเวอร์
โดยเฉพาะถ้าตอนเปิดมีการเบลอพื้นหลัง และถ้าปุ่มที่ถูกเบลออาจถูกคลิกโดยไม่ตั้งใจจากผู้ใช้ได้ ก็สงสัยว่าทำไมถึงมีฟังก์ชันนั้นให้ใช้
ลองค้นดูแล้วพบว่าสามารถผสมสองอย่างนี้เข้าด้วยกันได้
ประมาณว่า “ถ้าต้องการรวมการควบคุมป๊อปโอเวอร์กับความหมายเชิงกล่องโต้ตอบ ก็ทำให้
<dialog>element เป็นป๊อปโอเวอร์ได้”ถ้าอย่างนั้นตรงนี้แอตทริบิวต์อย่าง
modalน่าจะสมเหตุสมผลกว่านะเพราะก็ยอมรับกรณีใช้งานนี้อย่างชัดเจนอยู่แล้ว
<dialog>มีมาก่อนนานแล้วดีมาก
ถ้าเข้าใจถูก นี่ไม่ได้เป็นการนำฟีเจอร์ใหม่เข้ามาเท่าไร แต่เป็นการทำให้ส่วนที่เคยต้องใช้ modal
div, maskdiv, containerdivและ CSS จัดตำแหน่งที่ยุ่งยาก ง่ายขึ้นยังมีการเพิ่ม pseudo-class ที่ช่วยให้จัดสไตล์ได้ง่ายขึ้นด้วย ชอบเลย
ไม่ต้องฝืนใช้ checkbox ที่ซ่อนไว้แล้ว
ไม่รู้ว่าป๊อปโอเวอร์ที่มีสไตล์และแอนิเมชันจะไปได้ไกลแค่ไหนโดยไม่ใช้ JS แต่การรองรับแบบไม่ใช้ JS ที่จัดการโฟกัสได้ถูกต้องนั้นดี
อยากบอกว่ามีการรองรับ accessibility ในตัวด้วย แต่ยังหาไม่เจอในสเปกตอนนี้
ถ้าจัดการไปถึงการแจ้งองค์ประกอบให้เครื่องมือ accessibility อย่าง screen reader ทราบด้วย ก็จะช่วยได้มาก
เพราะเวลาทำเองมักเผลอลืมได้ค่อนข้างง่าย
มีประโยชน์แน่นอน
เดโม: https://mdn.github.io/dom-examples/popover-api
เพราะยังไม่มีใครใน Chrome หรือ Firefox ทำ ดีเลย์เวลา ก่อนที่เมนูย่อยจะหายไป
งานวิจัยด้านประสบการณ์ผู้ใช้หลายสิบปีหายไป และก็แทบจะเป็นไปตามที่คาดไว้
https://mdn.github.io/dom-examples/popover-api/nested-popove...
ดูเท่ดี แต่ไม่เข้าใจว่าทำไมหน้านี้ถึงไม่มี รูปภาพที่แสดงว่าป๊อปโอเวอร์คืออะไร เลยสักรูป
https://mdn.github.io/dom-examples/popover-api/
มีลิงก์ไปยังตัวอย่างแบบโต้ตอบอยู่ แต่สไตล์พื้นฐานของป๊อปโอเวอร์ดูไม่น่าสนใจเท่าไร
https://mdn.github.io/dom-examples/popover-api/
ยอดเยี่ยม
การทำ custom ด้วย Stimulus โดยใช้ Popper อยู่ที่นี่
https://github.com/tramlinehq/tramline/blob/main/app/javascr...
และการทำสำหรับกล่องโต้ตอบอยู่ที่นี่
https://github.com/tramlinehq/tramline/blob/main/app/javascr...