Làm thế nào để kiểm tra xem một chuỗi có phải là biểu diễn màu hex hợp lệ không?


120

Ví dụ:

AA33FF = màu hex hợp lệ

Z34FF9 = màu hex không hợp lệ (có Z trong đó)

AA33FF11 = màu hex không hợp lệ (có thêm ký tự)


10
tùy thuộc vào ngữ cảnh, màu cuối cùng có thể là màu hợp lệ, nếu nó có AARRGGBBđịnh dạng alpha .
J. Holmes

Câu trả lời:


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

Để giải thích:

^ ->khớp bắt đầu
# ->một băm
[0-9A-F] ->bất kỳ số nguyên nào từ 0 đến 9 và bất kỳ chữ cái nào từ A đến F
{6} ->trong nhóm trước đó xuất hiện đúng 6 lần
$ ->khớp kết thúc
i -> bỏ qua trường hợp

Nếu bạn cần hỗ trợ cho mã HEX 3 ký tự, hãy sử dụng các cách sau:

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

Sự khác biệt duy nhất ở đây là

 [0-9A-F]{6}

được thay thế bằng

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

Điều này có nghĩa là thay vì khớp chính xác 6 ký tự, nó sẽ khớp chính xác 3 ký tự, nhưng 1 hoặc 2 lần. Cho phép ABCAABBCCnhưng khôngABCD


18
Theo định nghĩa, điều này đúng, nhưng các mã có độ dài 3 cũng hợp lệ để giải thích trình duyệt. color: #f00;cũng sẽ được hiểu là màu đỏ (# ff0000).
Smamatti

13
hoặc hình thức khác:/^#[0-9a-f]{3}(?:[0-9a-f]{3})?$/i.test("#f00")
J. Holmes

8
Tôi cũng sẽ thêm /^#([0-9a-f]{3}){1,2}$/ivào hỗn hợp.
MasterAM

1
@AndresSepar /^#[0-9A-F]{3,6}$/i.test('#aabb')cũng vượt qua, nhưng #aabbkhông phải là màu hex hợp lệ.
Roman Boiko

3
var isOk = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/i.test('#aabbcc '); @RomanBoiko điều này là đúng! Cảm ơn!
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

Câu trả lời này được sử dụng để đưa ra kết quả dương tính giả vì thay vì Number('0x' + hex), nó được sử dụng parseInt(hex, 16).
parseInt()sẽ phân tích cú pháp từ đầu chuỗi cho đến khi nó gặp ký tự không có trong cơ số ( 16). Điều này có nghĩa là nó có thể phân tích cú pháp các chuỗi như 'AAXXCC', vì nó bắt đầu bằng 'AA'.

Number()mặt khác, sẽ chỉ phân tích cú pháp nếu toàn bộ chuỗi khớp với cơ số. Bây giờ, Number()không lấy tham số cơ số, nhưng may mắn thay, bạn có thể đặt trước các chữ số để lấy một số ở bán kính khác.

Đây là một bảng để làm rõ:

╭─────────────┬────────────┬────────┬───────────────────╮
 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')    
╰─────────────┴────────────┴────────┴───────────────────╯

6
+1 bcs tốt hơn nhiều để đọc và hiểu nhanh hơn so với regex
Chris

10
@ Chris 'vì' được cũng tốt hơn nhiều để đọc và nhanh hơn để hiểu hơn 'BCS' ;-)
Chris

1
@Chris: Tôi đã quá quen với 'bcs' đối với tôi không tạo ra sự khác biệt. Dù sao thì bình luận của tôi cũng chỉ là một lời khen nên hãy vui lên.
Chris

12
Điều này là sai: parseInt ('abcZab', 16) sẽ xuất ra số và vượt qua bài kiểm tra
Salvador Dali

1
@fflorent Because parseIntwill take "abcZab", thấy rằng "Z"nó không hợp lệ (đối với cơ số 16), và bỏ qua nó và bất cứ thứ gì sau nó. Sau đó "abc", nó bắt đầu và chuyển đổi nó thành 2748(cũng là kết quả của parseInt("abcZab", 16), chứng minh đó là logic đang xảy ra). Như tên của nó, parseInt phân tích cú pháp một chuỗi. Giống như nếu bạn đang phân tích cú pháp một số với các đơn vị trên đó có cơ số 10, chẳng hạn như parseInt("10px", 10)bạn sẽ nhận được 10. Bạn có thể thấy nó được mô tả ở đây: es5.github.io/#x15.1.2.2 (bước 11)
Ian

8

Đây có thể là một vấn đề phức tạp. Sau nhiều lần thử, tôi đã nghĩ ra một giải pháp khá sạch sẽ. Hãy để người duyệt web làm công việc cho bạn.

Bước 1: Tạo một div với kiểu đường viền được đặt thành không. Div có thể được đặt ngoài màn hình hoặc nó có thể là bất kỳ div nào trên trang của bạn không sử dụng đường viền.

Bước 2: Đặt màu đường viền thành một chuỗi trống. Mã có thể trông giống như sau:

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

Bước 3: Đặt màu viền thành màu mà bạn không chắc chắn.

e.style.borderColor=testcol;

Bước 4: Kiểm tra xem màu sắc có thực sự bị thay đổi hay không. Nếu testcol không hợp lệ, sẽ không có thay đổi nào xảy ra.

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

Bước 5: Tự dọn dẹp bằng cách thiết lập màu trở lại chuỗi trống.

e.style.borderColor="";

Bộ phận:

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

Bây giờ là hàm 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;
}

Trong trường hợp này, hàm đang trả về câu trả lời đúng / sai cho câu hỏi, tùy chọn khác là để nó trả về giá trị màu hợp lệ. Giá trị màu gốc của bạn, giá trị từ borderColor hoặc một chuỗi trống thay cho các màu không hợp lệ.


IMO, đây không phải là một giải pháp sạch trong ít nhất
Gust van de Wal

5

Nếu bạn đang cố gắng sử dụng nó trong HTML Hãy thử sử dụng trực tiếp mẫu này:

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

giống

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

Nó sẽ cung cấp một xác nhận để phù hợp với định dạng được yêu cầu.


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

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

Lưu ý: Điều này yêu cầu jQuery

Điều này hoạt động cho TẤT CẢ các loại màu không chỉ các giá trị hex. Nó cũng không nối các phần tử không cần thiết vào cây DOM.


Đẹp và dễ dàng và hoạt động rất tốt. Cá nhân tôi đã thêm if (hexString.indexOf ('#') == -1) {return false; } Để kiểm tra một hash như một tấm séc thô sơ mà màu sắc là một giá trị hex
365SplendidSuns

1

Nếu bạn cần một hàm cho bạn biết liệu một màu có hợp lệ hay không, bạn cũng có thể hàm nó cung cấp cho bạn một thứ hữu ích - các giá trị được tính toán của màu đó - và trả về null khi nó không phải là màu hợp lệ. Đây là công việc của tôi đối với chức năng tương thích (Chrome54 & MSIE11) để nhận các giá trị RGBA của "màu" ở bất kỳ định dạng nào - có thể là 'xanh lá cây' hoặc '#FFF' hoặc '# 89abcd' hoặc 'rgb (0,0,128) 'hoặc' 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;
}

0

Thêm kiểm tra độ dài để đảm bảo rằng bạn không bị dương tính giả

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;

}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.