Προσπαθεί να ελέγξει εάν ένα στοιχείο είναι ορατό στον χρήστη

Πρόσφατα μετέφεραν ένα έργο κληρονομιάς σε μια νέα ζωή.

Ένα νέο έργο που καλύπτεται από δοκιμές και να κάνουμε τα πράγματα σωστά. Δηλαδή να πετάξει όλο το παλιό έργο στο χαντάκι.

Λοιπόν, πριν το πετάξω, έπρεπε να κάνω μια ανάλυση για να μάθω τις κύριες λειτουργίες, τις εκτεθειμένες λειτουργίες και πολλά άλλα.

Κατά τη διάρκεια της ανάλυσης βρήκα αυτή τη συνάρτηση:

Στην πράξη, αυτή η συνάρτηση θα επιστρέψει true εάν το στοιχείο που παρέχεται βρίσκεται στην τρέχουσα θύρα προβολής του χρήστη.

Είμαι βέβαιος ότι οι περισσότεροι προγραμματιστές frontend χρησιμοποίησαν αυτή τη λειτουργία και είναι παρούσα σε πολλά έργα frontend.

Μέσα στο έργο στο οποίο εργάζομαι, αυτή η λειτουργία είναι ένα σημαντικό μέρος της επιχειρηματικής λογικής και επειδή ο κώδικας που θα στείλω θα εκτελεστεί σε πολλούς ιστότοπους που δεν βρίσκονται υπό τον έλεγχό μου. Επομένως, πρέπει πραγματικά να μάθω αν το στοιχείο βρίσκεται στο παράθυρο προβολής, χωρίς ψευδώς θετικά.

Γιατί είναι ελλιπής;

Ως προγραμματιστές διεπαφής, γνωρίζουμε ότι δεν διαθέτουμε μόνο το στοιχείο HTML και τον κώδικα JavaScript που μπορούν να επηρεάσουν ορισμένες συμπεριφορές σε ένα πρόγραμμα περιήγησης.

Έτσι, όταν έγραψα κάποια δοκιμή για αυτήν τη συνάρτηση, άρχισα να σκέφτομαι: «Εάν το στοιχείο έχει εμφάνιση: καμία. Εφαρμόστηκε ο κανόνας στυλ; Εφαρμόστηκε ο κανόνας στυλ;;» και ούτω καθεξής…

Το δοκίμασα με ένα στοιχείο με εφαρμογή display: none; και η επιστροφή του ήταν πάντα true. 🤯

Έτσι, άρχισα να ψάχνω για κάποιους τρόπους απόκρυψης στοιχείων στο CSS και δοκίμασα τη συμπεριφορά της συνάρτησης που εμφανίστηκε πριν.

Όταν αυτοί οι κανόνες εφαρμόζονται στα στοιχεία που παρέχονται στην κλήση του isInViewport, το αποτέλεσμα δεν είναι αυτό που περίμενα, όπως είπα προηγουμένως με το display: none; η επιστροφή συνάρτησης είναι πάντα true.

Αυτή είναι μια λίστα με μερικές περιπτώσεις όπου η λειτουργία αποτυγχάνει:

  • height: 0;
  • opacity: 0;
  • display: none;
  • visibility: hidden;
  • clip-path: circle(0);
  • transform: scale(0);
  • Κρυφό χαρακτηριστικό HTML

Μπορεί να μην έχω καλύψει όλες τις περιπτώσεις, αλλά το να καλύπτω αυτές τις περιπτώσεις είναι καλύτερο από το να μην τις καλύπτω καθόλου.

Εντάξει, με αυτήν τη λίστα μπορούμε να βελτιώσουμε τη λειτουργία ως εξής:

Για να ελέγξουμε τους κανόνες CSS που εφαρμόζονται στο στοιχείο χρησιμοποιήσαμε το window.getComputedStyle() API. Αυτό το API "επιστρέφει ένα αντικείμενο που περιέχει τις τιμές όλων των ιδιοτήτων CSS ενός στοιχείου, μετά την εφαρμογή ενεργών φύλλων στυλ και την επίλυση οποιουδήποτε βασικού υπολογισμού μπορεί να περιέχουν αυτές οι τιμές."

Δεν είναι αρκετό

ποτέ δεν είναι αρκετό! Τώρα καλύψαμε ορισμένες περιπτώσεις που σχετίζονται άμεσα με το CSS.

Τι γίνεται όμως με position: absolute;; Ευτυχώς με position: absolute; αυτή η λειτουργία λειτουργεί καλά, αλλά όχι όταν υπάρχει επικάλυψη στοιχείου.

Πώς μπορεί να γίνει η επικάλυψη;

Η επικάλυψη μπορεί να γίνει με την ιδιότητα z-index που καθορίζει τη σειρά στοίβας ενός στοιχείου.

Ένα στοιχείο με μεγαλύτερη σειρά στοίβας βρίσκεται πάντα μπροστά από ένα στοιχείο με χαμηλότερη σειρά στοίβας.

Σε ορισμένους ιστότοπους με σύνθετη διεπαφή χρήστη, μπορεί να συμβεί ένα στοιχείο να επικαλύπτεται με ένα άλλο και για αυτήν την περίπτωση, μπορούμε να προσθέσουμε έναν άλλο έλεγχο ορατότητας στη συνάρτησή μας χρησιμοποιώντας τα Document.elementFromPoint() και Node.compareDocumentPosition().

Το Document.elementFromPoint()API επιστρέφει το ανώτερο στοιχείο στις καθορισμένες συντεταγμένες (σε σχέση με τη θύρα προβολής), με αποτέλεσμα να ελέγχουμε αν το επιστρεφόμενο στοιχείο είναι διαφορετικό, εάν όχι να ελέγξουμε το καθορισμένο z-index. Εάν το z-index δεν έχει καθοριστεί τότε θα ελέγξουμε τη θέση των στοιχείων. Με το Node.compareDocumentPosition() , κατανοούμε ποιο στοιχείο βλέπει ο χρήστης και καλύπτουμε τον ακόλουθο κανόνα: Εάν δύο τοποθετημένα στοιχεία αλληλοεπικαλύπτονται χωρίςz-index Καθορίζεται , το στοιχείο που βρίσκεται τελευταίο στον κώδικα HTML θα εμφανίζεται στην κορυφή.)

Σύνδεσμος Gist

Χρησιμοποιώντας το Intersection Observer

Σε ορισμένες περιπτώσεις όπου θέλετε να εκτελέσετε κάποιον κώδικα όταν το στοιχείο είναι ορατό επισυνάπτοντας τη συνάρτηση στο συμβάν κύλισης ή χρησιμοποιώντας έναν περιοδικό χρονοδιακόπτη, η καλύτερη επιλογή είναι ο Παρατηρητής τομής.

Στην πραγματικότητα, αυτό που μας λέει ο Παρατηρητής διασταύρωσης είναι η τομή με ένα στοιχείο, αλλά δεν μας λέει αν είναι ορατό στα μάτια του χρήστη. Αυτό ήταν πάντα ένα δύσκολο πράγμα που είναι πλέον εφικτό χάρη στη χρήση της έκδοσης 2 του Παρατηρητή Διασταύρωσης.

Για περισσότερες πληροφορίες σχετικά με αυτό, υπάρχει ένα ενδιαφέρον άρθρο εδώ.

Το μόνο ελάττωμα της έκδοσης 2 του IntersectionObserver είναι ότι δεν υποστηρίζεται ακόμη σε όλα τα προγράμματα περιήγησης. Σε αυτόν τον σύνδεσμο, μπορείτε να δείτε ποιο πρόγραμμα περιήγησης και η σχετική έκδοση το υποστηρίζει.

Έτσι στιγμιαία, για να ελέγξουμε αν τουλάχιστον ένα στοιχείο είναι πραγματικά ορατό στα μάτια του χρήστη, μπορούμε να διαχειριστούμε ορισμένες γωνιακές θήκες με παρόμοιο τρόπο με τον τρόπο που σας έδειξα παραπάνω. (Και πάλι, δεν έχω χειριστεί όλες τις πιθανές υποθέσεις, αλλά το να διαχειριστείς κάποιες από αυτές είναι καλύτερο από το να μην τις διαχειριστείς καθόλου).

συμπέρασμα

Αυτό είναι όλο! Τώρα κανένα στοιχείο στο DOM δεν θα ξεφύγει!

Όταν αναπτύσσουμε κάτι για προγράμματα περιήγησης και ειδικά όταν αποστέλλουμε κώδικα που εκτελείται σε ιστότοπους που δεν βρίσκονται υπό τον έλεγχό μας, πρέπει να σκεφτούμε ποιες είναι οι δυνατότητες που μπορεί να επηρεάσουν τη λειτουργικότητά μας.

Ευχαριστώ για την προσοχή! Θα σε δω μετά!

Πόροι