Validating css color names
I've written a jQuery plugin that accepts css colors for some of its parameters.
I want to validate them. If it was just a hex or rgb value I could do that with a regular expression, but how do I validate all 147 valid color names without bloating the plugin?
I was wondering if there is some way of attempting to apply a style (maybe with jquery) and then catching an error from the browser if it is not valid?
Edit: powtac and Pantelis came up with a solution, but they both missed edge cases, so I am including a full solution here:
var validateCssColour = function(colour){
var rgb = $('<div style="color:#28e32a">'); // Use a non standard dummy colour to ease checking for edge cases
var valid_rgb = "rgb(40, 227,开发者_开发百科 42)";
rgb.css("color", colour);
if(rgb.css('color') == valid_rgb && colour != ':#28e32a' && colour.replace(/ /g,"") != valid_rgb.replace(/ /g,""))
return false;
else
return true;
};
I know this question is fairly old but I came up with a pure javascript solution for checking colors which seems to work in every browser and wanted to share it
This function uses the browser to convert any input string into a CSS color string (if possible)
function getColorCSS(c) {
const ele = document.createElement("div");
ele.style.color = c;
return ele.style.color.replace(/\s+/,'').toLowerCase();
}
UPDATE: The beauty of using the browser itself to render color strings is that it continues to work with newer formats like 8 digit hex (where the last 2 digits represent alpha)...
Let's take a look at the function output based on different inputs...
INVALID INPUTS
Basically anytime the browser can't figure out how to render the input string as a color an empty string
is returned which makes this tiny function perfect for detecting invalid color strings!
redd
,#f0gf0g
,#1234
,f00
,rgb(1,2)
,rgb(1,2,3.0)
,rgb(1,2,3,4)
,rgba(100,150,200)
VALID INPUTS
tomato
tomato
. . . chrometomato
. . . firefoxtomato
. . . internet explorer
#f00
,#ff0000
,rgb(255,0,0)
rgb(255,0,0)
. . . chromergb(255,0,0)
. . . firefoxrgb(255,0,0)
. . . internet explorer
rgba(255,0,0,1.0)
,rgba(255,0,0,100)
rgb(255,0,0)
. . . chrome convertsrgba
torgb
anytime alpha is1.0
or greater since it's fully opaque anyway (probably for performance)rgb(255,0,0)
. . . firefox does the same thing as chromergba(255,0,0,1)
. . . internet explorer converts the alpha param from1.0
or greater to1
rgba(0,255,0,0.5)
rgba(0,255,0,0.498039)
. . . chrome returns something different than the other browsers (possibly trading accuracy for performance)rgba(0,255,0,0.5)
. . . firefoxrgba(0,255,0,0.5)
. . . internet explorer
rgba(0,0,255,0.0)
,rgba(0,0,255,-100)
rgba(0,0,255,0)
. . . chrome converts the alpha param from0.0
or lower to0
rgba(0,0,255,0)
. . . firefox does the samergba(0,0,255,0)
. . . internet explorer does the same
rgba(0,0,0,0)
,rgba(0,0,0,-100)
rgba(0,0,0,0)
. . . chrometransparent
. . . firefox converts only this onergba
instance with all parameters set to0
to the wordtransparent
(strange)rgba(0,0,0,0)
. . . internet explorer
hsl(180,50%,50%)
rgb(63,191,191)
. . . chrome- ff
rgb(63,191,191)
. . . firefox - ie
hsl(180,50%,50%)
. . . internet explorer
hsl(x,x,0%)
rgb(0,0,0)
. . . chromergb(0,0,0)
. . . firefoxhsl(0,0%,0%)
. . . internet explorer converts any hsl representation ofblack
to this
hsl(x,x,100%)
rgb(255,255,255)
. . . chromergb(255,255,255)
. . . firefoxhsl(0,0%,100%)
. . . internet explorer converts any hsl representation ofwhite
to this
hsla(180,50%,50%,1.0)
,hsla(180,50%,50%,100)
rgba(63,191,191,1)
. . . chromergba(63,191,191,1)
. . . firefoxhsla(180,50%,50%,1)
. . . internet explorer
hsla(180,50%,50%,0.5)
rgba(63,191,191,0.498039)
. . . chromergba(63,191,191,0.5)
. . . firefoxhsla(180,50%,50%,0.5)
. . . internet explorer
hsla(0,0%,0%,0.0)
,hsla(0,0%,0%,-100)
rgba(0,0,0,0)
. . . chrometransparent
. . . firefox is consistent but this conversion still seems strangehsla(180,50%,50%,0)
. . . internet explorer
Wow, I can hardly believe I just spent 2 hours testing that function in different browsers!
I guess I may as well demo using the function while I'm at it...
function getColorCSS(c) {
var ele = document.createElement("div");
ele.style.color = c;
return ele.style.color.split(/\s+/).join('').toLowerCase();
}
function isColorValid(c) {
var s = getColorCSS(c);
return (s) ? true : false;
}
function isColorTransparent(c) {
var s = getColorCSS(c);
return (
s === "transparent" ||
s.substring(0,4) === "rgba" && +s.replace(/^.*,(.+)\)/,'$1') <= 0 ||
s.substring(0,4) === "hsla" && +s.replace(/^.*,(.+)\)/,'$1') <= 0
);
}
function isColorWhite(c) {
var s = getColorCSS(c);
return [
"white",
"rgb(255,255,255)",
"rgba(255,255,255,1)",
"hsl(0,0%,100%)",
"hsla(0,0%,100%,1)"
].indexOf(s) > -1;
}
function isColorBlack(c) {
var s = getColorCSS(c);
return [
"black",
"rgb(0,0,0)",
"rgba(0,0,0,1)",
"hsl(0,0%,0%)",
"hsla(0,0%,0%,1)"
].indexOf(s) > -1;
}
function checkColorString() {
var c = document.getElementById("c").value;
if (c === "") {
document.getElementsByTagName("body")[0].style.backgroundColor = 'transparent';
document.getElementById("result").innerHTML = '';
}
else if (isColorValid(c)) {
if (isColorTransparent(c)) {
document.getElementsByTagName("body")[0].style.backgroundColor = 'transparent';
document.getElementById("result").innerHTML = '<span style="color:#dadada;">TRANSPARENT</span>';
}
else if (isColorWhite(c)) {
document.getElementsByTagName("body")[0].style.backgroundColor = getColorCSS(c);
document.getElementById("result").innerHTML = '<span style="color:black;">WHITE</span>';
}
else if (isColorBlack(c)) {
document.getElementsByTagName("body")[0].style.backgroundColor = getColorCSS(c);
document.getElementById("result").innerHTML = '<span style="color:white;">BLACK</span>';
}
else {
document.getElementsByTagName("body")[0].style.backgroundColor = getColorCSS(c);
document.getElementById("result").innerHTML = getColorCSS(c);
}
}
else {
document.getElementsByTagName("body")[0].style.backgroundColor = 'transparent';
document.getElementById("result").innerHTML = '<span style="font-size:42px;color:#dadada;">☹</span>';
}
}
var eventList = ["change", "keyup", "paste", "input", "propertychange"];
for(event of eventList) {
document.getElementById("c").addEventListener(event, function() {
checkColorString();
});
}
#c {
width: 300px;
padding: 6px;
font-family: courier;
}
#result {
font-family: courier;
font-size: 24px;
padding: 12px 6px;
}
<input id="c" placeholder="Enter any valid CSS color..."></input>
<div id="result"></div>
All of the solutions posted on this page are incorrect when the string in question is the same colour as the test colour. Granted, you could use a very unlikely choice of colour, but I would prefer to go for 100% success rate.
OP has a single typo in his code (see condition with colon), and does not test for "#28e32a", so that colour will fail, and the regex will collapse whitespace within the colour, so "#28e 32a" would (incorrectly) pass.
In normal JavaScript, this should have 100% success:
function validTextColour(stringToTest) {
//Alter the following conditions according to your need.
if (stringToTest === "") { return false; }
if (stringToTest === "inherit") { return false; }
if (stringToTest === "transparent") { return false; }
var image = document.createElement("img");
image.style.color = "rgb(0, 0, 0)";
image.style.color = stringToTest;
if (image.style.color !== "rgb(0, 0, 0)") { return true; }
image.style.color = "rgb(255, 255, 255)";
image.style.color = stringToTest;
return image.style.color !== "rgb(255, 255, 255)";
}
JSFiddle: http://jsfiddle.net/WK_of_Angmar/xgA5C/
You could simply set the color to a dummy element and then check if the element's value is something other than white.
colorToTest = 'lime'; // 'lightgray' does not work for IE
$('#dummy').css('backgroundColor', 'white');
$('#dummy').css('backgroundColor', colorToTest);
if ($('#dummy').css('backgroundColor') != 'rgb(255, 255, 255)' || colorToTest == 'white') {
alert(colorToTest+' is valid');
}
function test(myColor) {
var valid = $('#test').css('color');
$('#test').css('color', myColor);
if (valid == $('#test').css('color')) alert("INVALID COLOR");
else {
alert("VALID");
$('#test').css('color', valid);
}
}
test("TATATA");
test("white");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="test">asdasdasdasd</div>
It is hastily written but it works.
I think you can use the script from this page that does exactly what you want: you pass a string to it and tries to figure out the color. Ok, it's not exactly what you wanted to do but it should work.
I think that in any case at some point you should do a name lookup (i don't think there is some magic way to determine the hex value from the string "light blue") so just snatch the work some one else has done (the script is by Stoyan Stefanov which is very good at javascript, i've read some good books from him, and if he does a lookup, well, i don't think there is another solution)
Short JavaScript version
Inspired by Valen's answer:
v=c=>((s=document.head.style).color=c,q=s.color,s.color='',!!q);
// v('red') => true
// v('reeeed') => false
More readably:
const validColor = c => {
document.head.style.color = c;
const q = document.head.style.color;
document.head.style.color = '';
return !!q
};
crazy thought
function isValidCssColor(c){
// put !! to normalize to boolean
return [
document.head.style.color = c,
document.head.style.color,
document.head.style.color = null
][1]; // split it in 3 lines is fine, see snippet
}
I believe it works (only not when your pages doesn't not have a head
element, somehow)
function isValidCssColor(c){
document.head.style.color = c;
let result = document.head.style.color;
document.head.style.color = null;
return result;
}
console.log(isValidCssColor("asdf")); // <empty string>
console.log(isValidCssColor("black")); // black
console.log(isValidCssColor("#abcdee")); // rgb(171, 205, 238) // this is browser dependent I guess
console.log(isValidCssColor("asssdf")); // <empty string>
I'm arriving a little bit late but now I'm using validate-color library on npm
精彩评论