Q:

RGB to Color Name Mapping (Approximate Color Mapping)

I'm building Color picker. If user picks a color square, it converts to approximate color name. 
For example, if user picks colors for C0C0C0 or BEBEBE, both color string will be converted to grey even though each color have a specific color name.
I can't even figure out how I can approach this problem and Google didn't help me either! :( 
Here is my sudo code for the color function
getApproxColor = (colorString) => {
    if(`BBBBBB` <= colorString  <= 'CCCCCC') {
        return 'grey'
    }
    ...
}

Should I write whole color name on this function? Is there any formula for hex color? 

A:

I am not sure if it is the best way, but if I ever had to do something like this, I think I would first convert these hex values to hsl.
Then you would have to check for saturation and luminance in order to find grays and add more granularity in your findings.
Here is a rough proof of concept using only 6 base colors and with a stolen code from an older question to do this hex => hsl conversion.

inp.oninput = e => {
  if (!inp.checkValidity()) return;
  var val = inp.value;
  if (val.length !== 3 && val.length !== 6) return;
  var color = hexToName(inp.value);
  if (color) {
    inp.style.backgroundColor = '#' + val;
    log.textContent = color;
  }
}


function hexToName(hex) {
  // first get hsl correspondance
  var hsl = hexToHsl(hex);
  if(!hsl){
    return;
  }
  // get the base color
  var color = getColorName(hsl[0] * 360);
  // check saturation and luminosity
  // needs more granularity, left as an exercise for the reader
  if (hsl[1] < .5) {
    return hsl[2] <= .5 ? hsl[2] === 0? 'black' : 'darkgray' : hsl[2] === 1 ? 'white': 'gray';
  }
  return hsl[2] <= .5 ? color : 'light' + color;
}
function getColorName(hue) {
  // here you will need more work:
  // we use fixed distance for this simple demo
  var names = ['red', 'yellow', 'green', 'cyan', 'blue', 'magenta'];
  var angles = [0, 60, 120, 180, 240, 300];
  var match = angles.filter(a =>
    a - 60 <= hue && a + 60 > hue
  )[0] || 0;
  return names[angles.indexOf(match)];
}
// shamelessly stolen from https://stackoverflow.com/a/3732187/3702797
function hexToHsl(hex) {
  if (hex.length === 3) {
    hex = hex.split('').map(c => c.repeat(2)).join('');
  }
  if (hex.length !== 6) {
    return;
  }
  var r = parseInt(hex[0] + hex[1], 16);
  var g = parseInt(hex[2] + hex[3], 16);
  var b = parseInt(hex[4] + hex[5], 16);

  r /= 255, g /= 255, b /= 255;
  var max = Math.max(r, g, b),
    min = Math.min(r, g, b);
  var h, s, l = (max + min) / 2;

  if (max == min) {
    h = s = 0; // achromatic
  } else {
    var d = max - min;
    s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
    switch (max) {
      case r:
        h = (g - b) / d + (g < b ? 6 : 0);
        break;
      case g:
        h = (b - r) / d + 2;
        break;
      case b:
        h = (r - g) / d + 4;
        break;
    }
    h /= 6;
  }

  return [h, s, l];
}
#<input id="inp" type="text" pattern="[0-9a-fA-F]+">
<pre id="log"><pre>

