ขอแนะนำ CSS Anchor Positioning API

เผยแพร่: 10 พฤษภาคม 2024

CSS Anchor Positioning API เป็นเครื่องมือที่พลิกโฉมการพัฒนาเว็บ เนื่องจากช่วยให้คุณวางตําแหน่งองค์ประกอบแบบเนทีฟให้สัมพันธ์กับองค์ประกอบอื่นๆ ที่เรียกว่าแองเคอร์ API นี้ช่วยลดความซับซ้อนของข้อกำหนดเลย์เอาต์ที่ซับซ้อนสำหรับฟีเจอร์อินเทอร์เฟซหลายอย่าง เช่น เมนูและเมนูย่อย เคล็ดลับเครื่องมือ ตัวเลือก ป้ายกำกับ การ์ด กล่องโต้ตอบการตั้งค่า และอื่นๆ อีกมากมาย การวางตำแหน่ง Anchor ที่มีอยู่ในเบราว์เซอร์จะช่วยให้คุณสร้างอินเทอร์เฟซผู้ใช้แบบเลเยอร์ได้โดยไม่ต้องพึ่งพาไลบรารีของบุคคลที่สาม ซึ่งจะเปิดโลกแห่งความเป็นไปได้ในการสร้างสรรค์

การวางตำแหน่ง Anchor พร้อมใช้งานใน Chrome 125

Browser Support

  • Chrome: 125.
  • Edge: 125.
  • Firefox Technology Preview: supported.
  • Safari: 26.

Source

แนวคิดหลัก: องค์ประกอบที่ยึดและองค์ประกอบที่กำหนดตำแหน่ง

หัวใจสำคัญของ API นี้คือความสัมพันธ์ระหว่างองค์ประกอบยึดและองค์ประกอบที่วางตำแหน่ง Anchor คือองค์ประกอบที่กำหนดเป็นจุดอ้างอิงโดยใช้พร็อพเพอร์ตี้ anchor-name องค์ประกอบที่วางตำแหน่งคือองค์ประกอบที่วางไว้เทียบกับจุดยึดโดยใช้พร็อพเพอร์ตี้ position-anchor หรือใช้ anchor-name อย่างชัดเจนในตรรกะการวางตำแหน่ง

องค์ประกอบ Anchor และองค์ประกอบที่กำหนดตำแหน่ง

การตั้งค่า Anchor

การสร้างสมอทำได้ง่ายๆ ใช้พร็อพเพอร์ตี้ชื่อจุดยึดกับองค์ประกอบที่เลือก แล้วกำหนดตัวระบุที่ไม่ซ้ำกัน ตัวระบุที่ไม่ซ้ำกันนี้ต้องมีเครื่องหมายขีดกลางคู่อยู่ด้านหน้า เช่นเดียวกับตัวแปร CSS

.anchor-button {
    anchor-name: --anchor-el;
}

เมื่อกำหนดชื่อยึดแล้ว .anchor-button จะทำหน้าที่เป็นจุดยึดที่พร้อมนำทางตำแหน่งขององค์ประกอบอื่นๆ คุณเชื่อมต่อจุดยึดนี้กับองค์ประกอบอื่นๆ ได้ 2 วิธีดังนี้

Anchor โดยนัย

วิธีแรกในการเชื่อมต่อสมอไปยังองค์ประกอบอื่นคือการใช้สมอโดยนัย ดังตัวอย่างโค้ดต่อไปนี้ ระบบจะเพิ่มพร็อพเพอร์ตี้ position-anchor ลงในองค์ประกอบที่ต้องการเชื่อมต่อกับ Anchor และมีชื่อของ Anchor (ในกรณีนี้คือ --anchor-el) เป็นค่า

.positioned-notice {
    position-anchor: --anchor-el;
}

ความสัมพันธ์ของจุดยึดโดยนัยช่วยให้คุณจัดตำแหน่งองค์ประกอบได้โดยใช้ฟังก์ชัน anchor() โดยไม่ต้องระบุชื่อจุดยึดอย่างชัดเจนในอาร์กิวเมนต์แรก

.positioned-notice {
    position-anchor: --anchor-el;
    top: anchor(bottom);
}

Anchor ที่ชัดเจน

หรือจะใช้ชื่อจุดยึดในฟังก์ชันจุดยึดโดยตรงก็ได้ (เช่น top: anchor(--anchor-el bottom) ซึ่งเรียกว่าจุดยึดที่ชัดเจน และอาจมีประโยชน์หากต้องการยึดกับองค์ประกอบหลายรายการ (อ่านตัวอย่างต่อ)

.positioned-notice {
    top: anchor(--anchor-el bottom);
}

วางตำแหน่งองค์ประกอบที่สัมพันธ์กับจุดยึด

แผนภาพการวางตำแหน่ง Anchor พร้อมคุณสมบัติทางกายภาพ

การวางตำแหน่งจุดยึดสร้างขึ้นจากการวางตำแหน่งแบบสัมบูรณ์ของ CSS หากต้องการใช้ค่าการวางตำแหน่ง คุณต้องเพิ่ม position: absolute ลงในองค์ประกอบที่วางตำแหน่ง จากนั้นใช้anchor()ฟังก์ชันเพื่อใช้ค่าการวางตำแหน่ง เช่น หากต้องการวางองค์ประกอบที่ยึดไว้ที่ด้านบนซ้ายขององค์ประกอบที่ยึด ให้ใช้การวางตำแหน่งต่อไปนี้

.positioned-notice {
    position-anchor: --anchor-el;
    /* absolutely position the positioned element */
    position: absolute;
    /* position the right of the positioned element at the right edge of the anchor */
    right: anchor(right);
    /* position the bottom of the positioned element at the top edge of the anchor */
    bottom: anchor(top);
}
แผนภาพของขอบการวางตำแหน่งในองค์ประกอบที่วางตำแหน่ง

ตอนนี้คุณมีองค์ประกอบหนึ่งที่ยึดกับอีกองค์ประกอบหนึ่งแล้ว ดังที่แสดงในรูปภาพต่อไปนี้

ภาพหน้าจอของเดโม

หากต้องการใช้การวางตำแหน่งเชิงตรรกะสำหรับค่าเหล่านี้ ค่าที่เทียบเท่าจะเป็นดังนี้

  • top = inset-block-start
  • left= inset-inline-start
  • bottom = inset-block-end
  • right= inset-inline-end

จัดกึ่งกลางองค์ประกอบที่วางตำแหน่งด้วย anchor-center

เราได้เพิ่มค่าใหม่ที่ชื่อ anchor-center ซึ่งใช้กับพร็อพเพอร์ตี้ justify-self, align-self, justify-items และ align-items ได้ เพื่อให้จัดกึ่งกลางองค์ประกอบที่วางตำแหน่งไว้กับจุดยึดได้ง่ายขึ้น

ตัวอย่างนี้แก้ไขตัวอย่างก่อนหน้าโดยใช้ justify-self: anchor-center เพื่อจัดองค์ประกอบที่วางตำแหน่งไว้ตรงกลางด้านบนของ Anchor

.positioned-notice {
  position: absolute;
  /*  Anchor reference  */
  position-anchor: --anchor-el;
  /*  Position bottom of positioned elem at top of anchor  */
  bottom: anchor(top);
  /*  Center justification to the anchor */
  justify-self: anchor-center;
}

ภาพหน้าจอของเดโม

Anchor หลายรายการ

โดยองค์ประกอบสามารถเชื่อมโยงกับสมอได้มากกว่า 1 รายการ ซึ่งหมายความว่าคุณอาจต้องตั้งค่าตำแหน่งที่สัมพันธ์กับจุดยึดมากกว่า 1 จุด โดยทำได้ด้วยการใช้ฟังก์ชัน anchor() และระบุอย่างชัดเจนว่าคุณอ้างอิงถึงจุดยึดใดในอาร์กิวเมนต์แรก ในตัวอย่างต่อไปนี้ มุมซ้ายบนขององค์ประกอบที่กำหนดตำแหน่งจะยึดกับมุมขวาล่างของจุดยึดหนึ่ง และมุมขวาล่างขององค์ประกอบที่กำหนดตำแหน่งจะยึดกับมุมซ้ายบนของจุดยึดที่สอง

.anchored {
  position: absolute;
  top: anchor(--one bottom);
  left: anchor(--one right);
  right: anchor(--two left);
  bottom: anchor(--two top);
}

ภาพหน้าจอของเดโม

ตำแหน่งที่มี inset-area

นอกเหนือจากการวางตำแหน่งแบบระบุทิศทางเริ่มต้นจากการวางตำแหน่งแบบสัมบูรณ์แล้ว ยังมีกลไกเลย์เอาต์ใหม่ที่รวมอยู่ใน API การยึดตำแหน่งที่เรียกว่าพื้นที่แทรก

พื้นที่ขอบในช่วยให้วางองค์ประกอบที่วางตำแหน่งยึดกับจุดยึดที่เกี่ยวข้องได้ง่าย และทำงานบนตารางกริด 9 เซลล์โดยมีองค์ประกอบยึดอยู่ตรงกลาง

ตัวเลือกการวางตำแหน่งพื้นที่ขอบด้านในที่เป็นไปได้ต่างๆ ซึ่งแสดงในตารางกริด 9 เซลล์

หากต้องการใช้พื้นที่แทรกแทนการวางตำแหน่งแบบสัมบูรณ์ ให้ใช้พร็อพเพอร์ตี้ inset-area ที่มีค่าทางกายภาพหรือค่าเชิงตรรกะ เช่น

  • ตรงกลางด้านบน: inset-area: top หรือ inset-area: block-start
  • ซ้ายตรงกลาง: inset-area: left หรือ inset-area: inline-start
  • กึ่งกลางด้านล่าง: inset-area: bottom หรือ inset-area: block-end
  • กึ่งกลางด้านขวา: inset-area: right หรือ inset-area: inline-end

ภาพหน้าจอของเดโม

ปรับขนาดองค์ประกอบด้วย anchor-size()

ฟังก์ชัน anchor-size() ซึ่งเป็นส่วนหนึ่งของ Anchor Positioning API ด้วย สามารถใช้เพื่อกำหนดขนาดหรือตำแหน่งขององค์ประกอบที่ยึดตามตำแหน่งของ Anchor ตามขนาดของ Anchor (ความกว้าง ความสูง หรือขนาดแบบอินไลน์และแบบบล็อก)

CSS ต่อไปนี้แสดงตัวอย่างการใช้สำหรับความสูง โดยใช้ anchor-size(height) ภายในฟังก์ชัน calc() เพื่อกำหนดความสูงสูงสุดของเคล็ดลับเครื่องมือให้เป็น 2 เท่าของความสูงของจุดยึด

.positioned-notice {
  position-anchor: --question-mark;

  /*  set max height of the tooltip to 2x height of the anchor  */
  max-height: calc(anchor-size(height) * 2);
}

ภาพหน้าจอของเดโม

ใช้ Anchor กับองค์ประกอบเลเยอร์บนสุด เช่น ป๊อปโอเวอร์และกล่องโต้ตอบ

การวางตำแหน่ง Anchor ทำงานได้ดีอย่างยิ่งกับองค์ประกอบเลเยอร์บนสุด เช่น popover และ <dialog> แม้ว่าองค์ประกอบเหล่านี้จะอยู่ในเลเยอร์แยกต่างหากจากส่วนที่เหลือของ DOM subtree แต่การวางตำแหน่ง Anchor จะช่วยให้คุณเชื่อมโยงองค์ประกอบกลับไปและเลื่อนไปพร้อมกับองค์ประกอบที่ไม่ได้อยู่ในเลเยอร์บนสุดได้ ซึ่งเป็นประโยชน์อย่างยิ่งสำหรับอินเทอร์เฟซแบบเลเยอร์

ในตัวอย่างต่อไปนี้ ระบบจะทริกเกอร์ให้ป๊อปโอเวอร์เคล็ดลับเครื่องมือชุดหนึ่งเปิดขึ้นโดยใช้ปุ่ม ปุ่มคือจุดยึดและเคล็ดลับเครื่องมือคือองค์ประกอบที่จัดตำแหน่ง คุณจัดรูปแบบองค์ประกอบที่วางตำแหน่งได้เช่นเดียวกับองค์ประกอบที่ยึดอื่นๆ สำหรับตัวอย่างนี้ anchor-name และ position-anchor เป็นรูปแบบอินไลน์ในปุ่มและเคล็ดลับเครื่องมือ เนื่องจากแต่ละจุดยึดต้องมีชื่อจุดยึดที่ไม่ซ้ำกัน การแทรกในบรรทัดจึงเป็นวิธีที่ง่ายที่สุดในการดำเนินการนี้เมื่อสร้างเนื้อหาแบบไดนามิก

ภาพหน้าจอของเดโม

ปรับตำแหน่งจุดยึดด้วย @position-try

เมื่อได้ตำแหน่งจุดยึดเริ่มต้นแล้ว คุณอาจต้องปรับตำแหน่งหากจุดยึดไปถึงขอบของบล็อกที่บรรจุ หากต้องการสร้างตำแหน่งยึดแทน คุณสามารถใช้คำสั่ง @position-try ร่วมกับพร็อพเพอร์ตี้ position-try-options

ในตัวอย่างต่อไปนี้ เมนูย่อยจะปรากฏทางด้านขวาของเมนู เมนูและเมนูย่อยเป็นตัวอย่างการใช้ API การวางตำแหน่ง Anchor ร่วมกับแอตทริบิวต์ป๊อปโอเวอร์ เนื่องจากเมนูเหล่านี้มักจะเชื่อมโยงกับปุ่มทริกเกอร์

สำหรับเมนูย่อยนี้ หากมีพื้นที่ไม่เพียงพอในแนวนอน คุณจะย้ายเมนูย่อยไปไว้ใต้เมนูแทนได้ โดยก่อนอื่นให้ตั้งค่าตำแหน่งเริ่มต้นดังนี้

#submenu {
  position: absolute;
  position-anchor: --submenu;

  /* initial position */
  margin-left: var(--padding);
  inset-area: right span-bottom;
}

จากนั้นตั้งค่าตำแหน่งยึดสำรองโดยใช้ @position-try ดังนี้

/* alternate position */
@position-try --bottom {
  margin: var(--padding) 0 0 var(--padding);
  inset-area: bottom;
}

สุดท้าย ให้เชื่อมต่อทั้ง 2 อย่างด้วย position-try-options โดยรวมแล้วจะมีลักษณะดังนี้

#submenu {
  position: absolute;
  position-anchor: --submenu;
  /* initial position */
  margin-left: var(--padding);
  inset-area: right span-bottom;
  */ connect with position-try options */
  position-try-options: --bottom;
}

/* alternate position */
@position-try --bottom {
  margin: var(--padding) 0 0 var(--padding);
  inset-area: bottom;
}

คีย์เวิร์ดที่พลิกตำแหน่งของ Anchor โดยอัตโนมัติ

หากมีการปรับพื้นฐาน เช่น พลิกจากบนลงล่างหรือจากซ้ายไปขวา (หรือทั้ง 2 อย่าง) คุณสามารถข้ามขั้นตอนการสร้าง@position-tryประกาศที่กำหนดเอง และใช้คีย์เวิร์ดพลิกที่เบราว์เซอร์รองรับในตัว เช่น flip-block และ flip-inline ได้ โดยจะใช้แทนการประกาศ @position-try ที่กำหนดเอง และใช้ร่วมกันได้

position-try-options: flip-block, flip-inline, flip-block flip-inline;

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

#my-tooltip {
  position-anchor: --question-mark;
  inset-area: top;
  position-try-options: flip-block;
}

position-visibility สำหรับลิงก์ในแถบเลื่อนย่อย

ในบางกรณี คุณอาจต้องการยึดองค์ประกอบภายในตัวเลื่อนย่อยของหน้า ในกรณีดังกล่าว คุณสามารถควบคุมระดับการมองเห็นของลิงก์โดยใช้ position-visibility เมื่อใดที่สมอจะยังคงอยู่ในมุมมอง When does it disappear? คุณควบคุมตัวเลือกเหล่านี้ได้ด้วยฟีเจอร์นี้ คุณใช้ position-visibility: anchors-visible เมื่อต้องการให้องค์ประกอบที่วางตำแหน่งยังคงอยู่ในมุมมองจนกว่าจุดยึดจะอยู่นอกมุมมอง

#tooltip {
  position: fixed;
  position-anchor: --anchor-top-anchor;
  position-visibility: anchors-visible;
  bottom: anchor(top);
}

หรือจะใช้ position-visibility: no-overflow เพื่อป้องกันไม่ให้ข้อความยึดเลยคอนเทนเนอร์ก็ได้

#tooltip {
  position: absolute;
  position-anchor: --anchor-top-anchor;
  position-visibility: no-overflow;
  bottom: anchor(top);
}

การตรวจหาฟีเจอร์และการเติมโพลีฟิล

เนื่องจากเบราว์เซอร์รองรับ API นี้ได้จำกัดในขณะนี้ คุณจึงอาจต้องใช้ API นี้ด้วยความระมัดระวัง ก่อนอื่น คุณสามารถตรวจสอบการสนับสนุนได้โดยตรงใน CSS โดยใช้คำค้นหาฟีเจอร์ @supports โดยคุณสามารถทำได้ด้วยการรวมสไตล์ลิงก์ในโค้ดต่อไปนี้

@supports (anchor-name: --myanchor) {

  /* Anchor styles here */

}

นอกจากนี้ คุณยังสามารถใช้ Polyfill ฟีเจอร์การวางตำแหน่ง Anchor ด้วย CSS Anchor Positioning Polyfill ของ Oddbird ซึ่งใช้ได้กับ Firefox 54, Chrome 51, Edge 79 และ Safari 10 Polyfill นี้รองรับฟีเจอร์ตำแหน่งยึดพื้นฐานส่วนใหญ่ แม้ว่าการใช้งานในปัจจุบันจะยังไม่สมบูรณ์และมีไวยากรณ์ที่ล้าสมัยอยู่บ้าง คุณสามารถใช้ลิงก์ unpkg หรือนำเข้าโดยตรงในเครื่องมือจัดการแพ็กเกจ

หมายเหตุเกี่ยวกับการช่วยเหลือพิเศษ

แม้ว่า API การวางตำแหน่งจุดยึดจะช่วยให้วางตำแหน่งองค์ประกอบให้สัมพันธ์กับองค์ประกอบอื่นๆ ได้ แต่ก็ไม่ได้สร้างความสัมพันธ์เชิงความหมายที่มีความหมายระหว่างองค์ประกอบเหล่านั้นโดยธรรมชาติ หากองค์ประกอบ Anchor และองค์ประกอบที่วางตำแหน่งมีความสัมพันธ์เชิงความหมายจริง (เช่น องค์ประกอบที่วางตำแหน่งเป็นความคิดเห็นในแถบด้านข้างเกี่ยวกับข้อความ Anchor) วิธีหนึ่งในการดำเนินการดังกล่าวคือการใช้ aria-details เพื่อชี้จากองค์ประกอบ Anchor ไปยังองค์ประกอบที่วางตำแหน่ง ซอฟต์แวร์โปรแกรมอ่านหน้าจอยังอยู่ในช่วงเรียนรู้วิธีจัดการกับ aria-details แต่การรองรับก็ดีขึ้นเรื่อยๆ

<div class="anchor" aria-details="sidebar-comment">Main content</div>
<div class="positioned" id="sidebar-comment">Sidebar content</div>
.anchor {
  anchor-name: --anchor;
}

.positioned {
  position: fixed;
  position-anchor: --anchor;
}

หากคุณใช้การวางตำแหน่งจุดยึดกับแอตทริบิวต์ popover หรือกับองค์ประกอบ <dialog> เบราว์เซอร์จะจัดการการแก้ไขการนำทางด้วยโฟกัสเพื่อให้การช่วยเหลือพิเศษเหมาะสม คุณจึงไม่จำเป็นต้องมีป๊อปโอเวอร์หรือกล่องโต้ตอบตามลำดับ DOM อ่านเพิ่มเติมเกี่ยวกับหมายเหตุเรื่องการช่วยเหลือพิเศษในข้อกำหนด

บทสรุป

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

อ่านเพิ่มเติม