การสร้างคอมโพเนนต์เคล็ดลับเครื่องมือ

ภาพรวมพื้นฐานของวิธีสร้างองค์ประกอบที่กำหนดเองของเคล็ดลับเครื่องมือที่ปรับสีได้และเข้าถึงได้

ในโพสต์นี้ ฉันอยากจะแชร์ความคิดเห็นเกี่ยวกับวิธีสร้าง<tool-tip>องค์ประกอบที่กำหนดเอง<tool-tip>ที่ปรับสีได้และเข้าถึงได้ ลองใช้ เดโมและดู แหล่งที่มา

เคล็ดลับเครื่องมือจะแสดงการทำงานในตัวอย่างและชุดรูปแบบสีต่างๆ

หากต้องการดูวิดีโอ โปรดดูโพสต์นี้ใน YouTube

ภาพรวม

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

สิ่งที่ควรทำ: ติดป้ายกำกับอินพุตเสมอ
อย่า: ใช้เคล็ดลับเครื่องมือแทนป้ายกำกับ

Toggletip เทียบกับ Tooltip

เช่นเดียวกับคอมโพเนนต์อื่นๆ มีคำอธิบายที่แตกต่างกันเกี่ยวกับสิ่งที่เรียกว่าเคล็ดลับเครื่องมือ เช่น ใน MDN, WAI ARIA, Sarah Higley และ Inclusive Components ฉันชอบ การแยกความแตกต่างระหว่างเคล็ดลับเครื่องมือกับเคล็ดลับการสลับ เคล็ดลับเครื่องมือควรมี ข้อมูลเสริมแบบไม่โต้ตอบ ในขณะที่เคล็ดลับการสลับอาจมี การโต้ตอบและข้อมูลสำคัญ สาเหตุหลักที่ทำให้เกิดการแบ่งแยกคือ การเข้าถึง ผู้ใช้ควรไปยังป๊อปอัปและเข้าถึง ข้อมูลและปุ่มภายในได้อย่างไร เคล็ดลับการเปิด/ปิดอาจซับซ้อนได้อย่างรวดเร็ว

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

ความท้าทาย GUI นี้ใช้เส้นทางของเคล็ดลับเครื่องมือ โดยพยายามทำทุกอย่างด้วย CSS และนี่คือวิธีสร้าง

Markup

ฉันเลือกใช้องค์ประกอบที่กำหนดเอง <tool-tip> ผู้เขียนไม่จำเป็นต้องเปลี่ยนองค์ประกอบที่กำหนดเอง ให้เป็นคอมโพเนนต์ของเว็บหากไม่ต้องการ เบราว์เซอร์จะถือว่า <foo-bar> เหมือนกับ <div> คุณอาจมองว่าองค์ประกอบที่กำหนดเองเป็นเหมือนคลาสที่มีความเฉพาะเจาะจงน้อยกว่า โดยไม่ต้องใช้ JavaScript

<tool-tip>A tooltip</tool-tip>

ซึ่งคล้ายกับ div ที่มีข้อความอยู่ข้างใน เราสามารถเชื่อมโยงกับโครงสร้างการช่วยเหลือพิเศษ ของโปรแกรมอ่านหน้าจอที่ใช้งานได้โดยการเพิ่ม [role="tooltip"]

<tool-tip role="tooltip">A tooltip</tool-tip>

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

ภาพหน้าจอของแผนผังการช่วยเหลือพิเศษของเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome ที่แสดง HTML แสดง
ลิงก์ที่มีข้อความ &quot;top ; Has tooltip: Hey, a tooltip!&quot; ซึ่งโฟกัสได้ ภายใน
มีข้อความแบบคงที่ของ &quot;top&quot; และองค์ประกอบเคล็ดลับเครื่องมือ

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

<tool-tip inert role="tooltip">A tooltip</tool-tip>

ภาพหน้าจออีกภาพของแผนผังการช่วยเหลือพิเศษของ Chrome DevTools คราวนี้ไม่มี
องค์ประกอบเคล็ดลับเครื่องมือ

จากนั้นฉันเลือกใช้แอตทริบิวต์เป็นอินเทอร์เฟซเพื่อระบุตำแหน่งของ เคล็ดลับเครื่องมือ โดยค่าเริ่มต้น <tool-tip> ทั้งหมดจะอยู่ในตำแหน่ง "บนสุด" แต่คุณปรับแต่งตำแหน่งในองค์ประกอบได้โดยเพิ่ม tip-position ดังนี้

<tool-tip role="tooltip" tip-position="right ">A tooltip</tool-tip>


ภาพหน้าจอของลิงก์ที่มีเคล็ดลับเครื่องมือทางด้านขวาซึ่งระบุว่า &quot;เคล็ดลับเครื่องมือ&quot;

ฉันมักจะใช้แอตทริบิวต์แทนคลาสสำหรับสิ่งต่างๆ เช่นนี้ เพื่อให้ <tool-tip> ไม่สามารถมีหลายตำแหน่งที่กำหนดพร้อมกันได้ โดยจะมีได้เพียง 1 รายการหรือไม่มีเลย

สุดท้าย ให้วางองค์ประกอบ <tool-tip> ไว้ภายในองค์ประกอบที่ต้องการแสดงเคล็ดลับเครื่องมือ ในที่นี้ ฉันแชร์altข้อความกับผู้ใช้ที่มีสายตาปกติโดยวางรูปภาพ และ<tool-tip>ไว้ภายใน องค์ประกอบ <picture>

<picture>
  <img alt="The GUI Challenges skull logo" width="100" src="...">
  <tool-tip role="tooltip" tip-position="bottom">
    The <b>GUI Challenges</b> skull logo
  </tool-tip>
</picture>

ภาพหน้าจอของรูปภาพที่มีเคล็ดลับเครื่องมือที่ระบุว่า &quot;โลโก้กะโหลกของ GUI Challenges
&quot;

ในตัวอย่างนี้ ฉันวาง <tool-tip> ไว้ภายในองค์ประกอบ <abbr>

<p>
  The <abbr>HTML <tool-tip role="tooltip" tip-position="top">Hyper Text Markup Language</tool-tip></abbr> abbr element.
</p>

ภาพหน้าจอของย่อหน้าที่มีตัวย่อ HTML ขีดเส้นใต้และเคล็ดลับเครื่องมือเหนือ
ข้อความที่ระบุว่า &quot;Hyper Text Markup Language&quot;

การช่วยเหลือพิเศษ

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

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

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

ภาพหน้าจอของ VoiceOver ใน MacOS ที่อ่านลิงก์พร้อมเคล็ดลับเครื่องมือ

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

ภาพหน้าจอของโครงสร้างการช่วยเหลือพิเศษของเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome ซึ่งข้อความลิงก์ระบุว่า
&#39;ด้านบน เฮ้ เคล็ดลับเครื่องมือ!&#39;

เพิ่มองค์ประกอบเสมือนสำหรับโปรแกรมอ่านหน้าจอเท่านั้นลงใน <tool-tip> แล้วเราจะเพิ่มข้อความแจ้งของเราเองสำหรับผู้ใช้ที่มองไม่เห็นได้

&::before {
  content: "; Has tooltip: ";
  clip: rect(1px, 1px, 1px, 1px);
  clip-path: inset(50%);
  height: 1px;
  width: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
}

ด้านล่างนี้คือแผนผังการช่วยเหลือพิเศษที่อัปเดตแล้ว ซึ่งตอนนี้มีเครื่องหมายอัฒภาค หลังข้อความลิงก์และข้อความแจ้งสำหรับเคล็ดลับเครื่องมือ "มีเคล็ดลับเครื่องมือ: "

ภาพหน้าจอที่อัปเดตแล้วของแผนผังการช่วยเหลือพิเศษของเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome ซึ่งข้อความลิงก์มีวลีที่ปรับปรุงแล้วว่า &quot;top ; Has tooltip: Hey, a tooltip!&quot;

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

รูปแบบ

องค์ประกอบ <tool-tip> จะเป็นองค์ประกอบย่อยขององค์ประกอบที่แสดงข้อความเสริม ดังนั้นเรามาเริ่มจากสิ่งจำเป็นสำหรับ เอฟเฟกต์ภาพซ้อนทับกันก่อน นำออกจากโฟลว์เอกสารด้วย position absolute

tool-tip {
  position: absolute;
  z-index: 1;
}

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

Browser Support

  • Chrome: 105.
  • Edge: 105.
  • Firefox: 121.
  • Safari: 15.4.

Source

:has(> tool-tip) {
  position: relative;
}

ไม่ต้องกังวลเรื่องการรองรับเบราว์เซอร์มากนัก ก่อนอื่นโปรดทราบว่าเคล็ดลับเครื่องมือเหล่านี้ เป็นข้อมูลเสริม หากไม่ได้ผลก็ไม่เป็นไร ประการที่สอง ในส่วน JavaScript เราจะติดตั้งใช้งานสคริปต์เพื่อ Polyfill ฟังก์ชันที่เราต้องการ สำหรับเบราว์เซอร์ที่ไม่มีการรองรับ :has()

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

tool-tip {
  
  pointer-events: none;
  user-select: none;
}

จากนั้นซ่อนเคล็ดลับเครื่องมือด้วยความทึบแสงเพื่อให้เราเปลี่ยนเคล็ดลับเครื่องมือด้วย การครอสเฟดได้

tool-tip {
  opacity: 0;
}

:has(> tool-tip):is(:hover, :focus-visible, :active) > tool-tip {
  opacity: 1;
}

:is() และ :has() จะ ทำงานหนักในส่วนนี้ ทำให้ tool-tip ที่มีองค์ประกอบระดับบนสุดรับรู้ถึง การโต้ตอบของผู้ใช้เพื่อสลับระดับการมองเห็นของเคล็ดลับเครื่องมือสำหรับองค์ประกอบย่อย ผู้ใช้เมาส์ สามารถวางเมาส์ ผู้ใช้แป้นพิมพ์และโปรแกรมอ่านหน้าจอสามารถโฟกัส และผู้ใช้ระบบสัมผัสสามารถแตะ

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

ภาพหน้าจอของเคล็ดลับเครื่องมือในดาร์กโหมดที่ลอยอยู่เหนือลิงก์ &quot;block-start&quot;

tool-tip {
  --_p-inline: 1.5ch;
  --_p-block: .75ch;
  --_triangle-size: 7px;
  --_bg: hsl(0 0% 20%);
  --_shadow-alpha: 50%;

  --_bottom-tip: conic-gradient(from -30deg at bottom, rgba(0,0,0,0), #000 1deg 60deg, rgba(0,0,0,0) 61deg) bottom / 100% 50% no-repeat;
  --_top-tip: conic-gradient(from 150deg at top, rgba(0,0,0,0), #000 1deg 60deg, rgba(0,0,0,0) 61deg) top / 100% 50% no-repeat;
  --_right-tip: conic-gradient(from -120deg at right, rgba(0,0,0,0), #000 1deg 60deg, rgba(0,0,0,0) 61deg) right / 50% 100% no-repeat;
  --_left-tip: conic-gradient(from 60deg at left, rgba(0,0,0,0), #000 1deg 60deg, rgba(0,0,0,0) 61deg) left / 50% 100% no-repeat;

  pointer-events: none;
  user-select: none;

  opacity: 0;
  transform: translateX(var(--_x, 0)) translateY(var(--_y, 0));
  transition: opacity .2s ease, transform .2s ease;

  position: absolute;
  z-index: 1;
  inline-size: max-content;
  max-inline-size: 25ch;
  text-align: start;
  font-size: 1rem;
  font-weight: normal;
  line-height: normal;
  line-height: initial;
  padding: var(--_p-block) var(--_p-inline);
  margin: 0;
  border-radius: 5px;
  background: var(--_bg);
  color: CanvasText;
  will-change: filter;
  filter:
    drop-shadow(0 3px 3px hsl(0 0% 0% / var(--_shadow-alpha)))
    drop-shadow(0 12px 12px hsl(0 0% 0% / var(--_shadow-alpha)));
}

/* create a stacking context for elements with > tool-tips */
:has(> tool-tip) {
  position: relative;
}

/* when those parent elements have focus, hover, etc */
:has(> tool-tip):is(:hover, :focus-visible, :active) > tool-tip {
  opacity: 1;
  transition-delay: 200ms;
}

/* prepend some prose for screen readers only */
tool-tip::before {
  content: "; Has tooltip: ";
  clip: rect(1px, 1px, 1px, 1px);
  clip-path: inset(50%);
  height: 1px;
  width: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
}

/* tooltip shape is a pseudo element so we can cast a shadow */
tool-tip::after {
  content: "";
  background: var(--_bg);
  position: absolute;
  z-index: -1;
  inset: 0;
  mask: var(--_tip);
}

/* top tooltip styles */
tool-tip:is(
  [tip-position="top"],
  [tip-position="block-start"],
  :not([tip-position]),
  [tip-position="bottom"],
  [tip-position="block-end"]
) {
  text-align: center;
}

การปรับธีม

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

@media (prefers-color-scheme: light) {
  tool-tip {
    --_bg: white;
    --_shadow-alpha: 15%;
  }
}

ภาพหน้าจอแบบข้างต่อข้างของเวอร์ชันสว่างและมืดของเคล็ดลับเครื่องมือ

สำหรับธีมสว่าง เราจะปรับพื้นหลังเป็นสีขาวและลดความเข้มของเงาลงอย่างมากโดยการปรับความทึบ

ขวาไปซ้าย

เพื่อรองรับโหมดการอ่านจากขวาไปซ้าย พร็อพเพอร์ตี้ที่กำหนดเองจะจัดเก็บ ค่าของทิศทางเอกสารเป็นค่า -1 หรือ 1 ตามลำดับ

tool-tip {
  --isRTL: -1;
}

tool-tip:dir(rtl) {
  --isRTL: 1;
}

ซึ่งใช้เพื่อช่วยในการวางตำแหน่งเคล็ดลับเครื่องมือได้

tool-tip[tip-position="top"]) {
  --_x: calc(50% * var(--isRTL));
}

รวมถึงช่วยระบุตำแหน่งของสามเหลี่ยม

tool-tip[tip-position="right"]::after {
  --_tip: var(--_left-tip);
}

tool-tip[tip-position="right"]:dir(rtl)::after {
  --_tip: var(--_right-tip);
}

สุดท้ายนี้ ยังใช้กับตรรกะการแปลงใน translateX() ได้ด้วย

--_x: calc(var(--isRTL) * -3px * -1);

การวางตำแหน่งเคล็ดลับเครื่องมือ

วางเคล็ดลับเครื่องมืออย่างมีตรรกะด้วยพร็อพเพอร์ตี้ inset-block หรือ inset-inline เพื่อจัดการทั้งตำแหน่งเคล็ดลับเครื่องมือจริงและตำแหน่งเคล็ดลับเครื่องมือเชิงตรรกะ โค้ดต่อไปนี้แสดงวิธีจัดรูปแบบตำแหน่งทั้ง 4 ตำแหน่งสำหรับทิศทางทั้งจากซ้ายไปขวาและจากขวาไปซ้าย

การจัดแนวบนและจัดแนวที่จุดเริ่มต้นของบล็อก

ภาพหน้าจอแสดงความแตกต่างของตําแหน่งระหว่างตําแหน่งด้านบนจากซ้ายไปขวา
และตําแหน่งด้านบนจากขวาไปซ้าย

tool-tip:is([tip-position="top"], [tip-position="block-start"], :not([tip-position])) {
  inset-inline-start: 50%;
  inset-block-end: calc(100% + var(--_p-block) + var(--_triangle-size));
  --_x: calc(50% * var(--isRTL));
}

tool-tip:is([tip-position="top"], [tip-position="block-start"], :not([tip-position]))::after {
  --_tip: var(--_bottom-tip);
  inset-block-end: calc(var(--_triangle-size) * -1);
  border-block-end: var(--_triangle-size) solid transparent;
}

การจัดแนวขวาและจัดแนวที่จุดสิ้นสุดของบรรทัด

ภาพหน้าจอแสดงความแตกต่างของตำแหน่งระหว่างตำแหน่งด้านขวาจากซ้ายไปขวา
และตำแหน่งท้ายบรรทัดจากขวาไปซ้าย

tool-tip:is([tip-position="right"], [tip-position="inline-end"]) {
  inset-inline-start: calc(100% + var(--_p-inline) + var(--_triangle-size));
  inset-block-end: 50%;
  --_y: 50%;
}

tool-tip:is([tip-position="right"], [tip-position="inline-end"])::after {
  --_tip: var(--_left-tip);
  inset-inline-start: calc(var(--_triangle-size) * -1);
  border-inline-start: var(--_triangle-size) solid transparent;
}

tool-tip:is([tip-position="right"], [tip-position="inline-end"]):dir(rtl)::after {
  --_tip: var(--_right-tip);
}

การจัดชิดด้านล่างและด้านท้ายของบล็อก

ภาพหน้าจอแสดงความแตกต่างของตำแหน่งระหว่างตำแหน่งด้านล่างจากซ้ายไปขวา
กับตำแหน่งบล็อกสิ้นสุดจากขวาไปซ้าย

tool-tip:is([tip-position="bottom"], [tip-position="block-end"]) {
  inset-inline-start: 50%;
  inset-block-start: calc(100% + var(--_p-block) + var(--_triangle-size));
  --_x: calc(50% * var(--isRTL));
}

tool-tip:is([tip-position="bottom"], [tip-position="block-end"])::after {
  --_tip: var(--_top-tip);
  inset-block-start: calc(var(--_triangle-size) * -1);
  border-block-start: var(--_triangle-size) solid transparent;
}

การจัดแนวซ้ายและจัดแนวเริ่มต้นในบรรทัด

ภาพหน้าจอแสดงความแตกต่างของตำแหน่งระหว่างตำแหน่งด้านซ้ายจากซ้ายไปขวา
และตำแหน่งเริ่มต้นในบรรทัดจากขวาไปซ้าย

tool-tip:is([tip-position="left"], [tip-position="inline-start"]) {
  inset-inline-end: calc(100% + var(--_p-inline) + var(--_triangle-size));
  inset-block-end: 50%;
  --_y: 50%;
}

tool-tip:is([tip-position="left"], [tip-position="inline-start"])::after {
  --_tip: var(--_right-tip);
  inset-inline-end: calc(var(--_triangle-size) * -1);
  border-inline-end: var(--_triangle-size) solid transparent;
}

tool-tip:is([tip-position="left"], [tip-position="inline-start"]):dir(rtl)::after {
  --_tip: var(--_left-tip);
}

แอนิเมชัน

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

การเปลี่ยนค่าเริ่มต้นที่ปลอดภัยและมีความหมาย

จัดรูปแบบองค์ประกอบเคล็ดลับเครื่องมือเพื่อเปลี่ยนความทึบแสงและเปลี่ยนรูปแบบ ดังนี้

tool-tip {
  opacity: 0;
  transform: translateX(var(--_x, 0)) translateY(var(--_y, 0));
  transition: opacity .2s ease, transform .2s ease;
}

:has(> tool-tip):is(:hover, :focus-visible, :active) > tool-tip {
  opacity: 1;
  transition-delay: 200ms;
}

การเพิ่มการเคลื่อนไหวลงในการเปลี่ยน

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

@media (prefers-reduced-motion: no-preference) {
  :has(> tool-tip:is([tip-position="top"], [tip-position="block-start"], :not([tip-position]))):not(:hover):not(:focus-visible):not(:active) tool-tip {
    --_y: 3px;
  }

  :has(> tool-tip:is([tip-position="right"], [tip-position="inline-end"])):not(:hover):not(:focus-visible):not(:active) tool-tip {
    --_x: -3px;
  }

  :has(> tool-tip:is([tip-position="bottom"], [tip-position="block-end"])):not(:hover):not(:focus-visible):not(:active) tool-tip {
    --_y: -3px;
  }

  :has(> tool-tip:is([tip-position="left"], [tip-position="inline-start"])):not(:hover):not(:focus-visible):not(:active) tool-tip {
    --_x: 3px;
  }
}

โปรดทราบว่านี่เป็นการตั้งค่าสถานะ "ออก" เนื่องจากสถานะ "เข้า" อยู่ที่ translateX(0)

JavaScript

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

สคริปต์ Polyfill จะทำ 2 อย่าง และจะทำก็ต่อเมื่อเบราว์เซอร์ไม่รองรับ :has() เท่านั้น ก่อนอื่น ให้ตรวจสอบ:has()การสนับสนุนดังนี้

if (!CSS.supports('selector(:has(*))')) {
  // do work
}

จากนั้นค้นหาองค์ประกอบระดับบนสุดของ <tool-tip> แล้วตั้งชื่อคลาสให้เพื่อ ใช้ทำงานด้วย

if (!CSS.supports('selector(:has(*))')) {
  document.querySelectorAll('tool-tip').forEach(tooltip =>
    tooltip.parentNode.classList.add('has_tool-tip'))
}

จากนั้น ให้แทรกชุดรูปแบบที่ใช้ชื่อคลาสนั้น โดยจำลอง:has() ตัวเลือกเพื่อให้มีลักษณะการทำงานที่เหมือนกันทุกประการ

if (!CSS.supports('selector(:has(*))')) {
  document.querySelectorAll('tool-tip').forEach(tooltip =>
    tooltip.parentNode.classList.add('has_tool-tip'))

  let styles = document.createElement('style')
  styles.textContent = `
    .has_tool-tip {
      position: relative;
    }
    .has_tool-tip:is(:hover, :focus-visible, :active) > tool-tip {
      opacity: 1;
      transition-delay: 200ms;
    }
  `
  document.head.appendChild(styles)
}

เพียงเท่านี้ เบราว์เซอร์ทั้งหมดก็จะแสดงเคล็ดลับเครื่องมืออย่างถูกต้องหากไม่รองรับ :has()

บทสรุป

ตอนนี้คุณทราบแล้วว่าฉันทำได้อย่างไร แล้วคุณล่ะจะทำอย่างไร 🙂 ฉันตั้งตารอที่จะได้ใช้ popup API เพื่อให้การสร้างเคล็ดลับการสลับง่ายขึ้น เลเยอร์บนสุดเพื่อไม่ต้องต่อสู้กับ z-index และ anchor API เพื่อจัดตำแหน่งสิ่งต่างๆ ในหน้าต่างให้ดียิ่งขึ้น ระหว่างนี้ ผมจะสร้างเคล็ดลับเครื่องมือ

มาลองใช้แนวทางที่หลากหลายและเรียนรู้วิธีต่างๆ ในการสร้างสรรค์บนเว็บกัน

สร้างการสาธิต ทวีตลิงก์มาให้ฉัน แล้วฉันจะเพิ่มลิงก์นั้น ลงในส่วนรีมิกซ์ของชุมชนด้านล่าง

รีมิกซ์ของชุมชน

ยังไม่มีอะไรให้ดูที่นี่

แหล่งข้อมูล