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

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

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

เคล็ดลับเครื่องมือจะแสดงตัวอย่างและรูปแบบสีที่หลากหลาย

หากต้องการดูวิดีโอ คุณสามารถใช้โพสต์นี้ในเวอร์ชัน YouTube:

ภาพรวม

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

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

เคล็ดลับเครื่องมือกับเคล็ดลับแบบเปิด/ปิด

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

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

ภารกิจ 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 ไม่มี รายการที่ 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> กำหนดหลายตำแหน่งพร้อมกันไม่ได้ โดยจะมีได้เพียงรายการเดียวหรือไม่มีเลย

สุดท้าย ให้วางองค์ประกอบ <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;ภาษามาร์กอัป HyperText&quot;

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

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

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

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

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

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

ภาพหน้าจอของต้นไม้การช่วยเหลือพิเศษของ Chrome DevTools ที่ข้อความลิงก์ระบุว่า &quot;ด้านบน ว้าว เคล็ดลับเครื่องมือ&quot;

เพิ่มองค์ประกอบจำลองสำหรับโปรแกรมอ่านหน้าจอเท่านั้นลงใน <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 DevTools ซึ่งข้อความลิงก์มีวลีที่ปรับปรุงแล้ว &quot;ด้านบน ; มีเคล็ดลับเครื่องมือ: ว้าว เคล็ดลับเครื่องมือ&quot;

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

รูปแบบ

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

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

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

การรองรับเบราว์เซอร์

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

แหล่งที่มา

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

ไม่ต้องกังวลมากไปเกี่ยวกับการรองรับเบราว์เซอร์ ก่อนอื่น อย่าลืมว่าเคล็ดลับ เครื่องมือเหล่านี้เป็นส่วนเสริม หากไม่ได้ผลก็ไม่เป็นไร อย่างที่ 2 ในส่วน JavaScript เราจะทำให้สคริปต์ใช้งานได้ในหลากหลายฟังก์ชันสำหรับเบราว์เซอร์ที่ไม่รองรับ :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 สำหรับการจัดวางสิ่งต่างๆ ในหน้าต่างให้ดียิ่งขึ้น ในระหว่างนี้ เราจะสร้างคำแนะนำเครื่องมือ

มาเพิ่มความหลากหลายให้แนวทางของเราและเรียนรู้วิธีทั้งหมดในการสร้างเนื้อหาบนเว็บกัน

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

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

ยังไม่มีข้อมูลใดๆ

แหล่งข้อมูล