Como obter o valor da cor hexadecimal em vez do valor RGB?


171

O uso do jQuery a seguir obterá o valor RGB da cor de fundo de um elemento:

$('#selector').css('backgroundColor');

Existe uma maneira de obter o valor hexadecimal em vez do RGB?


2
Sobre um tópico relacionado, existem mais maneiras (e sem dúvida melhores) de converter cores hexadecimais e RGB: stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb Essa roda foi reinventada várias vezes para construir um trem rodoviário. Eu esperava que uma das bibliotecas JS populares, mais simples que menos, tivesse uma função de utilitário.
Michael Scheper

Lembre-se de que alguns navegadores retornam rgba (#, #, #, #), como rgba (0,0,0,0), que é transparente, não preto. O quarto valor é a opacidade, com 1,0 sendo 100% colorido e 0,5 sendo 50%.
Twelve24

Respostas:


141
var hexDigits = new Array
        ("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"); 

//Function to convert rgb color to hex format
function rgb2hex(rgb) {
 rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
 return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}

function hex(x) {
  return isNaN(x) ? "00" : hexDigits[(x - x % 16) / 16] + hexDigits[x % 16];
 }

( Fonte )


7
+1, você pode usar Number.toString (16) - pelo menos para cada dígito hexadecimal (ou bloco com 0 se for menor de 16 anos)
orip

19
-1. Conforme mencionado pelo orip, você pode usar toString (16). Votado por outras ineficiências. Se você declarar hexDigits em todas as chamadas de função, faça-o pelo menos no corpo da função do rgb2hex (não no corpo do hex), para que a matriz não seja redefinida 3 vezes por 1 chamada para rgb2hex. Aprenda também a usar 'var', para não poluir o escopo global.
Matt

3
Esse método não parece muito tolerante em diferenciar espaço em branco ou capitalização. jsfiddle.net/Xotic750/pSQ7d
Xotic750

1
Se você realmente quer ser pedante, pode tornar o regex mais permissivo: rgb.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i)No entanto, o regex fornecido foi projetado para lidar com o formato fornecido por um navegador ao usar o jQuery, e isso não tem as consistências de espaço em branco ou captilização diferentes você está falando sobre. Você também pode usar o mesmo regex e apenas remover todos os espaços em branco e converter em minúsculas antes de fazer a correspondência em rgb. PS Seu exemplo do violino: 'rgb (10, 128,)' Eu não acho que isso seja razoável para testar
fichário

e para mim o retorno de jquery css background-colors vem em formato com rgba, portanto isso não funciona.
Miguel

159

Aqui está a solução mais limpa que escrevi com base na sugestão do @Matt:

function rgb2hex(rgb) {
    rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
    function hex(x) {
        return ("0" + parseInt(x).toString(16)).slice(-2);
    }
    return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}

Alguns navegadores já retornam cores como hexadecimais (no Internet Explorer 8 e abaixo). Se você precisar lidar com esses casos, basta anexar uma condição dentro da função, como o @gfrobenius sugeriu:

function rgb2hex(rgb) {
    if (/^#[0-9A-F]{6}$/i.test(rgb)) return rgb;

    rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
    function hex(x) {
        return ("0" + parseInt(x).toString(16)).slice(-2);
    }
    return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}

Se você estiver usando o jQuery e quiser uma abordagem mais completa, poderá usar os CSS Hooks disponíveis desde o jQuery 1.4.3, como mostrei ao responder a esta pergunta: Posso forçar o retorno do jQuery.css ("backgroundColor") no formato hexadecimal?


2
Sugiro a todos: dê uma olhada na minha resposta aqui para ver uma versão aprimorada usando os ganchos CSS do jQuery .
precisa saber é o seguinte

1
@Ghigo, desculpe, mas você está errado. IE8 já retorna como cores hexadecimal quando chegar o estilo atual, desta forma: document.getElementById("your_id").currentStyle["backgroundColor"]. A função rgb2hex()não é necessária. Aqui está o plugin jQuery usando CSS Ganchos que eu sugeri acima, que já faz todas as validações para recuperar as cores em diferentes navegadores: stackoverflow.com/questions/6177454/...
Erick Petrucelli

2
@Ghigo, acho que você entendeu errado: você NÃO DEVE usar essa função se estiver em um navegador que retorne em HEX. Esta função converte RGB em HEX e apenas isso. Não use quando não estiver em RGB. O fato de você precisar de uma solução mais completa (que detecta se o valor já é RGB, como feito por @ Jim-F) não altera o fato de que essa solução oferece exatamente o que foi solicitado pelo OP. Seu voto negativo não faz sentido, desculpe.
Erick Petrucelli 27/03

4
Sinto muito, mas não concordo. Uma função entre navegadores é sempre melhor do que aquela que precisa de execução com base na detecção do navegador. Op pediu para converter $('#selector').css('backgroundColor')para hex, não um valor rgb para hex. E no IE8, $('#selector').css('backgroundColor')já é hexadecimal, por isso deve ser tratado. É isso aí. Não fique com raiva de mim :)
Ghigo

1
Faça isso pessoal, um liner simples que eu adicionei à rgb2hex()função, obrigado @ErickPetru! Eu tenho que codificar de volta para o IE7, acredite ou não. Com IE7 e 8 .css('backgroundColor')nativos obj.style.backgroundColor, retornará hexadecimal, não RGB, então adicionei isso como a primeira linha norgb2hex() função na resposta fornecida, para que funcione todo o caminho de volta ao IE7: /* IE7&8 will return hex, so no need to run this function if it is already hex. */ if (/^#[0-9A-F]{6}$/i.test(rgb)) return rgb.substring(1, 7); //I'm doing a subtring here because I do not want the leading # symbolEspero que ajude.
Gfrobenius #

61

A maioria dos navegadores parece retornar o valor RGB ao usar:

$('#selector').css('backgroundColor');

Somente o IE (apenas 6 testados até o momento) retorna o valor Hex.

Para evitar mensagens de erro no IE, você pode agrupar a função em uma instrução if:

function rgb2hex(rgb) {
     if (  rgb.search("rgb") == -1 ) {
          return rgb;
     } else {
          rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
          function hex(x) {
               return ("0" + parseInt(x).toString(16)).slice(-2);
          }
          return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]); 
     }
}

1
Este funciona melhor que a maioria dos outros, já que Jim leva em conta o rgba, que é o que o Safari (pelo menos no Mac OS X) usa. Obrigado Jim!
Pascal Lindelauf 6/06/11

1
Ótima solução. Observe que a função retorna letras minúsculas, ou seja, # ff5544 e não # FF5544.
Peter Peter

Esse regex também suporta canais aplha na solução acima rgb = rgb.match (/ ^ rgba? ((\ D +), \ s * (\ d +), \ s * (\ d +) (?:, \ S * (0 \. \ D +))?) $ /);
Henning Winter

trabalho como um encanto
ucMedia

22

Atualizado @ErickPetru para compatibilidade com rgba:

function rgb2hex(rgb) {
    rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
    function hex(x) {
        return ("0" + parseInt(x).toString(16)).slice(-2);
    }
    return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}

Atualizei o regex para corresponder ao valor alfa, se definido, mas não para usá-lo.


Apenas para completar: estou trabalhando em algo que será exportado para o PowerPoint (não pergunte ...) e ele aceita um quarto byte na cadeia hexadecimal do canal alfa, para que você possa usá-lo assim: return hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]) /* Add the alpha channel if it exists */ + (rgb[5] !== undefined ? hex(Math.round(rgb[5] * 255)) : ''); Também estou removendo o #símbolo para torná-lo independente do uso final (pode-se obter a saída e anexá-la 0xpor exemplo, ou deixá-la sem prefixo). Espero que ajude alguém!
Óscar Gómez Alcañiz

10

Aqui está um liner do ES6 que não usa jQuery:

var rgb = document.querySelector('#selector').style['background-color'];
return '#' + rgb.substr(4, rgb.indexOf(')') - 4).split(',').map((color) => parseInt(color).toString(16)).join('');

1
Obrigado, isso me ajudou a incorporá-lo em uma página do Wordpress que retira as barras invertidas do regex nas respostas anteriores.
Jason

5

Aqui está uma versão que também verifica a transparência. Eu precisava disso, pois meu objetivo era inserir o resultado em um atributo de estilo, onde a versão transparente de uma cor hexadecimal é na verdade a palavra "transparente".

function rgb2hex(rgb) {
     if (  rgb.search("rgb") == -1 ) {
          return rgb;
     }
     else if ( rgb == 'rgba(0, 0, 0, 0)' ) {
         return 'transparent';
     }
     else {
          rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
          function hex(x) {
               return ("0" + parseInt(x).toString(16)).slice(-2);
          }
          return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]); 
     }
}

4

Função que retorna a cor de fundo de um elemento em hexadecimal.

function getBgColorHex(elem){
    var color = elem.css('background-color')
    var hex;
    if(color.indexOf('#')>-1){
        //for IE
        hex = color;
    } else {
        var rgb = color.match(/\d+/g);
        hex = '#'+ ('0' + parseInt(rgb[0], 10).toString(16)).slice(-2) + ('0' + parseInt(rgb[1], 10).toString(16)).slice(-2) + ('0' + parseInt(rgb[2], 10).toString(16)).slice(-2);
    }
    return hex;
}

exemplo de uso:

$('#div1').click(function(){
   alert(getBgColorHex($(this));
}

jsfiddle


4

Mesma resposta como resposta de Jim F, mas sintaxe ES6 , portanto, menos instruções:

const rgb2hex = (rgb) => {
  if (rgb.search("rgb") === -1) return rgb;
  rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
  const hex = (x) => ("0" + parseInt(x).toString(16)).slice(-2);
  return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
};

3

classe de cores retirada do seletor de cores de inicialização

// Color object
var Color = function(val) {
    this.value = {
        h: 1,
        s: 1,
        b: 1,
        a: 1
    };
    this.setColor(val);
};

Color.prototype = {
    constructor: Color,

    //parse a string to HSB
    setColor: function(val){
        val = val.toLowerCase();
        var that = this;
        $.each( CPGlobal.stringParsers, function( i, parser ) {
            var match = parser.re.exec( val ),
            values = match && parser.parse( match ),
            space = parser.space||'rgba';
            if ( values ) {
                if (space === 'hsla') {
                    that.value = CPGlobal.RGBtoHSB.apply(null, CPGlobal.HSLtoRGB.apply(null, values));
                } else {
                    that.value = CPGlobal.RGBtoHSB.apply(null, values);
                }
                return false;
            }
        });
    },

    setHue: function(h) {
        this.value.h = 1- h;
    },

    setSaturation: function(s) {
        this.value.s = s;
    },

    setLightness: function(b) {
        this.value.b = 1- b;
    },

    setAlpha: function(a) {
        this.value.a = parseInt((1 - a)*100, 10)/100;
    },

    // HSBtoRGB from RaphaelJS
    // https://github.com/DmitryBaranovskiy/raphael/
    toRGB: function(h, s, b, a) {
        if (!h) {
            h = this.value.h;
            s = this.value.s;
            b = this.value.b;
        }
        h *= 360;
        var R, G, B, X, C;
        h = (h % 360) / 60;
        C = b * s;
        X = C * (1 - Math.abs(h % 2 - 1));
        R = G = B = b - C;

        h = ~~h;
        R += [C, X, 0, 0, X, C][h];
        G += [X, C, C, X, 0, 0][h];
        B += [0, 0, X, C, C, X][h];
        return {
            r: Math.round(R*255),
            g: Math.round(G*255),
            b: Math.round(B*255),
            a: a||this.value.a
        };
    },

    toHex: function(h, s, b, a){
        var rgb = this.toRGB(h, s, b, a);
        return '#'+((1 << 24) | (parseInt(rgb.r) << 16) | (parseInt(rgb.g) << 8) | parseInt(rgb.b)).toString(16).substr(1);
    },

    toHSL: function(h, s, b, a){
        if (!h) {
            h = this.value.h;
            s = this.value.s;
            b = this.value.b;
        }
        var H = h,
        L = (2 - s) * b,
        S = s * b;
        if (L > 0 && L <= 1) {
            S /= L;
        } else {
            S /= 2 - L;
        }
        L /= 2;
        if (S > 1) {
            S = 1;
        }
        return {
            h: H,
            s: S,
            l: L,
            a: a||this.value.a
        };
    }
};

Como usar

var color = new Color("RGB(0,5,5)");
color.toHex()

3

Legível e& Reg-exp grátis (sem Reg-exp)

Eu criei uma função que usa funções básicas legíveis e sem reg-exps.
A função aceita cores nos formatos hex, rgb ou rgba CSS e retorna a representação hexadecimal.
EDIT: houve um erro ao analisar o formato rgba (), corrigido ...

function getHexColor( color ){
    //if color is already in hex, just return it...
    if( color.indexOf('#') != -1 ) return color;
    
    //leave only "R,G,B" :
    color = color
                .replace("rgba", "") //must go BEFORE rgb replace
                .replace("rgb", "")
                .replace("(", "")
                .replace(")", "");
    color = color.split(","); // get Array["R","G","B"]
    
    // 0) add leading #
    // 1) add leading zero, so we get 0XY or 0X
    // 2) append leading zero with parsed out int value of R/G/B
    //    converted to HEX string representation
    // 3) slice out 2 last chars (get last 2 chars) => 
    //    => we get XY from 0XY and 0X stays the same
    return  "#"
            + ( '0' + parseInt(color[0], 10).toString(16) ).slice(-2)
            + ( '0' + parseInt(color[1], 10).toString(16) ).slice(-2)
            + ( '0' + parseInt(color[2], 10).toString(16) ).slice(-2);
}

1
Não funciona com rgba (0,0,0,0). Primeiro: a ordem precisa mudar. .replace("rgba", "") .replace("rgb", "") .replace("(", "") .replace(")", "");Caso contrário, você fica com a0,0,0,0. E retorna # 000000, que é preto, em vez de transparente.
Twelve24

Se o quarto valor em um rgba for 0 (zero), então, para css, esse 'elemento' seria: elemento {color: # 000000, opacidade: 0,0;} que é transparente ou apenas retorna condicionalmente o 'rgba (0,0 , 0,0) 'volta para o chamador.
Twelve24

@ Twelve24 Análise corrigida - Na verdade, notei que antes de ler seu comentário, mas definitivamente obrigado por isso :), Quanto à transparência - a função deve retornar a cor HEXA, ou a "cor base" - para que uma seja de propósito :)
jave.web 18/06/2015

3

Experimentar

// c - color str e.g."rgb(12,233,43)", result color hex e.g. "#0ce92b"
let rgb2hex= c=> '#'+c.match(/\d+/g).map(x=>(+x).toString(16).padStart(2,0)).join``


2

Este parece um pouco melhor:

var rgb = $('#selector').css('backgroundColor').match(/\d+/g);
var r   = parseInt(rgb[0], 10);
var g   = parseInt(rgb[1], 10);
var b   = parseInt(rgb[2], 10);
var hex = '#'+ r.toString(16) + g.toString(16) + b.toString(16);

uma linha mais sucinta:

var rgb = $('#selector').css('backgroundColor').match(/\d+/g);
var hex = '#'+ Number(rgb[0]).toString(16) + Number(rgb[1]).toString(16) + Number(rgb[2]).toString(16);

forçando o jQuery a sempre retornar hex:

$.cssHooks.backgroundColor = {
    get: function(elem) {
        if (elem.currentStyle)
            var bg = elem.currentStyle["backgroundColor"];
        else if (window.getComputedStyle) {
            var bg = document.defaultView.getComputedStyle(elem,
                null).getPropertyValue("background-color");
        }
        if (bg.search("rgb") == -1) {
            return bg;
        } else {
            bg = bg.match(/\d+/g);
            function hex(x) {
                return ("0" + parseInt(x).toString(16)).slice(-2);
            }
            return "#" + hex(bg[0]) + hex(bg[1]) + hex(bg[2]);
        }
    }
}

2

Só para adicionar à resposta de @ Justin acima ..

deveria ser

var rgb = document.querySelector('#selector').style['background-color'];
return '#' + rgb.substr(4, rgb.indexOf(')') - 4).split(',').map((color) => String("0" + parseInt(color).toString(16)).slice(-2)).join('');

Como as funções parse int acima truncam os zeros à esquerda, produz códigos de cores incorretos de 5 ou 4 letras, podendo ser ... ou seja, para rgb (216, 160, 10), produz # d8a0a enquanto # d8a00a.

obrigado


1

Aqui está uma solução que descobri que não gera erros de script no IE: http://haacked.com/archive/2009/12/29/convert-rgb-to-hex.aspx


Nas versões mais antigas do IE, buscar um valor de cor de um objeto usando jquery às vezes pode retornar hex em vez de rgb, enquanto a maioria dos navegadores modernos retornam RGB. A função vinculada à lida com os dois casos de uso
Paul T

1

A resposta de Steven Pribilinskiy diminui os zeros à esquerda, por exemplo # ff0000 se torna # ff00.

Uma solução é anexar um 0 inicial e uma subcadeia dos 2 últimos dígitos.

var rgb = $('#selector').css('backgroundColor').match(/\d+/g);
var hex = '#'+ String('0' + Number(rgb[0]).toString(16)).slice(-2) + String('0' + Number(rgb[1]).toString(16)).slice(-2) + String('0' + Number(rgb[2]).toString(16)).slice(-2);

1

Como a pergunta estava usando JQuery, aqui está um plugin JQuery baseado no código de Daniel Elliott:

$.fn.cssAsHex = function(colorProp) {

    var hexDigits = '0123456789abcdef';

    function hex(x) {
        return isNaN(x) ? '00' : hexDigits[(x - x % 16) / 16] + hexDigits[x % 16];
    };

    // Convert RGB color to Hex format
    function rgb2hex(rgb) {
        var rgbRegex = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
        return '#' + hex(rgbRegex[1]) + hex(rgbRegex[2]) + hex(rgbRegex[3]);
    };

    return rgb2hex(this.css(colorProp));
};

Use-o como:

var hexBackgroundColor = $('#myElement').cssAsHex('background-color');

0

Aqui está a minha solução, também faz caso do uso de um argumento e verifica outros possíveis espaços em branco e letras maiúsculas na string fornecida.

var a = "rgb(10, 128, 255)";
var b = "rgb( 10, 128, 255)";
var c = "rgb(10, 128, 255 )";
var d = "rgb ( 10, 128, 255 )";
var e = "RGB ( 10, 128, 255 )";
var f = "rgb(10,128,255)";
var g = "rgb(10, 128,)";

var rgbToHex = (function () {
    var rx = /^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i;

    function pad(num) {
        if (num.length === 1) {
            num = "0" + num;
        }

        return num;
    }

    return function (rgb, uppercase) {
        var rxArray = rgb.match(rx),
            hex;

        if (rxArray !== null) {
            hex = pad(parseInt(rxArray[1], 10).toString(16)) + pad(parseInt(rxArray[2], 10).toString(16)) + pad(parseInt(rxArray[3], 10).toString(16));

            if (uppercase === true) {
                hex = hex.toUpperCase();
            }

            return hex;
        }

        return;
    };
}());

console.log(rgbToHex(a));
console.log(rgbToHex(b, true));
console.log(rgbToHex(c));
console.log(rgbToHex(d));
console.log(rgbToHex(e));
console.log(rgbToHex(f));
console.log(rgbToHex(g));

Em jsfiddle

Comparação de velocidade em jsperf

Uma melhoria adicional poderia ser trim()a rgbstring

var rxArray = rgb.trim().match(rx),

0

Minha bela solução não-padrão

HTML

<div id="selector" style="background-color:#f5b405"></div>

jQuery

$("#selector").attr("style").replace("background-color:", "");

Resultado

#f5b405

1
Retorna tudo no estilo. : c
Eddie
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.