¿Cómo obtener el valor de color hexadecimal en lugar del valor RGB?

171

Usando el siguiente jQuery obtendrá el valor RGB del color de fondo de un elemento:

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

¿Hay alguna manera de obtener el valor hexadecimal en lugar del RGB?

bfavaretto
fuente
2
En un tema relacionado, hay más formas (y posiblemente mejores) de convertir entre colores hexadecimales y RGB: stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb Esta rueda se ha reinventado suficientes veces para construir un tren de carretera. Esperaba que una de las bibliotecas JS populares, más simple que menos, tuviera una función de utilidad.
Michael Scheper el
Recuerde que algunos navegadores devuelven rgba (#, #, #, #), como rgba (0,0,0,0) que es transparente, no negro. El cuarto valor es la opacidad, siendo 1.0 el 100% a todo color y 0.5 el 50%.
Doce 24 de

Respuestas:

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

( Fuente )

Daniel Elliott
fuente
77
+1, puede usar Number.toString (16) - al menos para cada dígito hexadecimal (o pad con 0 si es menor de 16)
orip
19
-1. Como lo menciona orip, puede usar toString (16). Votado negativamente por otras ineficiencias. Si va a declarar hexDigits en cada llamada de función, al menos hágalo en el cuerpo de función de rgb2hex (no en el cuerpo de hex), por lo que la matriz no se redefine 3 veces por 1 llamada a rgb2hex. También aprenda a usar 'var', para no contaminar el alcance global.
Matt
3
Este método no parece muy tolerante con los diferentes espacios en blanco o las mayúsculas. jsfiddle.net/Xotic750/pSQ7d
Xotic750
1
Si realmente quiere ser pedante, puede hacer que la expresión regular sea más permisiva: sin rgb.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i)embargo, la expresión regular dada está diseñada para hacer frente al formato dado por un navegador cuando usa jQuery, y esto no tiene las diferentes consistencias de espacio en blanco o de captura. de que estas hablando También puede usar la misma expresión regular y simplemente eliminar todos los espacios en blanco y convertir a minúsculas antes de hacer coincidir en rgb. PD Su ejemplo de violín: 'rgb (10, 128,)' No creo que sea razonable probarlo
2014
y para mí, el regreso de jquery css background-colors viene en formato con rgba, por lo que esto no funciona.
Miguel
159

Aquí está la solución más limpia que escribí en base a la sugerencia de @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]);
}

Algunos navegadores ya devuelven los colores como hexadecimales (a partir de Internet Explorer 8 y posteriores). Si necesita lidiar con esos casos, simplemente agregue una condición dentro de la función, como sugirió @gfrobenius:

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

Si está usando jQuery y desea un enfoque más completo, puede usar CSS Hooks disponibles desde jQuery 1.4.3, como lo mostré al responder esta pregunta: ¿Puedo forzar retornos jQuery.css ("backgroundColor") en formato hexadecimal?

Erick Petrucelli
fuente
2
Sugiero a todos: miren mi respuesta aquí para ver una versión mejorada usando jQuery CSS Hooks .
Erick Petrucelli
1
@ Ghigo, lo siento pero estás equivocado. IE8 ya se vuelve colores como hexadecimal al conseguir el estilo actual, de esta manera: document.getElementById("your_id").currentStyle["backgroundColor"]. La función rgb2hex()no es necesaria. Aquí está el complemento jQuery con CSS Hooks que sugerí anteriormente, que ya hace todas las validaciones para recuperar colores en diferentes navegadores: stackoverflow.com/questions/6177454/…
Erick Petrucelli
2
@Ghigo, creo que malinterpretas: NO DEBES usar esta función si estás en un navegador que regresa en HEX. Esta función convierte RGB a HEX y solo eso. No lo use cuando no esté en RGB. El hecho de que necesite una solución más completa (que detecta si el valor ya es como RGB, como lo hizo @ Jim-F) no cambia el hecho de que esta solución ofrece exactamente lo que solicitó el OP. Su voto negativo no tiene sentido, lo siento.
Erick Petrucelli
44
Lo siento pero no estoy de acuerdo. Una función de navegador cruzado siempre es mejor que una que necesita ejecución basada en la detección del navegador. Op pidió convertir $('#selector').css('backgroundColor')a hexadecimal, no un valor rgb a hexadecimal. Y en IE8, $('#selector').css('backgroundColor')ya es hexadecimal, por lo que debe manejarse. Eso es. No te enojes conmigo :)
Ghigo
1
Haga esto chicos, un simple revestimiento que agregué a la rgb2hex()función, ¡gracias @ErickPetru! Tengo que codificar de nuevo a IE7 lo creas o no. Con .css('backgroundColor')y obj.style.backgroundColorIE7 y 8 nativos devolverán hexadecimal, no RGB, así que agregué esto como la primera línea de la rgb2hex()función en la respuesta suministrada para que funcione todo el camino de regreso a 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 ayude.
gfrobenius
61

La mayoría de los navegadores parecen devolver el valor RGB al usar:

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

Solo IE (solo 6 probados hasta ahora) devuelve el valor Hex.

Para evitar mensajes de error en IE, puede ajustar la función en una declaración 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]); 
     }
}
Jim F
fuente
1
Este funciona mejor que la mayoría de los demás, ya que Jim tiene en cuenta rgba, que es lo que utiliza Safari (al menos en Mac OS X). Gracias Jim!
Pascal Lindelauf
1
Gran solución Tenga en cuenta que la función devuelve letras minúsculas, es decir, # ff5544 no # FF5544.
Peter
Esta expresión regular también admitirá canales aplha en la solución anterior rgb = rgb.match (/ ^ rgba? ((\ D +), \ s * (\ d +), \ s * (\ d +) (?:, \ S * (0 \. \ D +))?) $ /);
Henning Winter
trabajar como un encanto
ucMedia
22

@ErickPetru actualizado para compatibilidad con 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]);
}

Actualicé la expresión regular para que coincida con el valor alfa si está definido, pero no lo uso.

Zack Katz
fuente
Solo para completar: estoy trabajando en una cosa que se exportará a PowerPoint (no pregunte ...), y acepta un cuarto byte en la cadena hexadecimal para el canal alfa, por lo que uno puede usarlo así: 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)) : ''); También estoy eliminando el #símbolo para que sea independiente del uso final (se podría obtener el resultado y anteponerlo, 0xpor ejemplo, o dejarlo sin prefijo). Espero que ayude a alguien!
Óscar Gómez Alcañiz
10

Aquí hay un ES6 one liner que no 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('');
Justin McCandless
fuente
1
Gracias, eso me ayudó a incorporarlo a una página de Wordpress que elimina las barras invertidas de expresiones regulares en las respuestas anteriores.
Jason
5

Aquí hay una versión que también comprueba si es transparente, lo necesitaba ya que mi objetivo era insertar el resultado en un atributo de estilo, donde la versión transparente de un color hexadecimal es en realidad la palabra "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]); 
     }
}
Matt Welander
fuente
4

Función que devuelve el color de fondo de un elemento en 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;
}

ejemplo de uso:

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

jsfiddle

shaik
fuente
4

La misma respuesta que @Jim F answer pero la sintaxis ES6 , por lo tanto, menos instrucciones:

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]);
};
Abdennour TOUMI
fuente
3

clase de color tomada del selector de color bootstrap

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

cómo utilizar

var color = new Color("RGB(0,5,5)");
color.toHex()
Alnamrouti Fareed
fuente
3

Legible && Reg-exp gratis (sin Reg-exp)

He creado una función que utiliza funciones básicas legibles y no reg-exps.
La función acepta color en formato CSS hexadecimal, rgb o rgba y devuelve representación hexadecimal.
EDITAR: hubo un error al analizar el formato rgba (), corregido ...

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);
}
jave.web
fuente
1
No funciona en rgba (0,0,0,0). Primero: el orden debe cambiar. .replace("rgba", "") .replace("rgb", "") .replace("(", "") .replace(")", "");De lo contrario, se quedará con a0,0,0,0. Y, devuelve # 000000, que es negro, en lugar de transparente.
Doce 24 de
Si el 4to valor en un rgba es 0 (cero), entonces para css para ese 'elemento' sería: elemento {color: # 000000, opacidad: 0.0;} que es transparente o simplemente devuelve condicionalmente el 'rgba (0,0 , 0,0) 'de vuelta a la persona que llama.
Doce 24 de
@ Twelve24 Análisis corregido: de hecho, me di cuenta de eso antes de leer su comentario, pero definitivamente gracias por eso :), en cuanto a la transparencia , se supone que la función devuelve el color HEXA o el "color base", de modo que uno es a propósito :)
jave.web
3

Tratar

// 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``

Kamil Kiełczewski
fuente
2

Este se ve un poco mejor:

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

Una frase más 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);

obligando a jQuery a devolver siempre hexadecimal:

$.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]);
        }
    }
}
Steven Pribilinskiy
fuente
2

Solo para agregar a la respuesta de @ Justin arriba ...

debería 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 las funciones parse int anteriores truncan los ceros iniciales, por lo tanto, producen códigos de color incorrectos de 5 o 4 letras que pueden ser ... es decir, para rgb (216, 160, 10) produce # d8a0a mientras que debería ser # d8a00a.

Gracias

Yogesh Kumar Gupta
fuente
1

Aquí hay una solución que encontré que no arroja errores de secuencias de comandos en IE: http://haacked.com/archive/2009/12/29/convert-rgb-to-hex.aspx

Miguel
fuente
En versiones anteriores de IE, obtener un valor de color de un objeto usando jquery a veces puede devolver hexadecimal en lugar de rgb, mientras que la mayoría de los navegadores modernos devuelven RGB. La función vinculada a maneja ambos casos de uso
Paul T
1

La respuesta de Steven Pribilinskiy elimina los ceros a la izquierda, por ejemplo, # ff0000 se convierte en # ff00.

Una solución es agregar un 0 inicial y una subcadena de los últimos 2 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);
usuario2874310
fuente
1

Como la pregunta estaba usando JQuery, aquí hay un complemento de JQuery basado en el 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));
};

Úselo como:

var hexBackgroundColor = $('#myElement').cssAsHex('background-color');
Tom Söderlund
fuente
0

Aquí está mi solución, también hace caso de dudas mediante el uso de un argumento y busca otros posibles espacios en blanco y mayúsculas en la cadena suministrada.

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

En jsfiddle

Comparación de velocidad en jsperf

Una mejora adicional podría ser trim()la rgbcadena

var rxArray = rgb.trim().match(rx),
Xotic750
fuente
0

Mi hermosa solución no estándar

HTML

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

jQuery

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

Resultado

#f5b405
Newred
fuente
1
Devuelve todo en el estilo. : c
Eddie