Empreinte getClientRects : cohérence DOMRect
Interpréter les contrôles DOMRect de CreepJS sans confondre géométrie vide, texte fragmenté ou rapport absent avec une identité matérielle.
BotBrowser Team
Vous voulez la documentation structurée pour Empreinte ?
Cet article fait partie de la bibliothèque éditoriale. Pour les étapes de configuration, la référence et les mises à jour continues, passez directement à la section docs.
L'empreinte getClientRects concerne la géométrie de mise en page, pas les en-têtes Client Hints. Un rectangle peut changer parce que la boîte sélectionnée, le fragment de texte ou le contexte des coordonnées change. BotBrowser documente un bruit déterministe ClientRects, désactivé par défaut, et une graine pour reproduire les métriques des polices ; cela ne garantit pas l'accord de toutes les méthodes géométriques ni l'acceptation par CreepJS. Un rapport DOMRect utile distingue l'objet mesuré, l'API et le prédicat exact avant d'attribuer une cause.
Voir la vidéo
Cette vidéo en anglais suit la même question que l'article : les quatre appels géométriques de CSSOM View renvoient des formes différentes, donc un nombre de fragments, un rectangle englobant et une sélection ne peuvent pas se lire comme une seule valeur. Elle montre les trois états du rapport (absent, liste vide et rectangle de dimension nulle), les trois sorties de la réduction englobante, et deux sessions de console enregistrées sur une fixture contrôlée de même origine : deux expressions natives saisies à la main, le panneau de la fixture imprimant la troisième lecture. Elle ne montre ni collecte par un site ni verdict tiers, et une différence géométrique n'identifie ni appareil, ni personne, ni mécanisme de modification. L'audio est en anglais.
TL;DR
Element.getClientRects()renvoie une liste de fragments de boîte ;getBoundingClientRect()la réduit à un rectangle, avec des cas distincts pour une liste vide et des dimensions nulles. Longueur de liste et dimensions répondent à des questions différentes.- La géométrie de
Rangepeut décrire des fragments de texte sélectionné, pas nécessairement toute la boîte de bordure d'un élément. - La révision CreepJS
10aa6724cd33a1015db1574211890518cd04f0ccconserve quatre tableaux géométriques et applique plusieurs contrôles propres à ses éléments de test, pas un test universel d'identité. - Rapport DOMRect absent, liste de fragments vide et rectangle contenant des zéros sont des états distincts.
liedreprésente l'évaluation de cohérence de cette révision. Il ne prouve ni l'auteur d'une modification, ni l'identité d'un appareil, ni la décision d'un site externe.
Contents
- Voir la vidéo
- Quatre surfaces géométriques
- Les comparaisons de la révision CreepJS
- Les changements de disposition
- Matrice des états DOMRect
- Un relevé de comparaison limité
- Questions fréquentes sur ClientRects
- Conclusion pratique
Quatre surfaces géométriques
CSSOM View définit Element.getClientRects() à partir des boîtes CSS d'un élément. Un élément en ligne réparti sur plusieurs lignes peut produire plusieurs fragments, plutôt qu'un rectangle continu. La liste conserve leur séparation, y compris les fragments de taille nulle. Sans boîte CSS associée, l'élément produit une liste vide. « La valeur ClientRects » manque donc de précision : il peut s'agir d'une liste, d'un membre choisi, d'une union dérivée ou d'une empreinte condensée de plusieurs éléments de test.
Element.getBoundingClientRect() réduit la géométrie à un rectangle. La spécification distingue une liste vide, une liste dont tous les rectangles ont une largeur ou une hauteur nulle, puis le cas restant d'union. Le premier renvoie un rectangle à zéro ; le deuxième renvoie le premier rectangle. Sinon, l'union inclut les rectangles dont la hauteur ou la largeur n'est pas nulle : la condition utilise OR. Cette dernière branche n'efface pas les exceptions précédentes. Un rectangle placé ailleurs qu'à l'origine, de hauteur nulle, n'équivaut pas à l'absence de fragments.
MDN décrit le rectangle de l'élément comme incluant les espacements internes et la bordure, avec des coordonnées relatives à la zone visible. Comparer ce résultat à width: 100px exige de tenir compte du modèle de boîte, sans supposer que toute largeur renvoyée égale la déclaration CSS. Largeur du contenu et boîte de bordure sont différentes. Un rapport ne gardant qu'une largeur arrondie perd le choix d'API et le modèle de boîte.
Range.getClientRects() concerne une portion sélectionnée du document. La méthode englobante correspondante réduit sa liste en distinguant aussi les cas vide, à dimensions nulles et d'union. Une sous-chaîne sélectionnée n'a pas nécessairement les limites de son élément conteneur : l'une décrit le texte choisi, l'autre peut inclure toute la boîte. L'analyse des mesures de texte traite la surface distincte Canvas measureText() ; les champs TextMetrics ne sont pas des listes de fragments DOMRect.
| API | Forme renvoyée | Comparaison respectant sa signification |
|---|---|---|
Element.getClientRects() | DOMRectList de fragments de boîte | Même élément et mêmes positions de fragments |
Element.getBoundingClientRect() | Un DOMRect issu de l'algorithme englobant | Même élément et même contexte de zone visible |
Range.getClientRects() | Liste pour la sélection | Conserver les limites de sélection et la disposition |
Range.getBoundingClientRect() | Un rectangle obtenu par réduction de la liste | Conserver la sélection et les branches vide et à dimensions nulles |
Les interfaces exposent x, y, width, height, top, right, bottom et left. Sérialiser ces champs ne rend pas leurs objets d'origine équivalents. MDN distingue également l'interface de liste en lecture seule d'un tableau JavaScript. Convertir la liste en tableau modifie le conteneur, pas l'opération de disposition ayant produit les entrées. Une empreinte condensée de ce tableau n'explique pas, à elle seule, un fragment différent.
Les comparaisons de la révision CreepJS
Le module DOMRect public copie les huit champs dans des objets simples et renvoie quatre tableaux : elementClientRects, elementBoundingClientRect, rangeClientRects et rangeBoundingClientRect. Pour les deux API de liste, la collecte lit le premier membre, pas tous les rectangles d'une page multiligne quelconque. Ce choix compte : une empreinte condensée du groupe ne prouve pas que tous les fragments de tous les éléments ont été examinés.
Le module comporte une fonction choisissant le rectangle préféré parmi liste de l'élément, rectangle englobant de l'élément, liste de la sélection et rectangle englobant de la sélection, selon les problèmes d'API déjà enregistrés. Cette fonction est distincte de la collecte des quatre tableaux. Affirmer que « CreepJS utilise toujours le rectangle englobant » supprimerait ces branches. Leurs alternatives ne signifient pas non plus que les quatre API doivent produire des rectangles identiques pour toute sélection.
Le contrôle de déplacement relève le top initial, applique une classe de déplacement, relève la position décalée, retire la classe puis mesure à nouveau. Il compare la restauration par rapport à cette mesure décalée. Il n'impose pas qu'un rectangle reste inchangé après une modification de disposition. Un échec de restauration et une position initiale différente sont deux comparaisons ; « la position a changé » ne les distingue pas.
Le contrôle arithmétique examine les relations entre côtés opposés, dimensions et origine des rectangles d'élément. Un autre contrôle compare les côtés gauche et droit de deux éléments précis censés correspondre. Les prédicats sont différents : l'arithmétique interne peut être cohérente alors que les deux éléments diffèrent. L'analyse des groupes CreepJS explique pourquoi une évaluation de groupe doit conserver son périmètre, sans devenir une affirmation sur une personne ou toutes les API.
| Contrôle défini par le code | Comparaison | Ce qu'un échec ne prouve pas seul |
|---|---|---|
| Déplacement et restauration | Positions initiale, décalée et restaurée | La cause de l'écart |
| Arithmétique du rectangle | Relations entre côtés, origine et dimensions | La couche logicielle ayant fourni la valeur |
| Éléments égaux | Côtés choisis de deux éléments précis | L'égalité d'éléments arbitraires |
| Élément tourné | Attente du code conditionnée par moteur et DPR | Une signature universelle de géométrie |
| Élément fantôme | Si les huit champs relevés sont tous nuls | Que tout élément invisible doit avoir une géométrie nulle |
La branche de rotation dépend du classement du moteur et, dans une branche, de devicePixelRatio. Les valeurs attendues sont des hypothèses d'implémentation, pas une table normative de conformité. Copier une empreinte condensée connue n'apporte ni le rectangle sous-jacent ni la preuve d'une mesure de la disposition originale. La conclusion justifiée est que cette révision compare un élément de test à une attente limitée, pas qu'un écart prouve un système d'exploitation.
lied peut aussi commencer avec des réserves déjà enregistrées concernant les quatre API géométriques ou String.fromCodePoint, avant les contrôles locaux. Un résultat final vrai n'identifie donc pas le premier prédicat responsable. Le module intercepte les erreurs, enregistre un test échoué et ne renvoie aucun résultat ; l'affichage prévoit séparément un état bloqué quand le rapport manque. Ce cas diffère d'un tableau correctement collecté contenant des zéros. Aucune exécution de CreepJS n'est revendiquée.
Les changements de disposition
Les coordonnées relatives à la zone visible changent quand le contenu se déplace par rapport à elle. MDN mentionne explicitement le défilement pour getBoundingClientRect(). Comparer avant et après un défilement modifie une entrée, même si la largeur CSS ne change pas. Ajouter les décalages peut servir à calculer des coordonnées du document, mais il faut identifier cette valeur dérivée au lieu de la comparer silencieusement à la coordonnée initiale.
Le retour à la ligne modifie les fragments. Un même texte peut avoir un DOMRectList.length différent dans une colonne étroite et dans une colonne large. Le rectangle englobant résume ces fragments et peut inclure de l'espace qu'aucune ligne n'occupe. Comparer uniquement ce rectangle masque parfois une fragmentation différente ; ne lire que le premier fragment ignore les suivants. Aucun de ces cas ne démontre un remplacement de police.
Les transformations CSS affectent la géométrie. Un élément tourné doit être comparé à rotation et origine de référence identiques, pas à ses dimensions CSS sans rotation. Le rectangle englobant n'est pas le tracé du polygone visible. Une branche de détection consacrée à la rotation exige donc son propre contexte. La largeur mesurée n'est pas la longueur d'un côté tourné sans calcul géométrique supplémentaire.
Une sélection Range ajoute une entrée : les nœuds ou positions de texte choisis. Passer d'un élément entier à une sous-chaîne peut changer légitimement la liste du Range tout en laissant la boîte de l'élément intacte. CSSOM View traite aussi différemment le texte et les boîtes sélectionnés. Nommer Range.getClientRects() sans conserver la sélection ne permet pas une comparaison précise de deux captures de « la même page ».
Les polices appartiennent au contexte de disposition, mais une variation de rectangle n'est pas une recherche de nom de police. Disponibilité des polices, remplacement, texte, largeur du conteneur et styles peuvent tous compter. La documentation des mesures de polices décrit les contrôles ClientRects ; elle ne fournit pas un DOMRect de référence pour chaque texte, sélection ou disposition. La graine rend reproductible le bruit documenté, pas toutes les variations de mise en page.
Le contrôle fantôme reste lié à son élément de test. « Invisible pour une personne » recouvre plusieurs états de rendu et ne définit pas un modèle de boîte CSS unique. Un élément hors écran peut participer à la disposition ; un élément sans boîte associée suit un autre chemin. Généraliser ce contrôle à toute invisibilité remplacerait la condition concrète du code par une affirmation plus large non étayée.
Matrice des états DOMRect
La première question est de savoir si une géométrie a été obtenue. Exception du collecteur, liste vide et rectangle de taille nulle exigent des états différents. Remplacer tout échec par un rectangle à zéro efface cette différence et peut donner l'impression qu'un contrôle a examiné des données jamais collectées. Un null choisi par l'application n'est pas non plus un résultat natif DOMRectList.
| État observé | Interprétation limitée | Entrée suivante à comparer |
|---|---|---|
| Aucun rapport | Rapport absent, cause non établie | Phase de collecte et catégorie d'erreur disponible |
Liste avec length === 0 | Aucun fragment renvoyé par cet appel | Boîte associée ou contexte de sélection |
| Largeur ou hauteur nulle | Géométrie présente avec une dimension dégénérée | API, position et autre dimension |
| Longueur de liste différente | Structure de fragments différente | Texte, largeur, sélection et instant de disposition identiques |
| Échec arithmétique | Les champs ne respectent pas ce prédicat | Champs originaux et nom du prédicat |
| Seule l'empreinte du groupe change | Une entrée sérialisée diffère | Tableau, élément et champs avant attribution |
Ces cas proviennent des sources, pas d'observations mesurées. Par exemple, une liste hypothétiquement vide suivie d'un rectangle à zéro peut respecter la réduction prévue. Ce n'est pas une preuve de modification détectée. Un rapport affirmant une lecture réussie sans conserver la longueur ne distingue pas non plus ce cas d'une valeur absente ajoutée par son propre sérialiseur.
Un deuxième exemple hypothétique est un texte multiligne produisant davantage de fragments quand le conteneur rétrécit. Le constat utile est une entrée de disposition modifiée et une fragmentation différente. Aucune dimension précise ni identité d'appareil n'est prédite. Dans un troisième cas, l'élément reste fixe mais la sous-chaîne choisie change : le Range varie alors qu'une comparaison de l'élément peut rester stable. Chaque cas conserve la question réellement posée à l'API.
Un quatrième cas est une évaluation CreepJS privée de son motif individuel. lied ne permet pas de choisir entre réserves héritées sur la géométrie ou String.fromCodePoint, échec de restauration, échec arithmétique et attente propre à un élément. Le motif diagnostique nommé est plus informatif qu'une cause supposée attachée au booléen. Cela n'exige ni tous les rectangles d'une page ni l'exportation d'une empreinte réutilisable à un tiers.
Un relevé de comparaison limité
Un relevé minimal peut répondre sans conserver tout le texte de la page ni chaque valeur géométrique. Garder api, un identifiant non sensible de l'élément de test, le type de sélection, la longueur de liste si applicable, l'état de collecte et le prédicat nommé. Ajouter la révision du code pour CreepJS. Un contrôle n'est pas « standard » parce que la méthode de mesure est normalisée : algorithme d'API et attentes du détecteur constituent deux couches distinctes.
| Champ | Effet sur l'interprétation |
|---|---|
api | Sépare Element/Range et liste/rectangle |
selectionType | Distingue élément et sous-chaîne |
fragmentCount | Conserve les états vide et fragmenté |
coordinateSpace | Identifie coordonnées de zone visible ou conversion dérivée |
layoutContext | Nomme largeur, défilement et rotations pertinents |
collectionState | Distingue collecte réussie, vide et échouée |
rule et sourceRevision | Rattachent l'évaluation au prédicat et au code réels |
Ces noms forment un schéma proposé pour l'assistance, pas les clés de sortie CreepJS, sauf les tableaux explicitement nommés. Il ne faut pas noter fragmentCount: 0 si la collecte a échoué avant l'obtention d'une liste. Remplacer une évaluation absente par une chaîne vide ferait aussi croire à une comparaison exécutée sans résultat défavorable. Minimiser les données et représenter correctement les états servent le même diagnostic.
Le réglage documenté --bot-noise-client-rects=true active le bruit déterministe et reste désactivé par défaut. --bot-noise-seed est documenté pour reproduire les métriques des polices. Cela ne prouve ni une couverture identique d'Element et Range, ni le maintien de toutes les attentes arithmétiques d'un détecteur, ni l'anonymat, ni l'acceptation par un service. Ces résultats demanderaient leurs propres preuves. --bot-noise-text-rects=true est un autre contrôle, pas un substitut implicite au réglage ClientRects.
La séquence utile consiste à identifier API et état, vérifier sélection et entrées de disposition, puis examiner le prédicat nommé. Si ces entrées manquent, seul un écart géométrique inexpliqué subsiste. Lui attribuer système d'exploitation, modèle d'appareil ou mécanisme dépasserait le relevé. Le suivi minimal reproduit l'élément précis, sans élargir la collecte à d'autres signaux d'identité.
Questions fréquentes sur ClientRects
ClientRects désigne-t-il Client Hints ?
Non. getClientRects() est géométrique. Client Hints transmet des informations du navigateur par un autre mécanisme. Un en-tête ne prouve rien sur la disposition d'un élément et un rapport DOMRect n'établit pas les en-têtes envoyés.
Une empreinte condensée différente localise-t-elle le rectangle ?
Non. Elle résume des entrées sérialisées. Sans tableau, élément et champs sous-jacents, elle ne localise pas l'écart. Elle justifie l'examen du groupe, pas une attribution indépendante de l'entrée changée ou de sa cause.
Element et Range doivent-ils toujours correspondre ?
Non. Une boîte et une sélection textuelle peuvent couvrir des contenus différents. Une correspondance propre à un élément de test ne garantit rien pour une sélection arbitraire, un texte multiligne ou des boîtes tournées.
Un rectangle à zéro prouve-t-il un blocage ?
Non. La réduction d'une liste vide peut le produire ; les boîtes dégénérées constituent un autre état. L'affichage d'un rapport absent par CreepJS est séparé. Il faut conserver si l'appel a produit liste, rectangle ou aucun rapport.
L'attente du test de rotation est-elle une norme web ?
Non. Le code fixé utilise une branche conditionnée par moteur et DPR. CSSOM View définit les méthodes, pas les empreintes attendues du détecteur. Une révision ultérieure peut modifier cette branche sans renommer l'API.
Une graine garantit-elle un résultat identique partout ?
Non. La graine documentée concerne le bruit reproductible. Texte, largeur, sélection, transformations ou coordonnées différents changent toujours la question géométrique. Le réglage seul ne prouve ni équivalence entre appareils ni résultat du détecteur.
Sources
- CSSOM View : géométrie des éléments et sélections
- MDN : Element.getClientRects()
- MDN : Element.getBoundingClientRect()
- MDN : Range.getClientRects()
- MDN : Range.getBoundingClientRect()
- MDN : DOMRect
- MDN : DOMRectList
- CreepJS : module DOMRect fixé
- BotBrowser : contrôles des mesures de polices
Conclusion pratique
Un rapport utile d'empreinte getClientRects identifie une API, un objet choisi et une comparaison précise. Conserver les états vide, dégénéré et échoué ; séparer les prédicats CreepJS de la géométrie normalisée. Si seuls une empreinte condensée ou un booléen restent, la cause n'est pas résolue. Vérifier le contexte d'API ou de l'élément avant de modifier un réglage ou d'attribuer une identité matérielle.
Cet article fait partie du guide : Qu'est-ce qu'une empreinte de navigateur ?
Articles Connexes
Fingerprinting par mesure de texte : suivi sous-pixel
EmpreinteLire les signaux d’empreinte du navigateur
EmpreinteRapports audio CreepJS : rendu et valeurs absentes
EmpreinteMétriques emoji CreepJS : ensembles et sommes
EmpreinteClient Hints Fingerprinting : en-têtes HTTP et identité
EmpreinteEmpreinte Canvas : exports vides et erreurs
Faites passer BotBrowser de la recherche à la production
Utilisez ces guides pour comprendre le modèle, puis passez à la validation multi-plateforme, aux contextes isolés et au déploiement navigateur prêt pour l'échelle.