Modification dynamique du favicon du site Web

347

J'ai une application Web qui est personnalisée en fonction de l'utilisateur actuellement connecté. J'aimerais changer le favicon de la page pour qu'il devienne le logo de la marque de distributeur, mais je ne trouve aucun code ni aucun exemple de comment pour faire ça. Quelqu'un a-t-il déjà réussi cela?

J'imagine avoir une douzaine d'icônes dans un dossier, et la référence au fichier favicon.ico à utiliser est juste générée dynamiquement avec la page HTML. Pensées?

SqlRyan
la source
40
Il y a un jeu d'arcade dans un favicon.
Corey Trager
Notez que l'implémentation de favicon dynamique de Chrome est boguée et utilise trop de CPU. Voir code.google.com/p/chromium/issues/detail?id=121333
brillout
6
Le lien pour le jeu d'arcade a changé. C'est le bon.
Basil
Voir stackoverflow.com/questions/6296574/… sur la façon de mettre à jour dynamiquement le favicon en dessinant au-dessus d'une image de modèle avec un canevas.
gérer
1
Petit bug dans l'exemple de code fourni dans la réponse acceptée. Je n'ai pas un score de réputation suffisant pour commenter les réponses, c'est pourquoi j'écris ici à la place. La dernière ligne a permuté les parenthèses:} ()); Devrais lire })(); Ce serait bien que l'exemple de code soit mis à jour car il est très probablement copié et collé par d'autres.
Goran W

Réponses:

396

Pourquoi pas?

(function() {
    var link = document.querySelector("link[rel*='icon']") || document.createElement('link');
    link.type = 'image/x-icon';
    link.rel = 'shortcut icon';
    link.href = 'http://www.stackoverflow.com/favicon.ico';
    document.getElementsByTagName('head')[0].appendChild(link);
})();

Firefox devrait être cool avec ça.

modifié pour remplacer correctement les icônes existantes

keparo
la source
2
Je pense que cela est proche de ce que je recherche, mais comment puis-je obtenir le HREF approprié de la base de données. Je suppose que je vais devoir faire une recherche de serveur à partir de javascript, mais je ne veux pas que cela devienne trop compliqué. Merci pour le conseil.
SqlRyan
34
Comme cela ne fonctionne pas de toute façon dans IE, vous pouvez le supprimer shortcutde l' relattribut. shortcutest une relation de lien propriétaire IE invalide!
Mathias Bynens
8
Vous pouvez tout aussi facilement rechercher un lien favicon existant et le mettre à jour ou le remplacer.
keparo
5
Google peut vous donner le favicon d'un site en utilisant cette URL, en remplaçant stackoverflow.com par le domaine que vous souhaitez: s2.googleusercontent.com/s2/favicons?domain=stackoverflow.com
kirb
5
La saisie de cela dans la console Javascript dans Chrome devrait-elle fonctionner? Je n'arrive pas à changer les favicons sur divers sites de cette façon.
powerj1984
88

Voici du code qui fonctionne dans Firefox, Opera et Chrome (contrairement à toutes les autres réponses publiées ici). Voici une autre démonstration de code qui fonctionne également dans IE11 . L'exemple suivant peut ne pas fonctionner dans Safari ou Internet Explorer.

/*!
 * Dynamically changing favicons with JavaScript
 * Works in all A-grade browsers except Safari and Internet Explorer
 * Demo: http://mathiasbynens.be/demo/dynamic-favicons
 */

// HTML5™, baby! http://mathiasbynens.be/notes/document-head
document.head = document.head || document.getElementsByTagName('head')[0];

function changeFavicon(src) {
 var link = document.createElement('link'),
     oldLink = document.getElementById('dynamic-favicon');
 link.id = 'dynamic-favicon';
 link.rel = 'shortcut icon';
 link.href = src;
 if (oldLink) {
  document.head.removeChild(oldLink);
 }
 document.head.appendChild(link);
}

Vous l'utiliseriez alors comme suit:

var btn = document.getElementsByTagName('button')[0];
btn.onclick = function() {
 changeFavicon('http://www.google.com/favicon.ico');
};

Sortez ou regardez une démo .

Mathias Bynens
la source
Le bug de Chrome a été corrigé dans Chrome 6 (publié le 10 septembre), donc le piratage de Chrome n'est plus vraiment nécessaire - en fait, je vous suggère fortement de ne pas l'utiliser car il casse le bouton avant.
josh3736
Le bogue Chrome a peut-être été corrigé, mais il est à nouveau cassé dans 14.0.835.187.
danorton
La démo ne fonctionne pas pour moi avec Chrome 21 / WinXP.
Hugo
La démo ne fonctionne pas pour moi dans Chrome 26 / Win7. document.head || document.head = document.getElementsByTagName('head')[0]; Uncaught ReferenceError: Invalid left-hand side in assignment
Patrick
2
Cela fonctionne dans tous les navigateurs actuellement pris en charge (IE 11, Edge, FF et Chrome), impossible de tester avec safari
Aaron
46

Si vous disposez de l'extrait HTML suivant:

<link id="favicon" rel="shortcut icon" type="image/png" href="favicon.png" />

Vous pouvez changer le favicon en utilisant Javascript en changeant l'élément HREF sur ce lien, par exemple (en supposant que vous utilisez JQuery):

$("#favicon").attr("href","favicon2.png");

Vous pouvez également créer un élément Canvas et définir le HREF comme ToDataURL () du canvas, un peu comme le fait Favicon Defender .

fserb
la source
1
Je pense qu'au moment où JS s'exécute, le navigateur aura déjà vu le lien et tenté de se charger favicon.png. Cela pourrait devoir être fait côté serveur.
cHao
Si vous n'utilisez pas JQuery, vous pouvez modifier l' hrefattribut d' #faviconutilisation document.getElementById('favicon').setAttribute('href','favicon2.png') Peut-être pouvez-vous l'ajouter à votre message @fserb?
johannchopin
37

Version jQuery:

$("link[rel='shortcut icon']").attr("href", "favicon.ico");

ou encore mieux:

$("link[rel*='icon']").attr("href", "favicon.ico");

Version Vanilla JS:

document.querySelector("link[rel='shortcut icon']").href = "favicon.ico";

document.querySelector("link[rel*='icon']").href = "favicon.ico";
vorillaz
la source
@pkExec Une combinaison de cela et de la réponse de keparo ci-dessus (la réponse choisie) l'a fait fonctionner à la fois en ff et en chrome pour moi.
MrShmee
17

Une approche plus moderne:

const changeFavicon = link => {
  let $favicon = document.querySelector('link[rel="icon"]')
  // If a <link rel="icon"> element already exists,
  // change its href to the given link.
  if ($favicon !== null) {
    $favicon.href = link
  // Otherwise, create a new element and append it to <head>.
  } else {
    $favicon = document.createElement("link")
    $favicon.rel = "icon"
    $favicon.href = link
    document.head.appendChild($favicon)
  }
}

Vous pouvez ensuite l'utiliser comme ceci:

changeFavicon("http://www.stackoverflow.com/favicon.ico")
Michał Perłakowski
la source
11

Le favicon est déclaré dans la balise head avec quelque chose comme:

<link rel="shortcut icon" type="image/ico" href="favicon.ico">

Vous devriez pouvoir simplement passer le nom de l'icône que vous souhaitez dans les données de vue et le jeter dans la balise head.

Jeff Sheldon
la source
1
IIRC, cependant, certains navigateurs (je regarde dans votre direction, IE) ne respectent pas vraiment cela parfois.
Matthew Schinckel
(J'ai trouvé que j'avais de meilleurs résultats en ayant simplement le fichier d'icône au bon endroit, plutôt que le lien explicite).
Matthew Schinckel
9

Voici du code que j'utilise pour ajouter le support de favicon dynamique à Opera, Firefox et Chrome. Je n'ai pas réussi à faire fonctionner IE ou Safari. Fondamentalement, Chrome autorise les favicons dynamiques, mais il ne les met à jour que lorsque l'emplacement de la page (ou un iframeetc.) change pour autant que je sache:

var IE = navigator.userAgent.indexOf("MSIE")!=-1
var favicon = {
    change: function(iconURL) {
        if (arguments.length == 2) {
            document.title = optionalDocTitle}
        this.addLink(iconURL, "icon")
        this.addLink(iconURL, "shortcut icon")

        // Google Chrome HACK - whenever an IFrame changes location 
        // (even to about:blank), it updates the favicon for some reason
        // It doesn't work on Safari at all though :-(
        if (!IE) { // Disable the IE "click" sound
            if (!window.__IFrame) {
                __IFrame = document.createElement('iframe')
                var s = __IFrame.style
                s.height = s.width = s.left = s.top = s.border = 0
                s.position = 'absolute'
                s.visibility = 'hidden'
                document.body.appendChild(__IFrame)}
            __IFrame.src = 'about:blank'}},

    addLink: function(iconURL, relValue) {
        var link = document.createElement("link")
        link.type = "image/x-icon"
        link.rel = relValue
        link.href = iconURL
        this.removeLinkIfExists(relValue)
        this.docHead.appendChild(link)},

    removeLinkIfExists: function(relValue) {
        var links = this.docHead.getElementsByTagName("link");
        for (var i=0; i<links.length; i++) {
            var link = links[i]
            if (link.type == "image/x-icon" && link.rel == relValue) {
                this.docHead.removeChild(link)
                return}}}, // Assuming only one match at most.

    docHead: document.getElementsByTagName("head")[0]}

Pour changer de favicons, favicon.change("ICON URL")utilisez simplement ce qui précède.

(crédits à http://softwareas.com/dynamic-favicons pour le code sur lequel je me suis basé.)

cryo
la source
Le bug de Chrome a été corrigé dans Chrome 6 (publié le 10 septembre), donc le piratage de Chrome n'est plus vraiment nécessaire - en fait, je vous suggère fortement de ne pas l'utiliser car il casse le bouton avant.
josh3736
Chrome a toujours ce même bogue, bien que dans des circonstances légèrement différentes du bogue spécifique noté. code.google.com/p/chromium/issues/detail?id=99549
danorton
4

J'utiliserais l'approche de Greg et ferais un gestionnaire personnalisé pour favicon.ico Voici un gestionnaire (simplifié) qui fonctionne:

using System;
using System.IO;
using System.Web;

namespace FaviconOverrider
{
    public class IcoHandler : IHttpHandler
    {
    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "image/x-icon";
        byte[] imageData = imageToByteArray(context.Server.MapPath("/ear.ico"));
        context.Response.BinaryWrite(imageData);
    }

    public bool IsReusable
    {
        get { return true; }
    }

    public byte[] imageToByteArray(string imagePath)
    {
        byte[] imageByteArray;
        using (FileStream fs = new FileStream(imagePath, FileMode.Open, FileAccess.Read))
        {
        imageByteArray = new byte[fs.Length];
        fs.Read(imageByteArray, 0, imageByteArray.Length);
        }

        return imageByteArray;
    }
    }
}

Vous pouvez ensuite utiliser ce gestionnaire dans la section httpHandlers de la configuration Web dans IIS6 ou utiliser la fonctionnalité «Mappages de gestionnaires» dans IIS7.

Dan
la source
1
Je suis vraiment curieux de savoir pourquoi cela a été rejeté. c'est en fait la meilleure réponse étant donné que tous les autres s'appuient sur des scripts qui peuvent être disponibles ou non.
ethermal
1
@ethermal Parce qu'il semble que c'est dynamique côté serveur. OP demandait du dynamisme du côté du client.
Alexis Wilke
3

La seule façon de faire fonctionner cela pour IE est de paramétrer votre serveur Web pour traiter les demandes pour que * .ico appelle votre langage de script côté serveur (PHP, .NET, etc.). Configurez également * .ico pour rediriger vers un seul script et que ce script fournisse le fichier favicon correct. Je suis sûr qu'il y aura toujours des problèmes intéressants avec le cache si vous voulez pouvoir rebondir dans le même navigateur entre différents favicons.

Greg
la source
3

Il existe une solution sur une seule ligne pour ceux qui utilisent jQuery:

$("link[rel*='icon']").prop("href",'https://www.stackoverflow.com/favicon.ico');
Pepelegal
la source
3

Ou si vous voulez une émoticône :)

var canvas = document.createElement("canvas");
canvas.height = 64;
canvas.width = 64;

var ctx = canvas.getContext("2d");
ctx.font = "64px serif";
ctx.fillText("☠️", 0, 64); 

$("link[rel*='icon']").prop("href", canvas.toDataURL());

Accessoires à https://koddsson.com/posts/emoji-favicon/

max4ever
la source
2

Selon WikiPedia , vous pouvez spécifier le fichier favicon à charger en utilisant la linkbalise dans la headsection, avec un paramètre de rel="icon".

Par exemple:

 <link rel="icon" type="image/png" href="/path/image.png">

J'imagine que si vous vouliez écrire du contenu dynamique pour cet appel, vous auriez accès à des cookies afin que vous puissiez récupérer vos informations de session de cette façon et présenter un contenu approprié.

Vous risquez de tomber dans des formats de fichiers (IE ne prend en charge que son format .ICO, tandis que la plupart des autres prennent en charge les images PNG et GIF) et peut-être des problèmes de mise en cache, à la fois sur le navigateur et via des proxys. Cela serait dû à l'original intention de favicon, spécifiquement, pour marquer un signet avec le mini-logo d'un site.

staticsan
la source
beaucoup plus que ça. stackoverflow.com/a/45301651/661584 les faqs / info sur le site du générateur vous surprendront - il y a beaucoup à ce sujet.
MemeDeveloper
3
Le web change beaucoup en 9 ans.
staticsan
2

Oui totalement possible

  • Utilisez une chaîne de requête après le favicon.ico (et d'autres liens de fichiers - voir le lien de réponse ci-dessous)
  • Assurez-vous simplement que le serveur répond à "someUserId" avec le fichier d'image correct (qui peut être des règles de routage statiques ou du code côté serveur dynamique ).

par exemple

<link rel="shortcut icon" href="/favicon.ico?userId=someUserId">

Quel que soit le langage / framework côté serveur que vous utilisez, vous pouvez facilement trouver le fichier en fonction de l'ID utilisateur et le servir en réponse à cette demande .

Mais pour faire des favicons correctement (c'est en fait un sujet vraiment complexe ), veuillez voir la réponse ici https://stackoverflow.com/a/45301651/661584

Beaucoup plus facile que de travailler vous-même sur tous les détails.

Prendre plaisir.

MemeDeveloper
la source
Ouais, le lien est bon. Je pense que la principale raison pour laquelle ces réponses ne fonctionnent pas dans IE est qu'elles n'utilisent pas cette icône par défaut <link>, mais recherchent plutôt la apple-touch-iconou une autre variante de ce type.
Alexis Wilke
1

J'utilise favico.js dans mes projets.

Il permet de changer le favicon en une gamme de formes prédéfinies et également personnalisées.

En interne, il utilise canvaspour le rendu et base64l'URL des données pour le codage des icônes.

La bibliothèque a également de belles fonctionnalités: badges d'icônes et animations; soi-disant, vous pouvez même diffuser la vidéo de la webcam dans l'icône :)

Oscar Nevarez
la source
Le lien et la bibliothèque sont très utiles, veuillez fournir une description de leur fonctionnement afin que cela devienne également une réponse valide à la question comme indiqué.
Dima Tisnek
1
Merci @DimaTisnek. J'ai mis à jour ma réponse.
Oscar Nevarez
0

J'utilise cette fonctionnalité tout le temps lors du développement de sites ... afin que je puisse voir en un coup d'œil quel onglet contient local, dev ou prod.

Maintenant que Chrome prend en charge les favicons SVG, il est beaucoup plus facile.

Tampermonkey Script

Jetez un coup d'œil à https://gist.github.com/elliz/bb7661d8ed1535c93d03afcd0609360f pour un script tampermonkey qui pointe vers un site de démonstration que j'ai jeté sur https://elliz.github.io/svg-favicon/

Code de base

Adapté ceci d'une autre réponse ... pourrait être amélioré mais assez bon pour mes besoins.

(function() {
    'use strict';

    // play with https://codepen.io/elliz/full/ygvgay for getting it right
    // viewBox is required but does not need to be 16x16
    const svg = `
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
      <circle cx="8" cy="8" r="7.2" fill="gold" stroke="#000" stroke-width="1" />
      <circle cx="8" cy="8" r="3.1" fill="#fff" stroke="#000" stroke-width="1" />
    </svg>
    `;

    var favicon_link_html = document.createElement('link');
    favicon_link_html.rel = 'icon';
    favicon_link_html.href = svgToDataUri(svg);
    favicon_link_html.type = 'image/svg+xml';

    try {
        let favicons = document.querySelectorAll('link[rel~="icon"]');
        favicons.forEach(function(favicon) {
            favicon.parentNode.removeChild(favicon);
        });

        const head = document.getElementsByTagName('head')[0];
        head.insertBefore( favicon_link_html, head.firstChild );
    }
    catch(e) { }

    // functions -------------------------------
    function escapeRegExp(str) {
        return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
    }

    function replaceAll(str, find, replace) {
        return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
    }

    function svgToDataUri(svg) {
        // these may not all be needed - used to be for uri-encoded svg in old browsers
        var encoded = svg.replace(/\s+/g, " ")
        encoded = replaceAll(encoded, "%", "%25");
        encoded = replaceAll(encoded, "> <", "><"); // normalise spaces elements
        encoded = replaceAll(encoded, "; }", ";}"); // normalise spaces css
        encoded = replaceAll(encoded, "<", "%3c");
        encoded = replaceAll(encoded, ">", "%3e");
        encoded = replaceAll(encoded, "\"", "'"); // normalise quotes ... possible issues with quotes in <text>
        encoded = replaceAll(encoded, "#", "%23"); // needed for ie and firefox
        encoded = replaceAll(encoded, "{", "%7b");
        encoded = replaceAll(encoded, "}", "%7d");
        encoded = replaceAll(encoded, "|", "%7c");
        encoded = replaceAll(encoded, "^", "%5e");
        encoded = replaceAll(encoded, "`", "%60");
        encoded = replaceAll(encoded, "@", "%40");
        var dataUri = 'data:image/svg+xml;charset=UTF-8,' + encoded.trim();
        return dataUri;
    }

})();

Insérez simplement votre propre SVG (peut-être nettoyé avec le SVGOMG de Jake Archibald si vous utilisez un outil) dans la const en haut. Assurez-vous qu'il est carré (en utilisant l'attribut viewBox) et vous êtes prêt à partir.

Ruskin
la source