เอฟเฟกต์โฟกัสแกลเลอรี CSS แบบบริสุทธิ์ด้วย :not

โหนดต้นทาง: 1723238

บ่อยครั้งในอดีต ฉันต้องหาวิธีเพิ่มสไตล์ให้กับองค์ประกอบทั้งหมดภายในคอนเทนเนอร์ แต่ ไม่ โฉบหนึ่ง

การสาธิตผลกระทบ "จางหายไป" ที่คาดหวังในพี่น้องเพื่อให้ผู้ใช้ "มุ่งเน้น" ไปที่องค์ประกอบเฉพาะ

เอฟเฟกต์นี้ต้องเลือกพี่น้องขององค์ประกอบที่โฮเวอร์ ฉันเคยใช้ JavaScript สำหรับสิ่งนี้ เพิ่มหรือลบคลาสที่กำหนดกฎ CSS ที่เหมาะสมใน mouseenter และ mouseleave เหตุการณ์ที่คล้ายกันนี้:

แม้ว่าโค้ดจะใช้ได้ผล แต่ความรู้สึกในอุทรของฉันมักจะบอกฉันว่าต้องมีวิธี CSS บริสุทธิ์เพื่อให้ได้ผลลัพธ์แบบเดียวกัน เมื่อสองสามปีก่อน ขณะทำงานกับตัวเลื่อนบางตัวในบริษัทของฉัน ฉันคิดวิธีแก้ปัญหาที่คล้ายกับ Chris Geelhoed สร้างแอนิเมชั่นโฮมเพจ Netflix ที่มีชื่อเสียงอย่างไร และฉันเข้าใจว่าฉันไม่ต้องการ JavaScript สำหรับสิ่งนี้อีกต่อไป

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

โชคดีสำหรับฉัน ดูเหมือนว่าไม่ต้องเป็นแบบนี้ และอีกครั้งฉันไม่ต้องการ JavaScript สำหรับมัน

มาร์กอัปและฐาน CSS

มาเริ่มเขียนโค้ดโดยเตรียมมาร์กอัปที่เหมาะสมกัน:

  • .grid เป็นตารางตาม

      รายการ;

    • และ .grid__child องค์ประกอบคือ
    • เด็ก ๆ ที่เราต้องการโต้ตอบด้วย

    มาร์กอัปมีลักษณะดังนี้:

    สไตล์ควรมีลักษณะดังนี้:

    .grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, 15rem);
      grid-gap: 1rem;
    }
    
    .grid__child {
      background: rgba(0, 0, 0, .1);
      border-radius: .5rem;
      aspect-ratio: 1/1;
    }

    โค้ดตัวอย่างนี้จะสร้างรายการสามรายการที่มีสามคอลัมน์ในตาราง

    พลังของตัวเลือก CSS

    ตอนนี้ มาเพิ่มการโต้ตอบกัน แนวทางที่ฉันใช้ในตอนแรกนั้นขึ้นอยู่กับสองขั้นตอน:

    1. การวางเมาส์ไว้บนคอนเทนเนอร์ควรเปลี่ยนรูปแบบขององค์ประกอบทั้งหมดภายใน...  
    2. …ยกเว้นเคอร์เซอร์ที่เลื่อนอยู่ในขณะนี้

    เริ่มต้นด้วยการจับเด็กทุกคนในขณะที่เคอร์เซอร์วางเมาส์เหนือคอนเทนเนอร์:

    .grid:hover .grid__child {
      /* ... */
    }

    ประการที่สอง แยกรายการที่โฮเวอร์อยู่ในขณะนี้และลด opacity ของเด็กคนอื่น ๆ :

    .grid:hover .grid__child:not(:hover) {
      opacity: 0.3;
    }

    และนี่จะเพียงพอสำหรับคอนเทนเนอร์ที่ไม่มีช่องว่างระหว่างองค์ประกอบย่อย:

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

    อย่างไรก็ตาม ในกรณีของฉัน ฉันไม่สามารถลบช่องว่างเหล่านี้ได้:

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

    เมื่อฉันเลื่อนเมาส์ไปมาระหว่างแผ่นกระเบื้อง องค์ประกอบของลูกๆ ทั้งหมดก็ค่อยๆ จางลง

    ละเว้นช่องว่าง

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

    ใช่ เราทำได้ โดยใช้ pointer-events: none บน .grid ภาชนะแล้วนำกลับมาด้วย pointer-events: auto เกี่ยวกับลูก ๆ ของมัน:

    .grid {
      /* ... */
      pointer-events: none;
    }
    
    /* ... */
    
    .grid__child {
      /* ... */
      pointer-events: auto;
    }

    มาเพิ่มทรานซิชันเจ๋งๆ บน opacity และเรามีส่วนประกอบพร้อมแล้ว:

    มันอาจจะเจ๋งกว่านี้ด้วยซ้ำเมื่อเราเพิ่มไทล์และสร้างเลย์เอาต์ 2 มิติ:

    CSS สุดท้ายมีลักษณะดังนี้:

    .grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, 15rem);
      grid-gap: 3rem;
      pointer-events: none;
    }
    
    .grid:hover .grid__child:not(:hover) {
      opacity: 0.3;
    }
    
    .grid__child {
      background: rgba(0, 0, 0, .1);
      border-radius: .5rem;
      aspect-ratio: 1/1;
      pointer-events: auto;
      transition: opacity 300ms;
    }

    ด้วยโค้ดเพิ่มเติมเพียง 2 บรรทัด เราเอาชนะปัญหาช่องว่างได้!

    ปัญหาที่เป็นไปได้

    แม้ว่าจะเป็นโซลูชันขนาดกะทัดรัด แต่ก็มีบางสถานการณ์ที่อาจต้องใช้วิธีแก้ไขปัญหาชั่วคราว

    น่าเสียดาย เคล็ดลับนี้ใช้ไม่ได้เมื่อคุณต้องการให้คอนเทนเนอร์เลื่อนได้ เช่น ในแถบเลื่อนแนวนอนบางประเภท ดิ pointer-events: none สไตล์จะไม่สนใจเหตุการณ์โฮเวอร์เท่านั้นแต่จะไม่สนใจเหตุการณ์อื่นๆ ทั้งหมดด้วย ในสถานการณ์เช่นนี้ คุณสามารถห่อ .grid ในคอนเทนเนอร์อื่นดังนี้:

    สรุป

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

    ฉันหวังว่าคุณจะชอบบทแนะนำสั้นๆ นี้และพบว่ามีประโยชน์ ขอบคุณ!

    ผู้เขียนเลือก เทคโนโลยี การศึกษา เพื่อรับเงินบริจาคเป็นส่วนหนึ่งของ เขียนเพื่อบริจาค โครงการ

    ประทับเวลา:

    เพิ่มเติมจาก เคล็ดลับ CSS