กรณีศึกษา :has()

Swetha Gopalakrishnan
Swetha Gopalakrishnan
Saurabh Rajpal
Saurabh Rajpal

CSS มีชื่อเสียงว่าไม่มีวิธีเลือกองค์ประกอบหลักโดยตรงตามองค์ประกอบย่อย ซึ่งเป็นสิ่งที่นักพัฒนาแอปต้องการมาหลายปีแล้ว ตัวเลือก :has() ที่เบราว์เซอร์หลักทั้งหมดรองรับในตอนนี้จะช่วยแก้ปัญหานี้ได้ ก่อนหน้านี้ :has()คุณมักจะใช้เชนตัวเลือกแบบยาวหรือเพิ่มคลาสสำหรับฮุกการจัดสไตล์ ตอนนี้คุณจัดสไตล์ตามความสัมพันธ์ขององค์ประกอบกับองค์ประกอบที่สืบทอดได้แล้ว อ่านเพิ่มเติมเกี่ยวกับตัวเลือก :has() ใน CSS Wrapped 2023 และ 5 ข้อมูลโค้ด CSS ที่นักพัฒนาซอฟต์แวร์ฝั่งหน้าทุกคนควรทราบ

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

:has() เป็นส่วนหนึ่งของเกณฑ์พื้นฐานที่กลับมาเปิดให้จองอีกครั้ง

Browser Support

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

Source

ดูชุดบทความฉบับเต็มที่บทความนี้เป็นส่วนหนึ่งของบทความที่กล่าวถึงวิธีที่บริษัทอีคอมเมิร์ซปรับปรุงเว็บไซต์โดยใช้ฟีเจอร์ CSS และ UI ใหม่

Policybazaar

ตัวเลือก :has() ช่วยให้เรากำจัดการตรวจสอบที่อิงตาม JavaScript ของการเลือกของผู้ใช้ และแทนที่ด้วยโซลูชัน CSS ที่ทำงานได้อย่างราบรื่นและมอบประสบการณ์การใช้งานแบบเดิม — Aman Soni หัวหน้าทีมเทคโนโลยีของ Policybazaar

ทีมการลงทุนของ Policybazaar ใช้ตัวเลือก :has() อย่างชาญฉลาดเพื่อให้ผู้ใช้ที่เปรียบเทียบแผนเห็นภาพได้ชัดเจน รูปภาพต่อไปนี้แสดงแผน 2 ประเภทใน UI การเปรียบเทียบ (สีเหลืองและสีน้ำเงิน) แผนแต่ละแผนจะเปรียบเทียบได้กับแผนประเภทเดียวกันเท่านั้น เมื่อใช้ :has() เมื่อผู้ใช้เลือกแผนประเภทหนึ่ง ผู้ใช้จะเลือกแผนประเภทอื่นไม่ได้

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

รหัส

:has() ช่วยให้คุณเข้าถึงองค์ประกอบหลักของสไตล์และองค์ประกอบย่อยขององค์ประกอบหลักได้ โค้ดต่อไปนี้จะตรวจสอบว่าคอนเทนเนอร์หลักมีการตั้งค่าคลาส .disabled-group หรือไม่ หากเป็นเช่นนั้น การ์ดจะเป็นสีเทา และปุ่ม "เพิ่ม" จะไม่สามารถตอบสนองต่อการคลิกโดยการตั้งค่า pointer-events เป็น none

.plan-group-container:has(.disabled-group) {   opacity: 0.5;   filter: grayscale(100%); }  .plan-group-container:has(.disabled-section) .button {   pointer-events: none;   border-color: #B5B5B5;   color: var(--text-primary-38-color);   background: var(--input-border-color); } 

ทีมสุขภาพของ Policybazaar ใช้ Use Case ที่แตกต่างออกไปเล็กน้อย โดยจะมีแบบทดสอบย่อยในบทเรียนสำหรับผู้ใช้ และใช้ :has() เพื่อตรวจสอบสถานะช่องทำเครื่องหมายของคำถามเพื่อดูว่าผู้ใช้ตอบคำถามแล้วหรือยัง หากมี ระบบจะใช้ภาพเคลื่อนไหวเพื่อเปลี่ยนไปยังคำถามถัดไป

health.policybazaar.com/

รหัส

ในตัวอย่างการเปรียบเทียบแผน มีการใช้ :has() เพื่อตรวจสอบว่ามีคลาสหรือไม่ นอกจากนี้ คุณยังตรวจสอบสถานะขององค์ประกอบอินพุต เช่น ช่องทําเครื่องหมาย โดยใช้ :has(input:checked) ได้ด้วย ในภาพแสดงแบบทดสอบ แต่ละคำถามในแบนเนอร์สีม่วงจะเป็นช่องทำเครื่องหมาย Policybazaar จะตรวจสอบว่าตอบคำถามแล้วโดยใช้ :has(input:checked) หรือไม่ หากตอบแล้ว ระบบจะเรียกใช้ภาพเคลื่อนไหวโดยใช้ animation: quesSlideOut 0.3s 0.3s linear forwards เพื่อเลื่อนไปยังคำถามถัดไป ดูวิธีการทํางานในโค้ดต่อไปนี้

.segment_banner__wrap__questions {  position: relative;  animation: quesSlideIn 0.3s linear forwards; }  .segment_banner__wrap__questions:has(input:checked) {  animation: quesSlideOut 0.3s 0.3s linear forwards; }   @keyframes quesSlideIn {  from {    transform: translateX(50px);    opacity: 0;  }  to {    transform: translateX(0px);    opacity: 1;  } }  @keyframes quesSlideOut {  from {    transform: translateX(0px);    opacity: 1;  }  to {    transform: translateX(-50px);    opacity: 0;  } } 

Tokopedia

Tokopedia ใช้ :has() เพื่อสร้างรูปภาพวางซ้อนหากภาพปกผลิตภัณฑ์มีวิดีโอ หากภาพขนาดย่อของผลิตภัณฑ์มีคลาส .playIcon ระบบจะเพิ่มการวางซ้อน CSS ที่นี่ มีการใช้ตัวเลือก :has() ร่วมกับตัวเลือกการฝัง & ภายในคลาส .thumbnailWrapper หลักที่มีผลกับภาพปกทั้งหมด วิธีนี้ช่วยให้ CSS เป็นแบบโมดูลและอ่านได้ง่ายขึ้น

ภาพหน้าจอของหน้า Tokopedia ก่อนและหลังการใช้ตัวเลือก has
ก่อนและหลังใช้ :has()

รหัส

โค้ดต่อไปนี้ใช้ตัวเลือกและคอมบิเนเตอร์ CSS (& และ >) และการฝังด้วย :has() เพื่อจัดสไตล์ภาพขนาดย่อ สําหรับเบราว์เซอร์ที่ไม่รองรับ ระบบจะใช้กฎคลาส CSS เพิ่มเติมปกติเป็นทางเลือก ระบบจะใช้กฎ @supports selector(:has(*)) เพื่อตรวจสอบการรองรับเบราว์เซอร์ด้วย ดังนั้น ประสบการณ์โดยรวมจึงเหมือนกันในทุกเวอร์ชันของเบราว์เซอร์

export const thumbnailWrapper = css`   padding: 0;   margin-right: 7px;   border: none;   outline: none;   background: transparent;    > div {     width: 64px;     height: 64px;     overflow: hidden;     cursor: pointer;     border-color: ;     position: relative;     border: 2px solid ${NN0};     border-radius: 8px;     transition: border-color 0.25s;      &.active {       border-color: ${GN500};     }      @supports selector(:has(*)) {       &:has(.playIcon) {         &::after {           content: '';           display: block;           background: rgba(0, 0, 0, 0.2);           position: absolute;           top: 0;           left: 0;           right: 0;           bottom: 0;         }       }     }      & > .playIcon {       position: absolute;       top: 25%;       left: 25%;       width: 50%;       height: 50%;       text-align: center;       z-index: 1;     }   } `; 

สิ่งที่ควรพิจารณาเมื่อใช้ :has()

รวม :has() เข้ากับตัวเลือกอื่นๆ เพื่อสร้างเงื่อนไขที่ซับซ้อนมากขึ้น ดูตัวอย่างได้ใน has() ตัวเลือกครอบครัว

แหล่งข้อมูล

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