เป็นที่รู้กันว่า CSS ยังไม่มีวิธีเลือกองค์ประกอบระดับบนสุดโดยตรงโดยอิงตามองค์ประกอบย่อย นี่เป็นคำขอยอดนิยมจากนักพัฒนาแอปมาหลายปีแล้ว ซึ่งปัจจุบันเบราว์เซอร์หลักทั้งหมดรองรับตัวเลือก :has()
จะช่วยแก้ปัญหานี้ได้ ก่อน :has()
คุณมักเชื่อมโยงตัวเลือกแบบยาวหรือเพิ่มคลาสสำหรับตะขอการจัดรูปแบบ ตอนนี้คุณจัดรูปแบบตามความสัมพันธ์ขององค์ประกอบกับองค์ประกอบสืบทอดได้แล้ว อ่านเพิ่มเติมเกี่ยวกับตัวเลือก :has()
ใน CSS Wrapped 2023 และข้อมูลโค้ด CSS 5 รายการที่นักพัฒนาซอฟต์แวร์ฟรอนท์เอนด์ควรรู้จัก
แม้ว่าตัวเลือกนี้จะดูเหมือนไม่มาก แต่ก็เปิดใช้กรณีการใช้งานได้จำนวนมาก
บทความนี้แสดงกรณีการใช้งานบางอย่างที่บริษัทอีคอมเมิร์ซปลดล็อกด้วยตัวเลือก :has()
:has()
เป็นส่วนหนึ่งของเกณฑ์พื้นฐาน "พร้อมใช้งานใหม่"
อ่านข้อมูลในซีรีส์ฉบับเต็มในบทความนี้ ซึ่งจะอธิบายวิธีที่บริษัทอีคอมเมิร์ซเพิ่มประสิทธิภาพเว็บไซต์โดยใช้ฟีเจอร์ CSS และ UI ใหม่
นโยบายบาซาร์
การใช้ตัวเลือก
: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 ใช้ :has()
เพื่อสร้างภาพวางซ้อนหากภาพขนาดย่อของผลิตภัณฑ์มีวิดีโอ หากภาพปกของผลิตภัณฑ์มีคลาส .playIcon
ระบบจะเพิ่มการวางซ้อน CSS ในตัวอย่างนี้ ตัวเลือก :has() จะใช้ร่วมกับตัวเลือกการซ้อน &
ภายในคลาส .thumbnailWrapper
ที่ครอบคลุม ซึ่งจะมีผลกับภาพขนาดย่อทั้งหมด วิธีนี้จะสร้าง CSS ที่แบ่งเป็นส่วนๆ และอ่านได้ง่ายขึ้น
![ภาพหน้าจอของหน้า Tokopedia ก่อนและหลังการใช้ตัวเลือก "มี"](https://developer.chrome.com/static/blog/css-ui-ecommerce-has/image/has-before-after.png?authuser=5&hl=th)
: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 ในปี 2023
- :has(): ตัวเลือกครอบครัว
- การสาธิต :has()
- คุณต้องการรายงานข้อบกพร่องหรือขอฟีเจอร์ใหม่ เราอยากฟังความคิดเห็นจากคุณ
สำรวจบทความอื่นๆ ในชุดนี้ซึ่งพูดถึงวิธีที่บริษัทอีคอมเมิร์ซได้รับประโยชน์จากการใช้ฟีเจอร์ CSS และ UI ใหม่ เช่น ภาพเคลื่อนไหวที่มาจากการเลื่อน การเปลี่ยนดู การเปิดดู และการค้นหาคอนเทนเนอร์