Collecteur CSS CreepJS : styles calculés
Suivez la collecte des clés CSSStyleDeclaration dans CreepJS, la normalisation des alias et les sondes séparées des couleurs et polices système.
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.
CreepJS possède un collecteur CSS de styles calculés distinct de son collecteur de media queries. Le fichier épinglé
src/css/index.tsconstruit un inventaire de noms de propriétés, normalise les alias, puis lit séparément les couleurs système et les polices génériques comme valeurs calculées. BotBrowser documente des réglages CSS pilotés par le profil, mais ne prétend ni implémenter ce collecteur tiers ni prévoir son résultat. Une liste de noms pris en charge n'est ni une liste de valeurs observées ni une identité d'appareil.
TL;DR
- Le collecteur épinglé lit les noms disponibles sur
CSSStyleDeclaration; il ne calcule pas la valeur de chaque propriété nommée. - Il combine les noms du prototype, les clés propres énumérables et les alias reconnus, puis supprime les doublons avec
Set. - Les couleurs système et les mots-clés de polices génériques forment des sondes distinctes via
getComputedStyle(). - CreepJS sépare ce module des vérifications
@mediaetmatchMedia()décrites dans l'analyse des canaux media queries.
Sommaire
- Entrée du collecteur
- Construction de l'inventaire des clés
- Inspecter une page maîtrisée sans inventer de référence
- La normalisation des alias a des limites
- Couleurs et polices système : des sondes distinctes
- Ce qu'une liste de clés ne permet pas de conclure
- Conclusion pratique
Entrée du collecteur
Le code appelle getComputedStyle(document.body) et transmet le CSSStyleDeclaration obtenu à computeStyle(). Cet objet fournit les noms de propriétés disponibles, mais le collecteur ne parcourt pas cette liste pour enregistrer la valeur calculée de chaque propriété. Si color figure dans keys, cela indique seulement que l'interface expose ce nom dans cet environnement ; cela ne précise pas la couleur calculée d'un élément.
Le collecteur récupère aussi le prototype de la déclaration avec Object.getPrototypeOf() et Object.getOwnPropertyNames(). Les noms propres du prototype constituent une autre entrée de l'inventaire. Le guide du fingerprinting CSS couvre la collecte par media queries et chargement de ressources, pas l'inventaire des propriétés de cette déclaration.
Ce n'est pas le collecteur CSS de media queries de CreepJS. L'autre module interroge des préférences avec un canal de propriétés personnalisées @media et matchMedia() ; ses quatorze clés appariées répondent à une autre question que l'inventaire de propriétés calculées.
Construction de l'inventaire des clés
Le code parcourt d'abord Object.keys(cssStyleDeclaration). Les clés numériques sont traitées comme des entrées indexées : leur valeur est un nom de propriété, donc le collecteur ajoute la valeur et non l'index. Les clés non numériques sont ajoutées sauf si leur nom commence par --. Une valeur ressemblant à un jeton de propriété personnalisée est également exclue de ce chemin indexé.
CSS expose souvent une propriété en forme avec tirets et en camelCase, par exemple background-color et backgroundColor. Le collecteur vérifie avec l'opérateur in si la forme correspondante existe et la marque afin que les deux graphies ne soient pas traitées comme des observations indépendantes. Il tient également compte d'un marqueur de préfixe initial lors de la réduction d'un nom pour chercher son équivalent.
La liste finale combine les noms du prototype, les noms propres énumérables et les noms déduits des contrôles d'équivalence. Un Set supprime les doublons. Le nombre rendu décrit donc l'inventaire combiné de l'environnement en cours. Ce n'est pas un nombre stable entre versions et cela ne signifie pas que chaque nom fournit une valeur calculée unique.
| Entrée | Opération source | Signification de l'entrée |
|---|---|---|
| Prototype | Object.getOwnPropertyNames(proto) | Nom propre du prototype de la déclaration |
| Clés propres | Object.keys(cssStyleDeclaration) | Clé propre énumérable ; une entrée indexée devient un nom |
| Alias correspondant | Tests in entre formes avec tirets et camelCase | Relation de graphie utilisée pour éviter de compter deux propriétés |
| Inventaire final | new Set([...]) | Liste de noms dédupliquée, pas une table de valeurs |
La source épinglée du collecteur CSS fait autorité pour ces étapes. La référence CSSStyleDeclaration décrit l'objet, sans affirmer que tous les navigateurs énumèrent les mêmes noms.
Le collecteur se lit comme une petite chaîne de traitement. La première étape choisit getComputedStyle(document.body) et le prototype de CSSStyleDeclaration. La deuxième construit les noms à partir du prototype et des clés propres, y compris les alias. La troisième demande séparément au navigateur de résoudre des couleurs système et des polices génériques. Ces étapes ont des entrées et des formes de sortie différentes ; ne les aplatissez pas dans un seul champ « empreinte CSS ».
| Étape | Opération source | Forme de sortie | Question utile |
|---|---|---|---|
| Choix de la déclaration | getComputedStyle(document.body) | Objet de déclaration du body | Quel élément et quel document l'ont produit ? |
| Énumération | Noms du prototype et Object.keys() | Tableau keys dédupliqué | L'ensemble des noms exposés a-t-il changé ? |
| Couleurs système | Affecter un mot-clé, lire backgroundColor | Une valeur par mot-clé dans system.colors | Une couleur système résolue a-t-elle changé ? |
| Polices système | Affecter font, lire taille et famille | Chaîne taille/famille dans system.fonts | La résolution du raccourci de police a-t-elle changé ? |
Cette séparation aide à comparer deux versions du navigateur. Si keys change, commencez par demander si l'ensemble des noms exposés a changé, et non si la couleur affichée a changé. Un alias supplémentaire peut affecter le tableau avant déduplication ; une différence de prototype peut changer une entrée ; et Set peut masquer des graphies dupliquées. À l'inverse, l'inventaire peut rester identique alors qu'une couleur calculée change, car cette valeur est stockée dans system.colors.
Conservez la hiérarchie du rapport. L'objet CSS contient le résultat des styles calculés et celui des styles système ; l'interface ajoute un hash court et un compteur. Ce compteur est un résumé avec perte : il ne conserve ni les noms présents ni les valeurs obtenues par les sondes. Pour comparer des rapports, gardez les objets complets au lieu de recopier uniquement le compteur.
Inspecter une page maîtrisée sans inventer de référence
Sur une page que vous contrôlez, cette capture console conserve séparées les catégories de données. C'est une aide à la lecture, pas une reproduction de tous les helpers CreepJS ni une affirmation sur les données utilisées par un autre service :
const declaration = getComputedStyle(document.body);
const prototype = Object.getPrototypeOf(declaration);
const ownNames = Object.keys(declaration).map(key => {
const numeric = !Number.isNaN(Number(key));
return numeric ? declaration[key] : key;
});
const prototypeNames = Object.getOwnPropertyNames(prototype);
const inventory = [...new Set([...prototypeNames, ...ownNames])];
const selectedValues = Object.fromEntries(
['color', 'background-color', 'font-family', 'font-size'].map(name => [name, declaration.getPropertyValue(name)])
);
console.log({ inventory, selectedValues });
L'exemple nomme l'échantillon selectedValues ; il ne prétend pas reproduire toute la logique d'alias CreepJS. Il ne remplace pas non plus les sondes CreepJS de couleurs et polices système. Dans la source épinglée, ces sondes créent ou réutilisent un élément, affectent un mot-clé au style en ligne, appellent getComputedStyle() et lisent un champ résolu précis. Notez l'élément inspecté et toute modification avant d'interpréter la valeur.
Pour comparer des captures, conservez séparément l'identifiant du build navigateur, l'origine de la page, l'élément choisi, l'heure de capture et l'objet exact. Comparez ensuite la liste de noms indépendamment des valeurs. Ne triez ni ne normalisez l'objet original avant sa conservation : cela peut effacer sa représentation. Une vue normalisée peut être dérivée si l'original reste disponible.
Une valeur absente mérite un état propre. Une propriété peut ne pas être prise en charge, une lecture peut renvoyer une chaîne vide, ou le collecteur peut échouer avant de créer l'objet attendu. Ces résultats ne sont pas équivalents. L'API CSSOM définit l'accès et le calcul des styles, mais le relevé doit encore préciser si le champ est absent, vide ou renseigné. Cela évite de transformer une observation manquante en résultat négatif mesuré.
La normalisation des alias a des limites
Les vérifications d'équivalence de la source servent à dédupliquer ; elles ne prouvent pas que toutes les graphies CSS sont interchangeables dans chaque contexte. Le code dérive un équivalent pour les noms avec tirets, tient compte d'un marqueur de préfixe initial et dérive aussi une forme avec tirets depuis les majuscules. Si l'équivalent existe sur l'objet déclaration, il est marqué dans propertiesInPrototypeChain. La liste finale l'inclut, puis Set élimine les doublons exacts.
Deux questions restent distinctes : le collecteur reconnaît-il deux chaînes comme alias, et la lecture des deux graphies sur un élément donne-t-elle la même valeur ? Le code répond à la première lors de la création de l'inventaire. Il n'enregistre pas une comparaison de valeurs pour chaque paire d'alias. Ne déduisez donc pas un test d'équivalence des valeurs du fait que deux graphies ont été normalisées.
Les propriétés personnalisées sont traitées différemment. Les noms correspondant à --... ne passent pas par la branche ordinaire, et certaines valeurs ressemblant à un jeton de propriété personnalisée sont exclues du chemin indexé. C'est un filtrage propre à cette source. Cela ne prouve pas qu'une propriété personnalisée soit illisible via getPropertyValue() ; keys n'est pas un dump complet des déclarations ou des feuilles de style.
| Changement observé | Première zone à examiner | Conclusion à éviter |
|---|---|---|
Le compteur keys change, mais les noms courants restent | Alias et énumération du prototype | Qu'une valeur de style a changé dans la même proportion |
| Une nouvelle forme tirets/camelCase apparaît | Transformation du nom et test in | Que les valeurs des deux graphies ont été comparées |
system.colors change | Affectation du mot-clé et backgroundColor calculé | Que le thème du système en est l'unique cause |
system.fonts change | Shorthand font générique, taille et famille résolues | Que toutes les polices installées ont été énumérées |
| Rapport CSS absent ou partiel | Capture d'erreur et chemin de rendu | Que le navigateur a renvoyé un inventaire vide |
Ce tableau est un plan de triage dérivé de l'implémentation épinglée. Il indique la provenance de chaque catégorie de sortie ; il ne diagnostique pas une différence sans objets bruts et métadonnées de l'environnement.
Couleurs et polices système : des sondes distinctes
getSystemStyles() effectue deux groupes d'appels. Pour des couleurs telles que Canvas, CanvasText, ButtonFace et Highlight, il affecte background-color à l'élément temporaire puis lit getComputedStyle(el).backgroundColor. Pour les mots-clés génériques de police comme caption, icon, menu, message-box, small-caption et status-bar, il définit le raccourci font et enregistre fontSize et fontFamily calculés.
Ce sont des observations de valeurs, contrairement à l'inventaire keys. Ce n'est pas non plus un parseur de couleurs : le collecteur demande au navigateur de résoudre les mots-clés système puis stocke la chaîne obtenue. La référence couleurs système CSS décrit cette catégorie, et getComputedStyle() décrit l'API de lecture des styles résolus.
Sans élément fourni, le code crée un div, l'ajoute à document.body, récupère les styles puis le supprime. Avec un élément fourni, il réutilise celui-ci. La fonction intercepte les erreurs et ne renvoie pas le résultat de styles système en cas d'échec, après le signalement par le mécanisme d'erreur CreepJS. Un résultat absent n'est donc pas une liste vide mesurée.
Les listes fixes précisent aussi ce que le collecteur ne cherche pas. La liste de couleurs comprend Canvas, CanvasText, Field, FieldText, Highlight et WindowText. La liste de polices contient des mots-clés génériques, pas un catalogue des familles installées. Le résultat répond à « comment le navigateur a-t-il résolu ces mots-clés sur cet élément ? », et non « quelles polices sont installées ? » ou « quelle préférence matchMedia() a-t-il renvoyée ? »
La source affecte chaque couleur sous la forme background-color: <keyword> !important avant de lire le fond calculé. Pour une police, elle utilise le raccourci font puis combine taille et famille résolues. Ces choix délimitent la mesure. Un relevé comparatif devrait conserver le mot-clé, le nom du champ et la chaîne obtenue ; sinon CanvasText → rgb(...) pourrait être confondu avec une lecture directe de la couleur de texte d'une page arbitraire.
L'état temporaire du DOM compte également. Le chemin par défaut ajoute son propre div au body, lit les styles puis le retire. Ce n'est pas la même chose que lire un élément d'application dont les classes, styles hérités ou déclarations en ligne influencent le résultat. Une reproduction ne devrait pas changer silencieusement l'élément choisi puis attribuer l'écart au navigateur.
Ce qu'une liste de clés ne permet pas de conclure
Un inventaire ne prouve pas qu'une page a utilisé une propriété, qu'une valeur particulière a été renvoyée ni qu'un détecteur distant a consommé le rapport. La source montre les noms enregistrés et les valeurs de couleurs et polices demandées. Elle ne permet pas à elle seule d'identifier du matériel, un système d'exploitation ou une personne. La présence d'un nom est une observation d'interface ; son interprétation demande la version du navigateur, le contexte du document et les valeurs réelles.
BotBrowser documente les réglages CSS du profil dans sa référence sur la cohérence des signaux CSS. Cette configuration ne reproduit pas ce collecteur CreepJS et ne garantit pas son résultat. Gardez séparées les capacités produit et les affirmations sur le code source CreepJS.
FAQ
keys contient-il toutes les valeurs CSS calculées ?
Non. Il contient des noms issus des clés et alias de l'objet déclaration. Le code montré demande séparément uniquement les valeurs des sondes de couleurs et polices système dans getSystemStyles().
Pourquoi inspecter l'objet et son prototype ?
La source traite les clés propres énumérables et les noms propres du prototype comme des entrées distinctes, puis les combine. Cela expose sa normalisation ; cela ne signifie pas que chaque origine est une mesure navigateur séparée.
Est-ce le même signal que matchMedia() ?
Non. src/css/index.ts lit les noms de déclaration et les styles système. src/cssmedia/index.ts interroge des préférences avec des règles CSS et matchMedia(). L'étiquette CSS commune ne fusionne pas les collecteurs.
Cette liste identifie-t-elle un appareil ?
Non. Les noms décrivent une surface d'API et les styles sont des valeurs résolues par le navigateur. Ni l'un ni l'autre n'établit seul un appareil physique ou une identité unique.
Sources
- Collecteur CSS CreepJS épinglé (
src/css/index.ts) - MDN :
Window.getComputedStyle() - MDN :
CSSStyleDeclaration - MDN : couleurs système CSS
- BotBrowser : cohérence des signaux CSS
Conclusion pratique
Lisez le rapport CSS de CreepJS comme deux catégories : un inventaire fusionné de noms de propriétés et des valeurs calculées séparées de couleurs et polices système. Lors d'une comparaison, gardez ces catégories distinctes, épinglez la révision source et conservez l'objet réel au lieu de l'inférer du compteur. L'article sur les canaux CSS media queries couvre les préférences ; l'analyse des tables de polices CreepJS décrit un autre champ du rapport, pas les valeurs des polices système CSS.
Cet article fait partie du guide : Qu'est-ce qu'une empreinte de navigateur ?
Articles Connexes
Requêtes média CSS dans CreepJS : deux canaux, une préférence
EmpreinteFingerprinting CSS : comment les styles vous suivent
EmpreinteTables CreepJS : 51 noms et 14 retours possibles
EmpreinteRapport WebRTC CreepJS : origine des champs
EmpreinteRapport WebGL de CreepJS : contextes et signaux
EmpreinteSignaux Math de CreepJS : lire les champs
Exécutez la même vérification dans BotBrowser
Chargez un profil, gardez dans le navigateur les signaux que vous venez de lire, puis confirmez le résultat sur votre propre machine avant le déploiement.