เชื่อมต่ออินเทอร์เน็ตมือถือเข้าด้วยกันด้วยการจัดตำแหน่ง Anchor ของ CSS

ขณะนี้คุณเชื่อมโยงองค์ประกอบหนึ่งกับอีกองค์ประกอบหนึ่งอย่างไร คุณอาจลองติดตามตําแหน่งหรือใช้องค์ประกอบ Wrapper บางรูปแบบ

<!-- index.html -->
<div class="container">
  <a href="/link" class="anchor">I’m the anchor</a>
  <div class="anchored">I’m the anchored thing</div>
</div>
/* styles.css */
.container {
  position: relative;
}
.anchored {
  position: absolute;
}

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

รูปภาพแสดงการจำลองหน้าต่างเบราว์เซอร์โดยละเอียดเกี่ยวกับโครงสร้างของเคล็ดลับเครื่องมือ

การสนับสนุนเบราว์เซอร์

คุณลองใช้ CSS Anchor Positioning API ใน Chrome Canary ได้ที่ Flag "ฟีเจอร์แพลตฟอร์มเว็บเวอร์ชันทดลอง" หากต้องการเปิดใช้ Flag ดังกล่าว ให้เปิด Chrome Canary แล้วไปที่ chrome://flags จากนั้นเปิดใช้การติดธง "ฟีเจอร์แพลตฟอร์มเว็บเวอร์ชันทดลอง"

นอกจากนี้ ยังมี polyfill ที่กำลังพัฒนาโดยทีม Oddbird โปรดตรวจสอบที่พื้นที่เก็บข้อมูล github.com/oddbird/css-anchor-positioning

คุณตรวจสอบการรองรับการยึดได้ด้วยวิธีต่อไปนี้

@supports(anchor-name: --foo) {
  /* Styles... */
}

โปรดทราบว่า API นี้ยังอยู่ในขั้นทดลองและอาจมีการเปลี่ยนแปลง บทความนี้จะกล่าวถึงส่วนสําคัญในระดับสูง นอกจากนี้ การใช้งานในปัจจุบันยังไม่สอดคล้องกับข้อกำหนดของกลุ่มทํางาน CSS ทั้งหมด

ปัญหา

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

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

โซลูชันปัจจุบัน

ปัจจุบันคุณแก้ปัญหานี้ได้หลายวิธี

ขั้นแรกคือการใช้แนวทาง "ตัดต่อส่วนท้าย" แบบพื้นฐาน คุณนำองค์ประกอบทั้ง 2 รายการมารวมไว้ในคอนเทนเนอร์ จากนั้นใช้ position เพื่อจัดตำแหน่งเคล็ดลับเครื่องมือตามจุดยึด

<div class="containing-block">
  <div class="tooltip">Anchor me!</div>
  <a class="anchor">The anchor</a>
</div>
.containing-block {
  position: relative;
}

.tooltip {
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%);
}

คุณสามารถย้ายคอนเทนเนอร์และทุกอย่างจะยังคงอยู่ในตำแหน่งที่ต้องการส่วนใหญ่

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

<div class="tooltip">Anchor me!</div>
<a class="anchor">The anchor</a>
:root {
  --anchor-width: 120px;
  --anchor-top: 40vh;
  --anchor-left: 20vmin;
}

.anchor {
  position: absolute;
  top: var(--anchor-top);
  left: var(--anchor-left);
  width: var(--anchor-width);
}

.tooltip {
  position: absolute;
  top: calc(var(--anchor-top));
  left: calc((var(--anchor-width) * 0.5) + var(--anchor-left));
  transform: translate(-50%, calc(-100% - 10px));
}

แต่จะเกิดอะไรขึ้นหากคุณไม่ทราบตําแหน่งของเครื่องยึด คุณอาจต้องแทรกแซงด้วย JavaScript คุณอาจทําแบบโค้ดต่อไปนี้ได้ แต่ตอนนี้หมายความว่าสไตล์ของคุณเริ่มหลุดออกจาก CSS และเข้าไปใน JavaScript

const setAnchorPosition = (anchored, anchor) => {
  const bounds = anchor.getBoundingClientRect().toJSON();
  for (const [key, value] of Object.entries(bounds)) {
    anchored.style.setProperty(`--${key}`, value);
  }
};

const update = () => {
  setAnchorPosition(
    document.querySelector('.tooltip'),
    document.querySelector('.anchor')
  );
};

window.addEventListener('resize', update);
document.addEventListener('DOMContentLoaded', update);

คำถามที่ตามมาคือ

  • ฉันจะคำนวณสไตล์เมื่อใด
  • ฉันจะคำนวณสไตล์ได้อย่างไร
  • ฉันจะคำนวณสไตล์บ่อยแค่ไหน

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

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

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

โค้ดที่ใช้ "floating-ui" ซึ่งเป็นแพ็กเกจยอดนิยมสำหรับปัญหานี้อาจมีหน้าตาดังนี้

import {computePosition, flip, offset, autoUpdate} from 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.2.1/+esm';

const anchor = document.querySelector('.anchor')
const tooltip = document.querySelector('.tooltip')

const updatePosition = () => {  
  computePosition(anchor, tooltip, {
    placement: 'top',
    middleware: [offset(10), flip()]
  })
    .then(({x, y}) => {
      Object.assign(tooltip.style, {
        left: `${x}px`,
        top: `${y}px`
      })
  })
};

const clean = autoUpdate(anchor, tooltip, updatePosition);

ลองจัดตําแหน่งหมุดใหม่ในการแสดงตัวอย่างนี้ที่ใช้รหัสนั้น

"เคล็ดลับเครื่องมือ" อาจไม่ทำงานตามที่คาดไว้ องค์ประกอบจะตอบสนองต่อการออกจากวิวพอร์ตบนแกน y แต่จะไม่ตอบสนองต่อการออกจากวิวพอร์ตบนแกน x โปรดอ่านเอกสารประกอบและคุณอาจพบวิธีแก้ปัญหาที่เหมาะกับคุณ

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

การใช้ตำแหน่งโฆษณา Anchor

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

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

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

ก่อนอื่น คุณต้องเลือกวิธีกำหนดจุดยึด ซึ่งทำได้ภายใน CSS โดยการตั้งค่าพร็อพเพอร์ตี้ anchor-name ในองค์ประกอบแอตทริบิวต์ ค่าที่ใช้ได้คือ dashed-ident

.anchor {
  anchor-name: --my-anchor;
}

หรือจะกําหนดแอตทริบิวต์ anchor ในแฮนเดิลของ HTML ก็ได้ ค่าแอตทริบิวต์คือรหัสขององค์ประกอบแอตทริบิวต์ การดำเนินการนี้จะสร้างแท็ก Anchor โดยปริยาย

<a id="my-anchor" class="anchor"></a>
<div anchor="my-anchor" class="boat">I’m a boat!</div>

เมื่อกําหนดจุดยึดแล้ว คุณจะใช้ฟังก์ชัน anchor ได้ ฟังก์ชัน anchor ใช้อาร์กิวเมนต์ 3 รายการ ได้แก่

  • องค์ประกอบ Anchor: anchor-name ของ Anchor ที่จะใช้ หรือจะละเว้นค่าเพื่อใช้ Anchor implicit ก็ได้ ซึ่งสามารถกําหนดผ่านความสัมพันธ์ HTML หรือพร็อพเพอร์ตี้ anchor-default ที่มีค่า anchor-name
  • ด้านที่ใช้เป็นจุดยึด: คีย์เวิร์ดของตำแหน่งที่ต้องการใช้ ซึ่งอาจเป็น top, right, bottom, left, center ฯลฯ หรือจะส่งเปอร์เซ็นต์ก็ได้ เช่น 50% จะเท่ากับ center
  • ค่าสำรอง: ค่าสำรองที่ไม่บังคับซึ่งรับความยาวหรือเปอร์เซ็นต์

คุณใช้ฟังก์ชัน anchor เป็นค่าสำหรับพร็อพเพอร์ตี้ระยะยื่น (top, right, bottom, left หรือเทียบเท่าเชิงตรรกะ) ของอีลิเมนต์ที่ยึด คุณยังใช้ฟังก์ชัน anchor ใน calc ได้ด้วย

.boat {
  bottom: anchor(--my-anchor top);
  left: calc(anchor(--my-anchor center) - (var(--boat-size) * 0.5));
}

 /* alternative with anchor-default */
.boat {
  anchor-default: --my-anchor;
  bottom: anchor(top);
  left: calc(anchor(center) - (var(--boat-size) * 0.5));
}

ไม่มีพร็อพเพอร์ตี้ center inset ดังนั้นตัวเลือกหนึ่งคือการใช้ calc หากคุณทราบขนาดขององค์ประกอบที่ยึด เหตุผลที่ไม่ควรใช้ translate คุณอาจใช้ข้อความต่อไปนี้

.boat {
  anchor-default: --my-anchor;
  bottom: anchor(top);
  left: anchor(center);
  translate: -50% 0;
}

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

คุณอาจสังเกตเห็นการใช้พร็อพเพอร์ตี้ที่กำหนดเอง --boat-size ด้านบน แต่หากต้องการกำหนดขนาดองค์ประกอบที่ยึดตามขนาดขององค์ประกอบยึด คุณก็เข้าถึงขนาดนั้นได้เช่นกัน คุณใช้ฟังก์ชัน anchor-size แทนการคํานวณด้วยตนเองได้ ตัวอย่างเช่น หากต้องการสร้างเรือที่กว้าง 4 เท่าของสมอ ให้ทำดังนี้

.boat {
  width: calc(4 * anchor-size(--my-anchor width));
}

นอกจากนี้ คุณยังมีสิทธิ์เข้าถึงความสูงด้วย anchor-size(--my-anchor height) และคุณใช้เครื่องมือนี้เพื่อกำหนดขนาดของทั้ง 2 แกนหรือแกนใดแกนหนึ่งก็ได้

ในกรณีที่คุณต้องการยึดกับองค์ประกอบที่มีการจัดตำแหน่ง absolute กฎคือองค์ประกอบต้องไม่ใช่พี่น้องกัน ในกรณีนี้ คุณสามารถตัดต่อองค์ประกอบแองเคอร์ด้วยคอนเทนเนอร์ที่มีการจัดตำแหน่ง relative จากนั้นคุณก็วางหมุดได้

<div class="anchor-wrapper">
  <a id="my-anchor" class="anchor"></a>
</div>
<div class="boat">I’m a boat!</div>

ดูการสาธิตนี้ซึ่งคุณสามารถลากจุดยึดไปรอบๆ แล้วเรือจะตามไป

การติดตามตำแหน่งการเลื่อน

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

.boat { anchor-scroll: --my-anchor; }

ลองดูการสาธิตนี้ซึ่งคุณสามารถเปิดและปิด anchor-scroll ได้ด้วยช่องทําเครื่องหมายที่มุม

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

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

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

ตำแหน่งสำรองและการจัดตำแหน่งอัตโนมัติ

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

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

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

ก่อนที่จะสร้าง position-fallback ที่ชัดเจน การวางตำแหน่งจุดยึดจะมีการวางตำแหน่งอัตโนมัติด้วย คุณพลิกข้อความได้ฟรีโดยใช้ค่า auto ทั้งกับฟังก์ชันแองเคอร์และพร็อพเพอร์ตี้การเยื้องตรงข้าม เช่น หากคุณใช้ anchor สำหรับ bottom ให้ตั้งค่า top เป็น auto

.tooltip {
  position: absolute;
  bottom: anchor(--my-anchor auto);
  top: auto;
}

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

position-fallback ที่พยายามแสดงเคล็ดลับเครื่องมือด้านบนแล้วด้านล่างอาจมีลักษณะดังนี้

@position-fallback --top-to-bottom {
  @try {
    bottom: anchor(top);
    left: anchor(center);
  }

  @try {
    top: anchor(bottom);
    left: anchor(center);
  }
}

การใช้ข้อมูลดังกล่าวกับเคล็ดลับเครื่องมือจะมีลักษณะดังนี้

.tooltip {
  anchor-default: --my-anchor;
  position-fallback: --top-to-bottom;
}

การใช้ anchor-default หมายความว่าคุณสามารถนํา position-fallback ไปใช้กับองค์ประกอบอื่นๆ ซ้ำได้ นอกจากนี้ คุณยังใช้พร็อพเพอร์ตี้ที่กำหนดเองระดับขอบเขตเพื่อตั้งค่า anchor-default ได้ด้วย

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

position-fallback แสดงรายละเอียดมากขึ้นในครั้งนี้โดยพยายามวางตำแหน่งตามเข็มนาฬิกา

.boat {
  anchor-default: --my-anchor;
  position-fallback: --compass;
}

@position-fallback --compass {
  @try {
    bottom: anchor(top);
    right: anchor(left);
  }

  @try {
    bottom: anchor(top);
    left: anchor(right);
  }

  @try {
    top: anchor(bottom);
    right: anchor(left);
  }

  @try {
    top: anchor(bottom);
    left: anchor(right);
  }
}


ตัวอย่าง

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

เมนูตามบริบท

มาเริ่มกันที่เมนูตามบริบทโดยใช้ Popover API แนวคิดคือเมื่อคลิกปุ่มที่มีเครื่องหมายลูกศรจะแสดงเมนูตามบริบท และเมนูนั้นจะมีเมนูย่อยของตัวเองให้ขยาย

มาร์กอัปไม่ใช่ส่วนสําคัญ แต่คุณมีปุ่ม 3 ปุ่มที่ใช้ popovertarget คุณจึงมีองค์ประกอบ 3 รายการที่ใช้แอตทริบิวต์ popover ซึ่งจะช่วยให้คุณเปิดเมนูตามบริบทได้โดยไม่ต้องใช้ JavaScript ซึ่งอาจมีลักษณะดังนี้

<button popovertarget="context">
  Toggle Menu
</button>        
<div popover="auto" id="context">
  <ul>
    <li><button>Save to your Liked Songs</button></li>
    <li>
      <button popovertarget="playlist">
        Add to Playlist
      </button>
    </li>
    <li>
      <button popovertarget="share">
        Share
      </button>
    </li>
  </ul>
</div>
<div popover="auto" id="share">...</div>
<div popover="auto" id="playlist">...</div>

ตอนนี้คุณกำหนด position-fallback และแชร์ระหว่างเมนูตามบริบทได้แล้ว และเราจะตั้งค่าสไตล์ inset สำหรับป๊อปอัปใหม่ด้วย

[popovertarget="share"] {
  anchor-name: --share;
}

[popovertarget="playlist"] {
  anchor-name: --playlist;
}

[popovertarget="context"] {
  anchor-name: --context;
}

#share {
  anchor-default: --share;
  position-fallback: --aligned;
}

#playlist {
  anchor-default: --playlist;
  position-fallback: --aligned;
}

#context {
  anchor-default: --context;
  position-fallback: --flip;
}

@position-fallback --aligned {
  @try {
    top: anchor(top);
    left: anchor(right);
  }

  @try {
    top: anchor(bottom);
    left: anchor(right);
  }

  @try {
    top: anchor(top);
    right: anchor(left);
  }

  @try {
    bottom: anchor(bottom);
    left: anchor(right);
  }

  @try {
    right: anchor(left);
    bottom: anchor(bottom);
  }
}

@position-fallback --flip {
  @try {
    bottom: anchor(top);
    left: anchor(left);
  }

  @try {
    right: anchor(right);
    bottom: anchor(top);
  }

  @try {
    top: anchor(bottom);
    left: anchor(left);
  }

  @try {
    top: anchor(bottom);
    right: anchor(right);
  }
}

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

โฟกัสและติดตาม

การสาธิตนี้รวมองค์ประกอบพื้นฐานของ CSS โดยใช้ :has() แนวคิดคือเปลี่ยนตัวบ่งชี้ภาพสำหรับ input ที่มีโฟกัส

ซึ่งทำได้โดยการตั้งค่าแองเคอร์ใหม่ในรันไทม์ สําหรับการสาธิตนี้ พร็อพเพอร์ตี้ที่กําหนดเองระดับขอบเขตจะได้รับการอัปเดตเมื่อโฟกัสอินพุต

#email {
    anchor-name: --email;
  }
  #name {
    anchor-name: --name;
  }
  #password {
    anchor-name: --password;
  }
:root:has(#email:focus) {
    --active-anchor: --email;
  }
  :root:has(#name:focus) {
    --active-anchor: --name;
  }
  :root:has(#password:focus) {
    --active-anchor: --password;
  }

:root {
    --active-anchor: --name;
    --active-left: anchor(var(--active-anchor) right);
    --active-top: calc(
      anchor(var(--active-anchor) top) +
        (
          (
              anchor(var(--active-anchor) bottom) -
                anchor(var(--active-anchor) top)
            ) * 0.5
        )
    );
  }
.form-indicator {
    left: var(--active-left);
    top: var(--active-top);
    transition: all 0.2s;
}

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

การคํานวณแผนภูมิแท่ง

อีกสิ่งที่น่าสนใจที่คุณทําได้โดยใช้ตําแหน่งหมุดคือการรวมกับ calc ลองจินตนาการถึงแผนภูมิที่คุณมีพอพอัปที่อธิบายแผนภูมิ

คุณสามารถติดตามค่าสูงสุดและต่ำสุดได้โดยใช้ CSS min และ max CSS ของการดำเนินการดังกล่าวอาจมีลักษณะดังนี้

.chart__tooltip--max {
    left: anchor(--chart right);
    bottom: max(
      anchor(--anchor-1 top),
      anchor(--anchor-2 top),
      anchor(--anchor-3 top)
    );
    translate: 0 50%;
  }

มีการใช้ JavaScript บางรายการเพื่ออัปเดตค่าแผนภูมิและ CSS บางรายการเพื่อจัดรูปแบบแผนภูมิ แต่การวางตำแหน่งจุดยึดจะดูแลเรื่องการอัปเดตเลย์เอาต์ให้เรา

แฮนเดิลปรับขนาด

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

คุณอาจใช้จุดยึดเป็นจุดจับการปรับขนาดที่กำหนดเองและใช้ประโยชน์จากค่า inset

.container {
   position: absolute;
   inset:
     anchor(--handle-1 top)
     anchor(--handle-2 right)
     anchor(--handle-2 bottom)
     anchor(--handle-1 left);
 }

ในการสาธิตนี้ GreenSock Draggable จะทำให้แถบแฮนเดิลสามารถลากได้ แต่องค์ประกอบ <img> จะปรับขนาดให้พอดีกับคอนเทนเนอร์ที่ปรับขนาดให้พอดีกับช่องว่างระหว่างที่จับ

SelectMenu

รายการสุดท้ายนี้เป็นการบอกใบ้ถึงสิ่งที่จะเกิดขึ้น แต่คุณสร้างป๊อปอัปที่โฟกัสได้ และตอนนี้คุณก็มีตำแหน่งของจุดยึดแล้ว คุณอาจสร้างรากฐานขององค์ประกอบ <select> ที่ปรับแต่งสไตล์ได้

<div class="select-menu">
<button popovertarget="listbox">
 Select option
 <svg>...</svg>
</button>
<div popover="auto" id="listbox">
   <option>A</option>
   <option>Styled</option>
   <option>Select</option>
</div>
</div>

anchor ที่ไม่ระบุจะช่วยทำให้การดำเนินการนี้ง่ายขึ้น แต่ CSS สำหรับจุดเริ่มต้นขั้นพื้นฐานอาจมีลักษณะดังนี้

[popovertarget] {
 anchor-name: --select-button;
}
[popover] {
  anchor-default: --select-button;
  top: anchor(bottom);
  width: anchor-size(width);
  left: anchor(left);
}

รวมฟีเจอร์ของ Popover API เข้ากับการวางตำแหน่ง Anchor ของ CSS แล้วคุณก็จะใกล้ถึงเป้าหมาย

เป็นเรื่องที่ดีเมื่อคุณเริ่มแนะนำสิ่งต่างๆ เช่น :has() คุณหมุนเครื่องหมายในโหมดเปิดได้โดยทำดังนี้

.select-menu:has(:open) svg {
  rotate: 180deg;
}

คุณพาเราไปที่ไหนต่อได้บ้าง เราต้องทำอะไรอีกบ้างเพื่อให้ select ใช้งานได้ เราจะเก็บไว้สำหรับบทความถัดไป แต่ไม่ต้องกังวล องค์ประกอบ Select ที่ปรับแต่งสไตล์ได้จะพร้อมใช้งานในเร็วๆ นี้ โปรดอดใจรอ


เท่านี้ก็เรียบร้อย

แพลตฟอร์มเว็บมีการเปลี่ยนแปลงอยู่ตลอดเวลา การวางตำแหน่งจุดยึด CSS เป็นส่วนสําคัญในการปรับปรุงวิธีพัฒนาการควบคุม UI ซึ่งจะช่วยให้คุณไม่ต้องตัดสินใจเรื่องยากๆ บางอย่าง แต่จะช่วยให้คุณทำสิ่งต่างๆ ที่ไม่เคยทำได้มาก่อนได้ด้วย เช่น การจัดสไตล์องค์ประกอบ <select> บอกให้เรารู้ว่าคุณคิดอย่างไร

รูปภาพโดย CHUTTERSNAP ใน Unsplash