CSS ขึ้นชื่อว่าไม่มีวิธีเลือกองค์ประกอบระดับบนสุดโดยตรงตามองค์ประกอบระดับล่าง ซึ่งเป็นคำขอที่นักพัฒนาซอฟต์แวร์ขอมามากที่สุดเป็นเวลาหลายปี ตัวเลือก :has() ซึ่งตอนนี้เบราว์เซอร์หลักทั้งหมดรองรับแล้วจะช่วยแก้ปัญหานี้ได้ ก่อนที่จะมี :has() คุณมักจะต้องเชื่อมโยงตัวเลือกยาวๆ หรือเพิ่มคลาสสำหรับฮุกการจัดรูปแบบ ตอนนี้คุณสามารถจัดรูปแบบตามความสัมพันธ์ขององค์ประกอบกับองค์ประกอบที่สืบทอดมาได้แล้ว อ่านเพิ่มเติม
เกี่ยวกับตัวเลือก :has() ใน
CSS Wrapped 2023 และ
5 CSS Snippets Every Frontend Developer Should Know
แม้ว่าตัวเลือกนี้จะดูเล็กน้อย แต่ก็ช่วยให้เกิดกรณีการใช้งานจำนวนมากได้
บทความนี้แสดงกรณีการใช้งานบางส่วนที่บริษัทอีคอมเมิร์ซใช้ประโยชน์จากตัวเลือก :has()
ดูซีรีส์ฉบับเต็มที่บทความนี้เป็นส่วนหนึ่ง ซึ่งจะพูดถึงวิธีที่ บริษัทอีคอมเมิร์ซปรับปรุงเว็บไซต์โดยใช้ฟีเจอร์ CSS และ UI ใหม่
Policybazaar
ตัวเลือก
:has()ช่วยให้เราไม่ต้องใช้การตรวจสอบการเลือกของผู้ใช้ด้วย JavaScript และแทนที่ด้วยโซลูชัน CSS ซึ่งทำงานได้อย่างราบรื่น และให้ประสบการณ์การใช้งานแบบเดิม—Aman Soni, Tech Lead, 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 ใช้กรณีการใช้งานที่แตกต่างออกไปเล็กน้อย
ทีมนี้มีแบบทดสอบแบบอินไลน์สำหรับผู้ใช้และใช้ :has() เพื่อตรวจสอบสถานะช่องทำเครื่องหมายของคำถามเพื่อดูว่ามีการตอบคำถามหรือไม่ หากมีการตอบคำถาม ระบบจะใช้ภาพเคลื่อนไหวเพื่อเปลี่ยนไปแสดงคำถามถัดไป
รหัส
ในตัวอย่างการเปรียบเทียบแพ็กเกจ มีการใช้ :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 ที่เป็นโมดูลาร์และอ่านง่ายขึ้น
: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() the family selector
แหล่งข้อมูล
- CSS Wrapped 2023
- :has(): the family selector
- Demos :has()
- ต้องการรายงานข้อบกพร่องหรือขอฟีเจอร์ใหม่ไหม เราอยากรับฟังความคิดเห็นจากคุณ
สำรวจบทความอื่นๆ ในซีรีส์นี้ซึ่งพูดถึงวิธีที่บริษัทอีคอมเมิร์ซได้รับประโยชน์จากการใช้ฟีเจอร์ CSS และ UI ใหม่ๆ เช่น ภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อน การเปลี่ยนมุมมอง ป๊อปโอเวอร์ และการค้นหาคอนเทนเนอร์