เมื่อสร้างเคล็ดลับเครื่องมือหรือป๊อปโอเวอร์ด้วยการกำหนดตำแหน่ง Anchor ของ CSS เบราว์เซอร์จะ "พลิก" องค์ประกอบไปยังตำแหน่งสำรองโดยอัตโนมัติหากองค์ประกอบนั้นล้นวิวพอร์ต เมื่อเกิดกรณีนี้ขึ้น คุณอาจต้องปรับรูปแบบของเนื้อหาที่กำหนดตำแหน่ง เช่น เปลี่ยนตำแหน่งลูกศรที่ชี้จากเนื้อหาที่กำหนดตำแหน่งไปยัง Anchor
การค้นหาคอนเทนเนอร์ที่ตรึงไว้จะช่วยแก้ปัญหานี้โดยอนุญาตให้คุณค้นหาสถานะการจัดตำแหน่งที่ใช้งานอยู่ขององค์ประกอบและใช้สไตล์ตามนั้น สำหรับตำแหน่งเมนูแบบเลื่อนลงและเมนูย่อยที่ตรึงไว้ทั่วไปซึ่งมีการพลิกการชนวิวพอร์ต (โดยไม่มีการจัดรูปแบบลูกศรบอกทิศทางใหม่) โปรดดูเมนูแบบเลื่อนลงที่รับรู้วิวพอร์ต
ปัญหา
ลองนึกภาพเคล็ดลับเครื่องมือที่ปรากฏเหนือ Anchor โดยค่าเริ่มต้น โดยมีลูกศร "ลง" ที่ด้านล่าง หากผู้ใช้เลื่อนและเคล็ดลับเครื่องมือพลิกไปปรากฏด้านล่าง Anchor ลูกศรจะชี้ผิดทางและอยู่ผิดด้านของเคล็ดลับเครื่องมือ
โซลูชัน: การค้นหาคอนเทนเนอร์ที่ตรึงไว้
การตั้งค่า container-type: anchored ในองค์ประกอบที่กำหนดตำแหน่งจะเปลี่ยนองค์ประกอบดังกล่าวให้เป็นคอนเทนเนอร์การค้นหาที่ทราบสถานะที่กำหนดตำแหน่ง Anchor ของตนเอง จากนั้นคุณจะใช้การค้นหา @container anchored() เพื่ออัปเดตองค์ประกอบสืบทอดหรือองค์ประกอบจำลองได้
1. สร้างเคล็ดลับเครื่องมือและทริกเกอร์
ใช้ Popover API เพื่อสร้างเคล็ดลับเครื่องมือ การเรียกใช้ป๊อปโอเวอร์ผ่าน popovertarget จะสร้างการเชื่อมต่อ Anchor โดยนัยกับปุ่มทริกเกอร์โดยอัตโนมัติ จึงไม่จำเป็นต้องใช้ anchor-name หรือ position-anchor อย่างชัดแจ้ง
<button popovertarget="tooltip" id="anchor" aria-describedby="tooltip">anchor</button>
<div id="tooltip" popover role="tooltip"></div>
รีเซ็ตสไตล์ส่วนแทรกและระยะขอบของป๊อปโอเวอร์เพื่อใช้กับการจัดตำแหน่ง Anchor แต่เฉพาะในกรณีที่รองรับการจัดตำแหน่ง Anchor เท่านั้น
@supports (anchor-name: --my-anchor) {
[popover] {
inset: auto;
margin: unset;
}
}
2. ตั้งค่าคอนเทนเนอร์
ใช้ container-type: anchored กับองค์ประกอบที่กำลังจัดตำแหน่ง องค์ประกอบนี้ต้องมี position-try-fallbacks ที่กำหนดไว้เพื่อเปิดใช้ลักษณะการทำงานของการพลิกด้วย
#tooltip {
position: fixed;
position-area: block-start;
position-try-fallbacks: flip-block;
/* Enable anchored container queries */
container-type: anchored;
}
3. จัดรูปแบบตามโฆษณาสำรอง
ใช้ @container anchored(fallback: <value>) เพื่อใช้สไตล์เมื่อมีการใช้โฆษณาสำรองที่เฉพาะเจาะจง
เช่นเดียวกับการค้นหาคอนเทนเนอร์ทั้งหมด @container สามารถจัดรูปแบบองค์ประกอบสืบทอดของคอนเทนเนอร์ได้เท่านั้น กลยุทธ์ทั่วไปในการสร้างลูกศรคือการใช้ Pseudo-element ::before และ ::after ซึ่งถือเป็นองค์ประกอบสืบทอดและจัดรูปแบบได้โดยตรง อย่างไรก็ตาม หากต้องการจัดรูปแบบเคล็ดลับเครื่องมือ (ดังที่เห็นในขั้นตอนที่ 4) เราจะเพิ่มองค์ประกอบย่อยลงในเคล็ดลับเครื่องมือ และสร้างลูกศรในองค์ประกอบเทียม ::before
<div id="tooltip" popover role="tooltip">
<div class="tooltip-content">Tooltip</div>
</div>
.tooltip-content::before {
/* Default "down" arrow for the 'top' position */
content: "▼";
position: absolute;
inset-block-end: 0;
inset-inline-start: 1rem;
}
/* Update to an "up" arrow when the 'flip-block' fallback (bottom) is active */
@container anchored(fallback: flip-block) {
.tooltip-content::before {
content: "▲";
inset-block-start: 0;
inset-block-end: auto;
}
}
4. การจัดรูปแบบคอนเทนเนอร์
หากต้องการเปลี่ยนพร็อพเพอร์ตี้ในคอนเทนเนอร์ (เช่น margin หรือ background-color) เมื่อพลิก คุณควรใช้องค์ประกอบ Wrapper ด้านใน
- ใช้
container-type: anchoredกับองค์ประกอบที่วางตำแหน่งด้านนอก - กำหนดเป้าหมายองค์ประกอบภายในบล็อก
@container
@container anchored(fallback: flip-block) {
.tooltip-content {
border-radius: 0 0 .5rem .5rem;
margin-block-start: 0.25rem;
}
}
แนวทางปฏิบัติแนะนำ
- ใช้การสำรองเชิงตรรกะ: ใช้คีย์เวิร์ดอย่าง
flip-blockและflip-inlineในposition-try-fallbacksสำหรับการค้นหาที่ง่ายขึ้นซึ่งจัดการ RTL และโหมดการเขียนต่างๆ โดยอัตโนมัติ - ใช้องค์ประกอบเทียมสำหรับลูกศร: ลูกศรเคล็ดลับเครื่องมือมีไว้เพื่อตกแต่งเท่านั้นและเหมาะอย่างยิ่งสำหรับ
::beforeหรือ::afterซึ่งสามารถจัดสไตล์ผ่านการค้นหาคอนเทนเนอร์ที่ยึดไว้โดยไม่ต้องใช้ DOM เพิ่มเติม
กลยุทธ์สำรอง
การวางตำแหน่งลูกศรตามการใช้โหมดสำรองเป็นการเพิ่มประสิทธิภาพแบบต่อเนื่อง และไม่มีวิธีอื่นในการตอบสนองต่อตำแหน่งสำรอง หากต้องการซ่อนลูกศรในเบราว์เซอร์ที่ไม่รองรับการค้นหาคอนเทนเนอร์ตำแหน่ง Anchor ให้ทดสอบการรองรับ CSS ด้วย @supports (container-type: anchored)
@supports (container-type: anchored) {
.tooltip-content::before {
content: "▼";
}
}
การรองรับเบราว์เซอร์และทางเลือกสำรองสำหรับ Popover
Popover API ส่วนใหญ่เป็นการเพิ่มประสิทธิภาพแบบต่อเนื่อง แต่ลักษณะการทำงานที่กำหนดไว้ เช่น การโปรโมตเลเยอร์บนสุด การปิดเมื่อคลิกนอกองค์ประกอบ และการเรียกใช้ popovertarget ไม่มี CSS ที่เทียบเท่า เบราว์เซอร์รุ่นเก่าต้องใช้ Polyfill หรือการสำรองข้อมูลด้วยตนเองหากคุณไม่ต้องการจัดส่ง
Polyfill: หากต้องการรองรับแอตทริบิวต์ popover ในเบราว์เซอร์รุ่นเก่า ให้โหลด @oddbird/popover-polyfill แบบมีเงื่อนไข จำเป็น: ตรวจหาฟีเจอร์โดยการตรวจสอบพร็อพเพอร์ตี้ popover ใน HTMLElement.prototype และโหลด Polyfill เฉพาะเมื่อไม่มีการรองรับแบบเนทีฟ อย่าโหลดโดยไม่มีเงื่อนไข
เมื่อใช้ Bundler หรือแผนที่การนำเข้า ให้ทำดังนี้
// MANDATORY: Feature detect 'popover' on HTMLElement.prototype.
if (!("popover" in HTMLElement.prototype)) {
import("@oddbird/popover-polyfill");
}
หากไม่มี Bundler ให้นำเข้าจาก CDN ภายใน <script type="module">:
<script type="module">
if (!("popover" in HTMLElement.prototype)) {
import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
}
</script>
ข้อควรระวังเกี่ยวกับรูปแบบ: Polyfill ไม่สามารถกำหนดคลาสจำลอง :popover-open จริงได้ จึงใช้คลาส .\:popover-open แทน จำเป็น: รวมทั้ง 2 รายการเข้าด้วยกันโดยใช้ :is() หรือ :where() ไม่เช่นนั้นเบราว์เซอร์ที่ไม่มี :popover-open จะทิ้งกฎทั้งหมด
[popover]:is(:popover-open, .\:popover-open) {
display: block;
}
หรือสำหรับทางเลือกสำรองแบบเดิมที่ไม่มี Polyfill ให้ใช้ position: fixed และคำนวณพิกัดด้วยตนเองผ่าน getBoundingClientRect() หรือใช้การกำหนดตำแหน่งเริ่มต้นด้วย inset: auto หากยอมรับได้สำหรับกรณีการใช้งาน
เบราว์เซอร์ที่ไม่รองรับ Popover API จะไม่รองรับการวางตำแหน่ง Anchor ด้วย ดังนั้นเคล็ดลับเครื่องมือจะปรากฏตรงกลางหน้าจอ