Comment détecter laquelle des polices définies a été utilisée dans une page Web?

138

Supposons que j'ai la règle CSS suivante dans ma page:

body {
  font-family: Calibri, Trebuchet MS, Helvetica, sans-serif;
}

Comment puis-je détecter laquelle des polices définies a été utilisée dans le navigateur de l'utilisateur?

Modifier pour les personnes qui se demandent pourquoi je veux faire cela: la police que je détecte contient des glyphes qui ne sont pas disponibles dans d'autres polices et lorsque l'utilisateur n'a pas la police, je veux afficher un lien demandant à l'utilisateur de télécharger cette police afin qu'il peut utiliser mon application Web avec la bonne police.

Actuellement, j'affiche le lien de téléchargement de la police pour tous les utilisateurs, je souhaite l'afficher uniquement pour les personnes qui n'ont pas la bonne police installée.

Tapoter
la source
2
Une chose à garder à l'esprit est que certains navigateurs remplaceront certaines polices manquantes par des polices similaires, ce qui est impossible à détecter à l'aide de l'astuce JavaScript / CSS. Par exemple, les navigateurs Windows remplaceront Arial par Helvetica s'il n'est pas installé. L'astuce mentionnée par MojoFilter et dragonmatank signalera toujours qu'Helvetica est installé, même si ce n'est pas le cas.
tlrobinson
13
Une petite mise en garde: si vous proposez un lien pour télécharger Calibri, sachez que bien qu'il soit inclus dans plusieurs produits Microsoft, ce n'est pas une police gratuite et vous enfreignez le droit d'auteur en le proposant au téléchargement.
Adam Hepton

Réponses:

72

Je l'ai vu faire d'une manière assez douteuse, mais assez fiable. Fondamentalement, un élément est configuré pour utiliser une police spécifique et une chaîne est définie sur cet élément. Si le jeu de polices de l'élément n'existe pas, il prend la police de l'élément parent. Donc, ce qu'ils font est de mesurer la largeur de la chaîne rendue. S'il correspond à ce qu'ils attendaient de la police souhaitée par opposition à la police dérivée, il est présent. Cela ne fonctionnera pas pour les polices à espacement fixe.

Voici d'où il vient: Javascript / CSS Font Detector (ajaxian.com; 12 mars 2007)

MojoFilter
la source
2
Une autre approche utilisant à measureTextpartir de l' canvasélément: github.com/Wildhoney/DetectFont
Wildhoney
33

J'ai écrit un outil JavaScript simple que vous pouvez utiliser pour vérifier si une police est installée ou non.
Il utilise une technique simple et devrait être correct la plupart du temps.

jFont Checker sur github

Derek 朕 會 功夫
la source
2
La détection des polices ne résout pas le problème. Vous pouvez l'utiliser pour parcourir les polices déclarées et vérifier ce qui est valide, mais il donne peu ou pas d'informations sur la police utilisée pour un div donné. Si vous créez des div à partir de JS, comment pouvons-nous savoir quelle police est utilisée?
Jon Lennart Aasenden
1
@JonLennartAasenden Pour obtenir la police utilisée, je crois que vous pouvez utiliser la propriété "computedStyle" (j'ai oublié le nom exact mais c'est quelque chose comme ça.)
Derek 朕 會 功夫
1
J'ai écrit une classe qui fonctionne dans tous les navigateurs. Il est écrit en Smart Pascal qui se compile en JS, donc je ne peux pas vraiment publier la solution ici - mais en bref, j'ai dû extraire la chaîne de la famille de polices, puis vérifier que chaque police était valide, saisir la première qui était valide - et que fonctionne partout. J'ai porté le "détecteur de polices" sur smart pascal et j'ai fait quelques ajustements.
Jon Lennart Aasenden le
1
@JonLennartAasenden Il ne semble pas que votre classe soit infaillible. Les navigateurs vérifieront chaque police selon la priorité donnée, si elle est installée, mais choisiront parfois d'utiliser une police de priorité inférieure dans la liste, si la police installée de priorité supérieure a des caractères manquants ou des glyphes qui ne correspondent pas aux tailles demandées.
Brandon Elliott
10

@pat En fait, Safari ne donne pas la police utilisée, Safari renvoie toujours la première police de la pile, qu'elle soit installée ou non, du moins d'après mon expérience.

font-family: "my fake font", helvetica, san-serif;

En supposant qu'Helvetica soit celui installé / utilisé, vous obtiendrez:

  • "ma fausse police" dans Safari (et je crois que d'autres navigateurs webkit).
  • "ma fausse police, helvetica, san-serif" dans les navigateurs Gecko et IE.
  • "helvetica" dans Opera 9, même si j'ai lu qu'ils sont en train de changer cela dans Opera 10 pour correspondre à Gecko.

J'ai répondu à ce problème et j'ai créé Font Unstack , qui teste chaque police dans une pile et renvoie la première police installée uniquement. Il utilise l'astuce mentionnée par @MojoFilter, mais ne renvoie le premier que si plusieurs sont installés. Bien qu'il souffre de la faiblesse mentionnée par @tlrobinson (Windows remplacera silencieusement Arial par Helvetica et signalera qu'Helvetica est installé), cela fonctionne bien autrement.

Philoye
la source
9

Une technique qui fonctionne est de regarder le style calculé de l'élément. Ceci est pris en charge dans Opera et Firefox (et je reconnais dans safari, mais je n'ai pas testé). IE (7 au moins), fournit une méthode pour obtenir un style, mais il semble que ce soit ce qui était dans la feuille de style, pas le style calculé. Plus de détails sur quirksmode: obtenir des styles

Voici une fonction simple pour récupérer la police utilisée dans un élément:

/**
 * Get the font used for a given element
 * @argument {HTMLElement} the element to check font for
 * @returns {string} The name of the used font or null if font could not be detected
 */
function getFontForElement(ele) {
    if (ele.currentStyle) { // sort of, but not really, works in IE
        return ele.currentStyle["fontFamily"];
    } else if (document.defaultView) { // works in Opera and FF
        return document.defaultView.getComputedStyle(ele,null).getPropertyValue("font-family");
    } else {
        return null;
    }
}

Si la règle CSS pour cela était:

#fonttester {
    font-family: sans-serif, arial, helvetica;
}

Ensuite, il devrait renvoyer helvetica si cela est installé, sinon, arial, et enfin, le nom de la police sans-serif par défaut du système. Notez que l'ordre des polices dans votre déclaration CSS est important.

Un hack intéressant que vous pouvez également essayer est de créer de nombreux éléments cachés avec de nombreuses polices différentes pour essayer de détecter les polices installées sur une machine. Je suis sûr que quelqu'un pourrait créer une page de collecte de statistiques de polices astucieuse avec cette technique.

runeh
la source
6
Cela renvoie la chaîne complète du css comme "Helvetica, Arial, sans-serif". Il ne renvoie pas la police utilisée.
Tom Kincaid
8

Un formulaire simplifié est:

function getFont() {
    return document.getElementById('header').style.font;
}

Si vous avez besoin de quelque chose de plus complet, vérifiez ceci .

Facebiz
la source
8

Il existe une solution simple - utilisez simplement element.style.font:

function getUserBrowsersFont() {
    var browserHeader = document.getElementById('header');
    return browserHeader.style.font;
}

Cette fonction fera exactement ce que vous voulez. Lors de l'exécution, il retournera le type de police de l'utilisateur / du navigateur. J'espère que cela aidera.

Naeem Ul Wahhab
la source
J'essaye ceci dans Safari sur un élément qui a définitivement la police Arial et j'obtiens "" comme police. Une quelconque idée du pourquoi?
Alessandro Vermeulen
La raison la plus probable est que cela ne vérifie qu'une police définie, et s'il n'y a pas de jeu de polices, il utilise probablement Arial comme police.
Josiah
1
@AlessandroVermeulen c'est parce que element.style ne renvoie que les valeurs définies dans les attributs de style, et ne retournera aucune valeur d'ailleurs (c'est-à-dire que les valeurs des éléments de style, css externe ou user-agent default ne seront pas renvoyées). Cette réponse doit être supprimée car elle est trompeuse / incorrecte. Incroyable qu'il ait une prime!
brennanyoung
Je suis désolé, mais je ne pense pas que ce soit la bonne réponse. Bien que cela imprime la valeur de cette propriété CSS, il ne renvoie pas la police rendue réelle qui est utilisée par le navigateur.
gojun le
7

Une autre solution serait d'installer la police automatiquement via @font-facece qui pourrait annuler le besoin de détection.

@font-face { 
font-family: "Calibri"; 
src: url("http://www.yourwebsite.com/fonts/Calibri.eot"); 
src: local("Calibri"), url("http://www.yourwebsite.com/fonts/Calibri.ttf") format("truetype");
}

Bien sûr, cela ne résoudrait aucun problème de droit d'auteur, mais vous pouvez toujours utiliser une police freeware ou même créer votre propre police. Vous aurez besoin des deux fichiers .eot& .ttfpour fonctionner au mieux.

PaulnOZ
la source
3

Calibri est une police appartenant à Microsoft et ne devrait pas être distribuée gratuitement. De plus, exiger d'un utilisateur qu'il télécharge une police spécifique n'est pas très convivial.

Je suggérerais d'acheter une licence pour la police et de l'intégrer dans votre application.

Mark Kimitch
la source
3
+1 pour l'incorporation de polices. Cela résout le problème sans rien détecter.
Andrew Grothe
1
Je suggérerais de vérifier Google Fonts pour quelque chose de similaire avant d'acheter quoi que ce soit.
OJFord
Sauf que, si l'utilisateur est sur une machine Windows, il peut alors visualiser Calibri. C'est tout l'intérêt des listes de secours.
dudewad
1
Et votre réponse n'est pas liée à la question et devrait être un commentaire.
dudewad
2

J'utilise Fount. Il vous suffit de faire glisser le bouton Fount dans votre barre de favoris, de cliquer dessus puis de cliquer sur un texte spécifique sur le site. Il affichera alors la police de ce texte.

https://fount.artequalswork.com/

Woppi
la source
1

Vous pouvez placer Adobe Blank dans la famille de polices après la police que vous souhaitez voir, puis tous les glyphes qui ne sont pas dans cette police ne seront pas rendus.

par exemple:

font-family: Arial, 'Adobe Blank';

Autant que je sache, il n'y a pas de méthode JS pour dire quels glyphes dans un élément sont rendus par quelle police dans la pile de polices pour cet élément.

Cela est compliqué par le fait que les navigateurs ont des paramètres utilisateur pour les polices serif / sans-serif / monospace et qu'ils ont également leurs propres polices de remplacement codées en dur qu'ils utiliseront si un glyphe n'est trouvé dans aucune des polices d'un pile de polices. Ainsi, le navigateur peut rendre certains glyphes dans une police qui n'est pas dans la pile de polices ou dans le paramètre de police du navigateur de l'utilisateur. Les outils de développement Chrome vous montreront chaque police rendue pour les glyphes de l'élément sélectionné . Ainsi, sur votre machine, vous pouvez voir ce qu'elle fait, mais il n'y a aucun moyen de savoir ce qui se passe sur la machine d'un utilisateur.

Il est également possible que le système de l'utilisateur joue un rôle dans cela, par exemple Window effectue la substitution de polices au niveau des glyphes.

alors...

Pour les glyphes qui vous intéressent, vous n'avez aucun moyen de savoir s'ils seront rendus par le navigateur / système de secours de l'utilisateur, même s'ils n'ont pas la police que vous spécifiez.

Si vous voulez le tester dans JS, vous pouvez rendre des glyphes individuels avec une famille de polices comprenant Adobe Blank et mesurer leur largeur pour voir si elle est égale à zéro, MAIS vous devrez parcourir chaque glyphe et chaque police que vous souhaitez tester , mais bien que vous puissiez connaître les polices dans une pile de polices d'éléments, il n'y a aucun moyen de savoir quelles polices le navigateur de l'utilisateur est configuré pour utiliser, donc pour au moins certains de vos utilisateurs, la liste des polices que vous parcourez sera incomplète. (Ce n'est pas non plus une preuve pour l'avenir si de nouvelles polices sortent et commencent à être utilisées.)

Sam Hasler
la source