Comment obtenir une valeur de couleur hexadécimale plutôt qu'une valeur RVB?

171

L'utilisation du jQuery suivant obtiendra la valeur RVB de la couleur d'arrière-plan d'un élément:

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

Existe-t-il un moyen d'obtenir la valeur hexadécimale plutôt que RVB?

bfavaretto
la source
2
Sur un sujet connexe, vous trouverez ici plus (et sans doute de meilleures) façons de convertir entre les couleurs hexadécimales et RVB: stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb Cette roue a été réinventée suffisamment de fois pour construire un train routier. J'espérais que l'une des bibliothèques JS populaires, plus simple que moins, aurait une fonction utilitaire.
Michael Scheper
Souvenez-vous que certains navigateurs renvoient rgba (#, #, #, #), comme rgba (0,0,0,0) qui est transparent, pas noir. La 4ème valeur est l'opacité, 1,0 étant 100% en couleur et 0,5 50%.
Twelve24

Réponses:

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

( Source )

Daniel Elliott
la source
7
+1, vous pouvez utiliser Number.toString (16) - au moins pour chaque chiffre hexadécimal (ou pad avec 0 si moins de 16 ans)
orip
19
-1. Comme mentionné par orip, vous pouvez utiliser toString (16). Évalué pour d'autres inefficacités. Si vous allez déclarer hexDigits à chaque appel de fonction, faites-le au moins dans le corps de la fonction de rgb2hex (pas dans le corps de hex), pour que le tableau ne soit pas redéfini 3 fois par 1 appel à rgb2hex. Apprenez également à utiliser «var» pour ne pas polluer la portée globale.
Matt
3
Cette méthode ne semble pas très tolérante aux espaces blancs ou aux majuscules différents. jsfiddle.net/Xotic750/pSQ7d
Xotic750
1
Si vous voulez vraiment être pédant, vous pouvez rendre l'expression régulière plus permissive: rgb.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i)Cependant, l'expression régulière donnée est conçue pour faire face au format donné par un navigateur lors de l'utilisation de jQuery, et cela n'a pas les différentes consistances d'espace blanc ou de captilisation. Tu es en train de parler de. Vous pouvez également utiliser le même regex et simplement supprimer tous les espaces et les convertir en minuscules avant de faire correspondre sur rgb. PS Votre exemple de violon: 'rgb (10, 128,)' Je ne pense pas que ce soit raisonnable de tester
reliure
et pour moi, le retour de jquery css background-colors est au format rgba, donc cela ne fonctionne pas.
Miguel
159

Voici la solution plus propre que j'ai écrite basée sur la suggestion @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]);
}

Certains navigateurs renvoient déjà les couleurs au format hexadécimal (à partir d'Internet Explorer 8 et inférieurs). Si vous devez gérer ces cas, ajoutez simplement une condition à l'intérieur de la fonction, comme @gfrobenius l'a suggéré:

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 vous utilisez jQuery et souhaitez une approche plus complète, vous pouvez utiliser les Hooks CSS disponibles depuis jQuery 1.4.3, comme je l'ai montré en répondant à cette question: Puis-je forcer les retours de jQuery.css ("backgroundColor") au format hexadécimal?

Erick Petrucelli
la source
2
Je suggère à tout le monde: jetez un œil à ma réponse ici pour voir une version améliorée utilisant jQuery CSS Hooks .
Erick Petrucelli
1
@Ghigo, désolé mais vous vous trompez. IE8 retourne déjà les couleurs en hexadécimal lors de l' obtention du style actuel, de cette façon: document.getElementById("your_id").currentStyle["backgroundColor"]. La fonction rgb2hex()n'est pas nécessaire. Voici le plugin jQuery utilisant CSS Hooks que j'ai suggéré ci-dessus, qui effectue déjà toutes les validations pour récupérer les couleurs dans différents navigateurs: stackoverflow.com/questions/6177454/…
Erick Petrucelli
2
@Ghigo, je pense que vous avez mal compris: vous NE DEVRIEZ PAS utiliser cette fonction si vous êtes dans un navigateur qui retourne en HEX. Cette fonction convertit RVB en HEX et tout simplement. Ne l'utilisez pas lorsqu'il n'est pas en RVB. Le fait que vous ayez besoin d'une solution plus complète (qui détecte si la valeur est déjà RVB, comme l'a fait @ Jim-F) ne change pas le fait que cette solution offre exactement ce qui a été demandé par l'OP. Votre vote défavorable n'a aucun sens, désolé.
Erick Petrucelli
4
Je suis désolé mais je ne suis pas d'accord. Une fonction de navigateur croisé est toujours meilleure que celle qui nécessite une exécution basée sur la détection du navigateur. Op a demandé de convertir $('#selector').css('backgroundColor')en hexadécimal, pas une valeur RVB en hexadécimal. Et sur IE8, $('#selector').css('backgroundColor')est déjà hexadécimal donc il doit être manipulé. C'est tout. Ne vous fâchez pas contre moi :)
Ghigo
1
Faites ça les gars, une simple doublure que j'ai ajoutée à la rgb2hex()fonction, merci @ErickPetru! Je dois coder vers IE7, croyez-le ou non. Avec .css('backgroundColor')et obj.style.backgroundColorIE7 et 8 natifs renverront hex, pas RVB, j'ai donc ajouté ceci comme première ligne de la rgb2hex()fonction dans la réponse fournie pour que cela fonctionne jusqu'à 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 # symbolJ'espère que cela aide.
gfrobenius
61

La plupart des navigateurs semblent renvoyer la valeur RVB lors de l'utilisation:

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

Seul IE (seulement 6 testés jusqu'à présent) renvoie la valeur hexadécimale.

Pour éviter les messages d'erreur dans IE, vous pouvez envelopper la fonction dans une instruction 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
la source
1
Celui-ci fonctionne mieux que la plupart des autres, car Jim prend en compte rgba, ce que Safari (du moins sur Mac OS X) utilise. Merci, Jim!
Pascal Lindelauf le
1
Excellente solution. Notez que la fonction renvoie des lettres minuscules, c'est-à-dire # ff5544 et non # FF5544.
Peter le
Cette expression régulière supportera également les canaux aplha dans la solution ci-dessus rgb = rgb.match (/ ^ rgba? ((\ D +), \ s * (\ d +), \ s * (\ d +) (?:, \ S *) (0 \. \ D +))?) $ /);
Henning Winter
travailler comme un charme
ucMedia
22

Mise à jour de @ErickPetru pour la compatibilité 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]);
}

J'ai mis à jour l'expression régulière pour qu'elle corresponde à la valeur alpha si définie, mais je ne l'utilise pas.

Zack Katz
la source
Juste pour être complet: je travaille sur un élément qui va exporter vers PowerPoint (ne demandez pas ...), et il accepte un quatrième octet sur la chaîne hexadécimale pour le canal alpha, donc on peut l'utiliser comme ceci: 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)) : ''); De plus, je supprime le #symbole pour le rendre indépendant de l'utilisation finale (on pourrait obtenir la sortie et l'ajouter 0xpar exemple, ou le laisser sans préfixe). J'espère que cela aide quelqu'un!
Óscar Gómez Alcañiz
10

Voici une ligne ES6 One qui n'utilise pas 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
la source
1
Merci, cela m'a aidé à l'intégrer dans une page Wordpress qui supprime les barres obliques inverses des expressions régulières dans les réponses précédentes.
Jason le
5

Voici une version qui vérifie également la transparence, j'en avais besoin car mon objet était d'insérer le résultat dans un attribut de style, où la version transparente d'une couleur hexadécimale est en fait le mot "transparent".

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
la source
4

Fonction qui renvoie la couleur d'arrière-plan d'un élément en hexadécimal.

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

exemple d'utilisation:

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

jsfiddle

shaik
la source
4

Même réponse que @Jim F, mais syntaxe ES6 , donc moins d'instructions:

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
la source
3

classe de couleur extraite du sélecteur de couleurs 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
        };
    }
};

comment utiliser

var color = new Color("RGB(0,5,5)");
color.toHex()
Tarif Alnamrouti
la source
3

Lisible && Reg-exp gratuit (pas de Reg-exp)

J'ai créé une fonction qui utilise des fonctions de base lisibles et aucune reg-exps.
La fonction accepte la couleur au format CSS hexadécimal, rgb ou rgba et renvoie une représentation hexadécimale.
EDIT: il y avait un bug avec l'analyse du format rgba (), corrigé ...

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
la source
1
Ne fonctionne pas sur rgba (0,0,0,0). Premièrement: l'ordre doit changer .replace("rgba", "") .replace("rgb", "") .replace("(", "") .replace(")", "");Sinon, vous vous retrouvez avec a0,0,0,0. Et, il renvoie # 000000, qui est noir, au lieu de transparent.
Twelve24
Si la 4ème valeur d'un rgba est 0 (zéro), alors pour css pour cet 'élément' serait: element {color: # 000000, opacity: 0.0;} qui est transparent ou renvoie simplement conditionnellement le 'rgba (0,0 , 0,0) 'à l'appelant.
Twelve24
@ Twelve24 Parsing corrigé - j'ai en fait remarqué cela avant de lire votre commentaire, mais certainement merci pour cela :), Quant à la transparence - la fonction est censée renvoyer la couleur HEXA, ou la "couleur de base" - donc c'est exprès :)
jave.web
3

Essayer

// 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
la source
2

Celui-ci a l'air un peu plus joli:

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

un one-liner plus succinct:

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çant jQuery à toujours retourner 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]);
        }
    }
}
Steven Pribilinskiy
la source
2

Juste pour ajouter à la réponse de @ Justin ci-dessus.

ça devrait être

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

Comme les fonctions parse int ci-dessus tronquent les zéros non significatifs, produisant ainsi des codes de couleur incorrects de 5 ou 4 lettres peuvent être ... c'est-à-dire que pour rgb (216, 160, 10), il produit # d8a0a alors qu'il devrait être # d8a00a.

Merci

Yogesh Kumar Gupta
la source
1

Voici une solution que j'ai trouvée qui ne génère pas d'erreurs de script dans IE: http://haacked.com/archive/2009/12/29/convert-rgb-to-hex.aspx

Mike
la source
Dans les anciennes versions d'IE, la récupération d'une valeur de couleur d'un objet à l'aide de jquery peut parfois renvoyer hex au lieu de rgb, alors que la plupart des navigateurs modernes renvoient RVB. La fonction liée à gère les deux cas d'utilisation
Paul T
1

La réponse de Steven Pribilinskiy laisse tomber les zéros non significatifs, par exemple # ff0000 devient # ff00.

Une solution consiste à ajouter un 0 de début et une sous-chaîne des 2 derniers chiffres.

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);
user2874310
la source
1

Puisque la question utilisait JQuery, voici un plugin JQuery basé sur le code 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));
};

Utilisez-le comme:

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

Voici ma solution, fait également touppercase par l'utilisation d'un argument et vérifie d'autres espaces blancs possibles et la capitalisation dans la chaîne fournie.

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

Sur jsfiddle

Comparaison de vitesse sur jsperf

Une autre amélioration pourrait être trim()la rgbchaîne

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

Ma belle solution non standard

HTML

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

jQuery

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

Résultat

#f5b405
Newred
la source
1
Il renvoie tout dans le style. : c
Eddie