¿Cómo comprobar si una cadena es una representación de color hexadecimal válida?

120

Por ejemplo:

AA33FF = color hexadecimal válido

Z34FF9 = color hexadecimal no válido (tiene Z)

AA33FF11 = color hexadecimal no válido (tiene caracteres adicionales)

Alex
fuente
10
dependiendo del contexto, el último podría ser un color válido, si incluye alfa en AARRGGBBformato.
J. Holmes

Respuestas:

283
/^#[0-9A-F]{6}$/i.test('#AABBCC')

Elaborar:

^ ->coincide con el comienzo de
# ->un hash
[0-9A-F] ->cualquier número entero de 0 a 9 y cualquier letra de la A a la F,
{6} ->el grupo anterior aparece exactamente 6 veces
$ ->coincide con el final
i ->ignora el caso

Si necesita soporte para códigos HEX de 3 caracteres, use lo siguiente:

/^#([0-9A-F]{3}){1,2}$/i.test('#ABC')

La única diferencia aquí es que

 [0-9A-F]{6}

es reemplazado por

([0-9A-F]{3}){1,2}

Esto significa que en lugar de coincidir exactamente con 6 caracteres, coincidirá exactamente con 3 caracteres, pero 1 o 2 veces. Permitiendo ABCy AABBCC, pero noABCD

Royi Namir
fuente
18
Por definición, esto es correcto, pero los códigos con una longitud de 3 también son válidos para la interpretación del navegador. color: #f00;también se interpretará como rojo (# ff0000).
Smamatti
13
u otra forma:/^#[0-9a-f]{3}(?:[0-9a-f]{3})?$/i.test("#f00")
J. Holmes
8
También agregaría /^#([0-9a-f]{3}){1,2}$/ia la mezcla.
MasterAM
1
@AndresSepar /^#[0-9A-F]{3,6}$/i.test('#aabb')también pasa, pero #aabbno es un color hexadecimal válido.
Roman Boiko
3
var isOk = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/i.test('#aabbcc '); @RomanBoiko ¡esto es correcto! ¡Gracias!
Andres Separ
32

// regular function
function isHexColor (hex) {
  return typeof hex === 'string'
      && hex.length === 6
      && !isNaN(Number('0x' + hex))
}

// or as arrow function (ES6+)
isHexColor = hex => typeof hex === 'string' && hex.length === 6 && !isNaN(Number('0x' + hex))

console.log(isHexColor('AABBCC'))   // true
console.log(isHexColor('AABBCC11')) // false
console.log(isHexColor('XXBBCC'))   // false
console.log(isHexColor('AAXXCC'))   // false

Esta respuesta solía arrojar falsos positivos porque en lugar de Number('0x' + hex), usaba parseInt(hex, 16).
parseInt()analizará desde el principio de la cadena hasta que alcance un carácter que no esté incluido en la base ( 16). Esto significa que podría analizar cadenas como 'AAXXCC', porque comienza con 'AA'.

Number(), por otro lado, solo analizará si toda la cadena coincide con la base. Ahora, Number()no toma un parámetro de radix, pero afortunadamente, puede prefijar literales de números para obtener un número en otros radios.

Aquí hay una tabla para aclarar:

╭─────────────┬────────────┬────────┬───────────────────╮
 Radix        Characters  Prefix  Will output 27    
╞═════════════╪════════════╪════════╪═══════════════════╡
 Binary       0-1         0b      Number('0b11011') 
 Octal        0-7         0o      Number('0o33')    
 Decimal      0-9         -       -                 
 Hexadecimal  0-9A-F      0x      Number('0x1b')    
╰─────────────┴────────────┴────────┴───────────────────╯
fflorent
fuente
6
+1 bcs mucho mejor de leer y más rápido de entender que una expresión regular
Chris
10
@Chris 'porque' también es mucho mejor de leer y más rápido de entender que 'bcs' ;-)
Chris
1
@Chris: Me acostumbré tanto a 'bcs' para mí que no hace la diferencia. De todos modos, mi comentario fue un cumplido, así que alégrate.
Chris
12
Esto es incorrecto: parseInt ('abcZab', 16) generará un número y pasará la prueba
Salvador Dali
1
@fflorent Porque parseInttomará "abcZab", encontrará que "Z"no es válido (para la base 16) e ignórelo y cualquier cosa después de él. Luego toma el principio "abc"y lo convierte en 2748(que también es el resultado de parseInt("abcZab", 16), demostrando que esa es la lógica). Como su nombre lo indica, parseInt analiza una cadena. Al igual que si estuvieras analizando un número con unidades con una base de 10, parseInt("10px", 10)obtendrías 10. Puede verlo descrito aquí: es5.github.io/#x15.1.2.2 (paso 11)
Ian
8

Este puede ser un problema complicado. Después de varios intentos, se me ocurrió una solución bastante limpia. Deje que el buscador haga el trabajo por usted.

Paso 1: crea un div con el estilo de borde establecido en ninguno. El div se puede colocar fuera de la pantalla o puede ser cualquier div en su página que no use los bordes.

Paso 2: establece el color del borde en una cadena vacía. El código podría verse así:

e=document.getElementbyId('mydiv');
e.style.borderColor="";

Paso 3: establece el color del borde en el color del que no estás seguro.

e.style.borderColor=testcol;

Paso 4: Verifique si el color realmente cambió. Si testcol no es válido, no se producirá ningún cambio.

col2=e.style.borderColor;
if(col2.length==0) {alert("Bad Color!");}

Paso 5: Limpia después de ti mismo estableciendo el color nuevamente en una cuerda vacía.

e.style.borderColor="";

La Div:

<div id="mydiv" style="border-style:none; position:absolute; left:-9999px; top:-9999px;"></div>

Ahora la función de JavaScript:

function GoodColor(color)
{
   var color2="";
   var result=true;
   var e=document.getElementById('mydiv');
   e.style.borderColor="";
   e.style.borderColor=color;
   color2=e.style.borderColor;
   if (color2.length==0){result=false;}
   e.style.borderColor="";
   return result;
}

En este caso, la función devuelve una respuesta de verdadero / falso a la pregunta, la otra opción es que devuelva un valor de color válido. Su valor de color original, el valor de borderColor o una cadena vacía en lugar de colores no válidos.

Terry Prothero
fuente
En mi opinión, esta no es una solución limpia en lo más mínimo
Gust van de Wal
5

Si está intentando usarlo en HTML, intente usar este patrón directamente:

 pattern="^#+([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$"

me gusta

<input id="hex" type="text" pattern="^#+([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$" />

Dará una validación para que coincida con el formato solicitado.

Mohit Dhawan
fuente
2
function validColor(color){
  var $div = $("<div>");
  $div.css("border", "1px solid "+color);
  return ($div.css("border-color")!="")
}

https://gist.github.com/dustinpoissant/22ce25c9e536bb2c5a2a363601ba261c

Nota: esto requiere jQuery

Esto funciona para TODOS los tipos de color, no solo para valores hexadecimales. Tampoco no anexar elementos innecesarios al árbol DOM.

Dustin Poissant
fuente
Agradable y fácil y funciona muy bien. Personalmente agregué if (hexString.indexOf ('#') == -1) {return false; } para comprobar si hay un hash como comprobación rudimentaria de que el color era un valor hexadecimal
365SplendidSuns
1

Si necesita una función que le diga si un color es válido, también puede hacer que le brinde algo útil (los valores calculados de ese color) y devuelva nulo cuando no es un color válido. Aquí está mi prueba de una función compatible (Chrome54 y MSIE11) para obtener los valores RGBA de un "color" en cualquiera de los formatos, ya sea 'verde', '#FFF', '# 89abcd' o 'rgb (0,0,128) 'o' rgba (0, 128, 255, 0.5) '.

/* getRGBA:
  Get the RGBA values of a color.
  If input is not a color, returns NULL, else returns an array of 4 values:
   red (0-255), green (0-255), blue (0-255), alpha (0-1)
*/
function getRGBA(value) {
  // get/create a 0 pixel element at the end of the document, to use to test properties against the client browser
  var e = document.getElementById('test_style_element');
  if (e == null) {
    e = document.createElement('span');
    e.id = 'test_style_element';
    e.style.width = 0;
    e.style.height = 0;
    e.style.borderWidth = 0;
    document.body.appendChild(e);
  }

  // use the browser to get the computed value of the input
  e.style.borderColor = '';
  e.style.borderColor = value;
  if (e.style.borderColor == '') return null;
  var computedStyle = window.getComputedStyle(e);
  var c
  if (typeof computedStyle.borderBottomColor != 'undefined') {
    // as always, MSIE has to make life difficult
    c = window.getComputedStyle(e).borderBottomColor;
  } else {
    c = window.getComputedStyle(e).borderColor;
  }
  var numbersAndCommas = c.replace(new RegExp('[^0-9.,]+','g'),'');
  var values = numbersAndCommas.split(',');
  for (var i = 0; i < values.length; i++)
    values[i] = Number(values[i]);
  if (values.length == 3) values.push(1);
  return values;
}
Ábaco
fuente
0

Agregue una verificación de longitud para asegurarse de que no obtenga un falso positivo

function isValidHex(testNum){
  let validHex = false;
  let numLength = testNum.length;
  let parsedNum = parseInt(testNum, 16);
  if(!isNan(parsedNum) && parsedNum.length===numLength){
     validHex = true;
  }
  return validHex;

}

rotato poti
fuente