Mudando o favicon do site dinamicamente

347

Eu tenho um aplicativo Web com a marca de acordo com o usuário conectado no momento. Gostaria de mudar o ícone da página para ser o logotipo da marca própria, mas não consigo encontrar nenhum código ou exemplo de como para fazer isso. Alguém já fez isso com sucesso antes?

Estou imaginando ter uma dúzia de ícones em uma pasta, e a referência à qual o arquivo favicon.ico usar é gerada dinamicamente, juntamente com a página HTML. Pensamentos?

SqlRyan
fonte
40
Há um jogo de arcade em um favicon.
Corey Trager #
Observe que a implementação dinâmica de favicon do Chrome é defeituosa e usa muita CPU. Consulte code.google.com/p/chromium/issues/detail?id=121333
brillout em 30/04/12
6
O link para o jogo de arcade mudou. Este é o correto.
Basil
Consulte stackoverflow.com/questions/6296574/… sobre como atualizar dinamicamente o favicon desenhando sobre uma imagem de modelo com tela.
manipula
11
Pequeno erro no exemplo de código fornecido na resposta aceita. Não tenho uma pontuação de reputação suficiente para comentar as respostas, portanto, escrevendo aqui. A última linha tem os parênteses trocados:} ()); deve ler })(); Seria bom que o exemplo de código seja atualizado, pois provavelmente é copiado e colado por outros.
Goran W

Respostas:

396

Por que não?

(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);
})();

O Firefox deve ser legal com isso.

editado para substituir adequadamente os ícones existentes

keparo
fonte
2
Estou pensando que isso é próximo do que estou procurando, mas como obteria o HREF apropriado do banco de dados. Suponho que precisarei fazer uma pesquisa no servidor a partir de javascript, mas não quero que isso fique muito complicado. Obrigado pela dica.
SqlRyan 4/08
34
Como isso não funciona no IE, você pode remover shortcutdo relatributo shortcuté uma relação de link proprietária do IE inválida!
Mathias Bynens
8
Você poderia facilmente procurar por um link favicon existente e atualizá-lo ou substituí-lo.
31411 keparo
5
Google pode lhe dar favicon de um site usando este URL, substituindo stackoverflow.com com o domínio que você deseja: s2.googleusercontent.com/s2/favicons?domain=stackoverflow.com
Kirb
5
Deveria inserir isso no console Javascript no Chrome? Não consigo mudar os favicons em vários sites dessa maneira.
powerj1984
88

Aqui está um código que funciona no Firefox, Opera e Chrome (diferente de todas as outras respostas postadas aqui). Aqui está uma demonstração diferente do código que também funciona no IE11 . O exemplo a seguir pode não funcionar no Safari ou no 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);
}

Você o usaria da seguinte maneira:

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

Afaste-se ou veja uma demonstração .

Mathias Bynens
fonte
O bug do Chrome foi corrigido no Chrome 6 (lançado em 10 de setembro), então o hack do Chrome não é mais necessário - na verdade, eu sugiro fortemente que não o use, pois ele quebra o botão de avançar.
precisa saber é o seguinte
O bug do Chrome pode ter sido corrigido, mas foi quebrado novamente em 14.0.835.187.
Danorton 7/10
A demonstração não está funcionando para mim com o Chrome 21 / WinXP.
Hugo Hugo
A demonstração não está funcionando para mim no Chrome 26 / Win7. document.head || document.head = document.getElementsByTagName('head')[0]; Uncaught ReferenceError: Invalid left-hand side in assignment
7103 Patrick
2
Isso funciona em todos os navegadores atualmente suportados (IE 11, Edge, FF e Chrome) incapazes de testar com o safari
Aaron
46

Se você possui o seguinte snippet HTML:

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

Você pode alterar o favicon usando Javascript, alterando o elemento HREF neste link, por exemplo (supondo que você esteja usando JQuery):

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

Você também pode criar um elemento Canvas e definir o HREF como um ToDataURL () da tela, assim como o Favicon Defender .

fserb
fonte
11
Eu acho que quando o JS for executado, o navegador já terá visto o link e tentado carregar favicon.png. Isso pode precisar ser feito no lado do servidor.
cHao 13/07/12
Se você não usar o JQuery, poderá alterar o hrefatributo do #faviconuso document.getElementById('favicon').setAttribute('href','favicon2.png') Talvez você possa adicioná-lo à sua postagem @fserb?
johannchopin 22/04
37

Versão jQuery:

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

ou melhor ainda:

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

Versão Vanilla JS:

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

document.querySelector("link[rel*='icon']").href = "favicon.ico";
vorillaz
fonte
@pkExec Uma combinação disso e da resposta do keparo acima (a resposta escolhida) fez com que funcionasse em ff e chrome para mim.
MrShmee
17

Uma abordagem mais moderna:

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)
  }
}

Você pode usá-lo assim:

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

O favicon é declarado na tag head com algo como:

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

Você deve apenas passar o nome do ícone que deseja nos dados da visualização e jogá-lo na tag head.

Jeff Sheldon
fonte
11
O IIRC, no entanto, alguns navegadores (estou olhando na sua direção, IE) realmente não respeitam isso às vezes.
Matthew Schinckel 4/08/08
(Descobri que obtive melhores resultados apenas por ter o arquivo de ícone no local correto, em vez do link explícito).
Matthew Schinckel 4/08/08
9

Aqui estão alguns códigos que eu uso para adicionar suporte dinâmico a favicon no Opera, Firefox e Chrome. Eu não conseguia fazer o IE ou o Safari funcionar. Basicamente, o Chrome permite favicons dinâmicos, mas só os atualiza quando a localização da página (ou um iframeetc nela) muda tanto quanto eu sei:

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]}

Para alterar os favoritos, basta favicon.change("ICON URL")usar o acima.

(créditos para http://softwareas.com/dynamic-favicons pelo código em que baseei isso.)

crio
fonte
O bug do Chrome foi corrigido no Chrome 6 (lançado em 10 de setembro), então o hack do Chrome não é mais necessário - na verdade, eu sugiro fortemente que não o use, pois ele quebra o botão de avançar.
precisa saber é o seguinte
O Chrome ainda possui o mesmo bug, embora em circunstâncias ligeiramente diferentes do bug específico observado. code.google.com/p/chromium/issues/detail?id=99549
danorton
4

Eu usaria a abordagem de Greg e criaria um manipulador personalizado para o favicon.ico. Aqui está um manipulador (simplificado) que funciona:

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;
    }
    }
}

Em seguida, você pode usar esse manipulador na seção httpHandlers da configuração da web no IIS6 ou usar o recurso 'Mapeamentos de manipulador' no IIS7.

Dan
fonte
11
Na verdade, estou curioso para saber por que isso foi prejudicado? essa é realmente a melhor resposta, considerando que todos os outros dependem de scripts que podem ou não estar disponíveis.
ethermal
11
@ethermal Porque parece dinâmico no lado do servidor. O OP estava pedindo dinamismo no lado do cliente.
Alexis Wilke
3

A única maneira de fazer isso funcionar para o IE é configurando o servidor da Web para tratar solicitações do * .ico para chamar a linguagem de script do lado do servidor (PHP, .NET, etc). Também configure * .ico para redirecionar para um único script e faça com que esse script entregue o arquivo favicon correto. Tenho certeza de que ainda haverá alguns problemas interessantes com o cache, se você quiser voltar e voltar no mesmo navegador entre diferentes favicons.

Greg
fonte
3

Existe uma solução de linha única para quem usa jQuery:

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

Ou se você quiser um emoticon :)

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());

Adereços para https://koddsson.com/posts/emoji-favicon/

max4ever
fonte
2

De acordo com o WikiPedia , você pode especificar qual arquivo favicon carregar usando a linktag na headseção, com um parâmetro derel="icon" .

Por exemplo:

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

Imagino que se você quisesse escrever algum conteúdo dinâmico para essa chamada, teria acesso aos cookies para recuperar as informações da sessão dessa maneira e apresentar o conteúdo apropriado.

Você pode se deparar com os formatos de arquivo (o IE suporta apenas o formato .ICO, enquanto quase todos os outros suportam imagens PNG e GIF) e, possivelmente, problemas de cache, tanto no navegador quanto por meio de proxies. Isso seria devido à intenção original do favicon, especificamente, para marcar um marcador com o mini-logotipo de um site.

staticsan
fonte
muito mais do que isso. stackoverflow.com/a/45301651/661584 as perguntas frequentes / informações no site do gerador o surpreenderão - há muito nesse assunto.
MemeDeveloper
3
A web muda muito em 9 anos.
staticsan
2

Sim totalmente possível

  • Use uma string de consulta após o favicon.ico (e outros links de arquivos - veja o link de resposta abaixo)
  • Simplesmente verifique se o servidor responde ao "someUserId" com o arquivo de imagem correto (que pode ser regras de roteamento estático ou código dinâmico do lado do servidor).

por exemplo

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

Então qualquer servidor linguagem do lado / framework que você usa deve facilmente ser capaz de encontrar o arquivo com base na userId e servi-lo em resposta a esse pedido .

Mas para fazer favicons corretamente (é realmente um assunto realmente complexo ), consulte a resposta aqui https://stackoverflow.com/a/45301651/661584

Muito mais fácil que trabalhar todos os detalhes.

Aproveitar.

MemeDeveloper
fonte
Sim, o link está bom. Eu acho que a principal razão pela qual essas respostas não funcionam no IE é porque elas não usam esse ícone padrão <link>, mas, em vez disso, procure a apple-touch-iconou alguma outra variante desse tipo.
Alexis Wilke
1

Eu uso o favico.js nos meus projetos.

Permite alterar o favicon para uma variedade de formas predefinidas e também personalizadas.

Internamente, usa canvaspara renderizar ebase64 URL de dados para codificação de ícones.

A biblioteca também possui recursos interessantes: emblemas e animações de ícones; supostamente, você pode até transmitir o vídeo da webcam para o ícone :)

Oscar Nevarez
fonte
O link e a biblioteca são muito úteis; forneça uma descrição de como funciona, para que isso também se torne uma resposta válida à pergunta, conforme indicado.
Dima Tisnek
11
Obrigado @DimaTisnek. Atualizei minha resposta.
Oscar Nevarez
0

Eu uso esse recurso o tempo todo ao desenvolver sites ... para que eu possa ver rapidamente qual guia possui local, dev ou prod em execução.

Agora que o Chrome suporta favicons SVG, fica muito mais fácil.

Tampermonkey Script

Dê uma olhada em https://gist.github.com/elliz/bb7661d8ed1535c93d03afcd0609360f para obter um script tampermonkey que aponta para um site de demonstração no qual eu visitei https://elliz.github.io/svg-favicon/

Código básico

Adaptado de outra resposta ... poderia ser melhorado, mas bom o suficiente para minhas necessidades.

(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;
    }

})();

Basta colocar seu próprio SVG (talvez limpo com o SVGOMG de Jake Archibald, se você estiver usando uma ferramenta) na const, na parte superior. Verifique se ele é quadrado (usando o atributo viewBox) e você está pronto.

Ruskin
fonte