views:

713

answers:

10

I am creating a UI in which users have the ability to change color values of their pages. What I would like is to take the value assigned to their background color and lighten it a certain amount. I am just looking to achieve a highlight line without having to make new images every time.

Example: The user set the background color to #ECECEC. Now I want a certain elements border to become #F4F4F4 (A color closer to white).

Please let me know if their is a good way to do this with Javascript, PHP, or even jQuery.

Thanks, Brad

A: 

Using jQuery:

$(selector).css('border-color', '#f4f4f4')

Replace selector with selector that will match elements you want to modify. It's hard to write it for you without HTML code.

RaYell
+3  A: 

A simpler solution could be to use the rgba() color constructor in CSS:

border: 1px solid rgba(255,255,255,0.7)

This would create a white border of 70% opacity. Unfortunately, this is not supported in Firefox 2, Opera 9, or any version of IE. It wouldn't be difficult to create alternate versions for these browsers. jQuery example:

$('body').append('<div id="rgbatest" style="color:rgba(0,0,0,0);position:absolute;visibility:hidden">&nbsp;</div>"');
if(!$('#rgbatest').css('color').match(/^rgba/)){
     $('body').addClass('no-rgba');
}
$('#rgbatest').remove();

From here, you can use the .no-rgba class to override rgba colors.

#thisDiv{border: 1px solid rgba(255,255,255,0.7)}
.no-rgba #thisDiv{border: 1px solid #FFF}
cpharmston
I would advice agains rgba since it's not supported by half of the browsers (including IE). Here's the compatibility list: http://css-tricks.com/rgba-browser-support/
RaYell
Yeah, check the update I made; it includes a JavaScript-based check for rgba support.
cpharmston
A: 

Do you want the UI or the code ?

mere-teresa
A: 

I would implement color picker like this one. This is the most user friendly action and is not difficult to implement. With the onSubmit() method.

$(".picker").ColorPicker({
    onSubmit: function(hsb, hex, rgb, el){
        $(el).css({
            'background-color': '#' + hex
        });
        $(el).ColorPickerHide();
    }
});

In my case the 'el' is a div that I want to change the color.

Elzo Valugi
+1  A: 

You need to check the hex to see if it's 3(444) or 6 didgts(444444) and then split each RGB to an integer from the hex.

Then, choose a threshold value of how much closer to what you want(suppose it's split the difference).

66hex = 102dec.

floor((255-102)/2) = 76.

color correct 102 + 76 = 178

178dec = B2hex.

B2 will be your new value(rather than 66)

You will need to do this for all 3 hex pairs.

easement
Just found this: http://www.weberdev.com/get_example-3640.htmlYou'll still need to check for 3 digit hex and then convert to 6 digits.
easement
+1  A: 
var colorString=$(selector).css("background-color");
var colorInt=parseInt(colorString.replace('#',''),16);
colorInt+=parseInt("080808",16);
var newColor = "#" + colorInt.toString(16);

$(selector).css("border-color", newColor);
DLH
+2  A: 

You can use a function like this to lighten a color:

function lighten(color, factor) {
    factor = factor || 0.4;
    var lighter = '#';
    for(var i = 1; i < 6; i += 2) {
        var part = parseInt(color.substr(i, 2), 16);
        part += Math.round((255 - part) * 0.4);
        lighter += (part < 16 ? '0' : '') + part.toString(16);
    }
    return lighter;
}
lighten('#ececec'); // returns '#f4f4f4'

This lightens colors evenly by a percentage rather than a fixed amount.

Prestaul
How would I then implement into a form? I'm a beginner with JS and I would have a form that has the background color input of a Hex. Also would I be able to have it preview the changes live? The page will have a background color and the header element will have a border color that is lightened.
Brad
+1  A: 

An aside: RGB is not a perceptually linear color space. I recommend converting from RGB to HSL, interpolating, then converting back to RGB. I wrote the following PHP code to generate arbitrary perceptually-correct gradients; I suggest turning it into a service which can then be called from PHP or AJAX at need.

You can get your final hex output as

$hexcol = col2string( RGBinterpolate("#ececec", "#ffffff", 0.5) ); // "#f4f4f4"

The code:

// Input:
//   $start as RGB color string,
//   $end as RGB color string,
//   $dist as float in [0.0 .. 1.0] being % distance between start and end colors
// Output:
//   array(int, int, int) being the resulting color in RGB)
function RGBinterpolate( $start, $end, $dist ) {
        $hsl_start = rgb2hsl( getCol($start) );
        $hsl_end = rgb2hsl( getCol($end) );

        // choose the shorter arc of the hue wheel!
        if ($hsl_start[0] > $hsl_end[0]) {
            if ($hsl_start[0] > $hsl_end[0] + 0.5)
             $hsl_start[0] -= 1.0;
        }
        else {
            if ($hsl_end[0] > $hsl_start[0] + 0.5)
             $hsl_end[0] -= 1.0;
        }

        // do linear interpolation in hsl color space
        $hs = interp( $hsl_start[0], $hsl_end[0], $dist );
        $ss = interp( $hsl_start[1], $hsl_end[1], $dist );
        $ls = interp( $hsl_start[2], $hsl_end[2], $dist );

        return hsl2rgb( array( $hs, $ss, $ls ) );
}


// Input: start-value, end-value, % distance as float in [0.0 .. 1.0]
// Output: result of interpolation as float
function interp($start, $end, $dist) {
        return $start + ($end - $start)*$dist;
}


// Input: string in one of the following formats:
//  #XXXXXX        (standard hex code as used in CSS)
//  0xXXXXXX       (same thing written as C longint)
//  #XXX           (equivalent to each-digit-doubled, ie #abc is #aabbcc)
//  000, 000, 000  (decimal triad, each value in 0..255)
//  colorname      (Netscape defined color names)
// Output: array(int, int, int) for legal values, else default value
function getCol($str, $default=array(0,0,0)) {
    global $namedcolors;

        // convert named color to #xxxxxx code
    if( isset($namedcolors[$str]) )
     $str = $namedcolors[$str];  // turn named color into a hex value

    $str = trim($str); // remove leading and trailing whitespace
    $hex = "[0-9a-z]";

        // attempt to match #XXXXXX
    $pat = "/(#)($hex{2})($hex{2})($hex{2})/i";
    if ((preg_match($pat, $str, $arr)) == 1) {
      $r = hexdec($arr[2]);
      $g = hexdec($arr[3]);
      $b = hexdec($arr[4]);

      return array($r, $g, $b);
    }

        // attempt to match 0xXXXXXX
    $pat = "/(0x)($hex{2})($hex{2})($hex{2})/i";
    if ((preg_match($pat, $str, $arr)) == 1) {
      $r = hexdec($arr[2]);
      $g = hexdec($arr[3]);
      $b = hexdec($arr[4]);

      return array($r, $g, $b);
    }

        // attempt to match #XXX
    $pat = "/(#)($hex)($hex)($hex)/i";
    if ((preg_match($pat, $str, $arr)) == 1) {
      $r = hexdec($arr[2]) * 17;
      $g = hexdec($arr[3]) * 17;
      $b = hexdec($arr[4]) * 17;

      return array($r, $g, $b);
    }

    // attempt to match int, int, int
        $pat = "/(\d{1,3})\\s*,\\s*(\d{1,3})\\s*,\\s*(\d{1,3})/i";
    if ((preg_match($pat, $str, $arr)) == 1) {
      $r = 0 + $arr[2];    // implicit cast to int - make explicit?
      $g = 0 + $arr[3];
      $b = 0 + $arr[4];

      return array($r, $g, $b);
    }

        // if none of the above worked, return default value
    return $default;
}


// Input: array(int,int,int) being RGB color in { [0..255], [0..255], [0..255] }
// Output array(float,float,float) being HSL color in { [0.0 .. 1.0), [0.0 .. 1.0), [0.0 .. 1.0) }
function rgb2hsl($rgbtrio) {
    $r = $rgbtrio[0] / 256.0; // Normalize {r,g,b} to [0.0 .. 1.0)
    $g = $rgbtrio[1] / 256.0;
    $b = $rgbtrio[2] / 256.0;

    $h = 0.0;
    $s = 0.0;
    $L = 0.0;

    $min = min($r, $g, $b);
    $max = max($r, $g, $b);
    $delta = $max - $min;
    $L = 0.5 * ( $max + $min );

    if ( $delta < 0.001 ) // This is a gray, no chroma...
    {
     $h = 0.0; // ergo, hue and saturation are meaningless
     $s = 0.0;
    }
    else // Chromatic data...
    {
     if ( $L < 0.5 )   $s = $max / ( $max + $min );
     else     $s = $max / ( 2 - $max - $min );

     $dr = ( (($max - $r) / 6.0) + ($max / 2.0) ) / $max;
     $dg = ( (($max - $g) / 6.0) + ($max / 2.0) ) / $max;
     $db = ( (($max - $b) / 6.0) + ($max / 2.0) ) / $max;

     if ($r == $max)   $h = $db - $dg;
     elseif ($g == $max)  $h = (0.3333) + $dr - $db;
     elseif ($b == $max)  $h = (0.6666) + $dg - $dr;

     if ( $h < 0.0 ) $h += 1.0;
     if ( $h > 1.0 ) $h -= 1.0;
    }

    return array($h, $s, $L);
}


    function Hue_2_RGB( $v1, $v2, $vH ) {
     $v1 = 0.0+$v1;
     $v2 = 0.0+$v2;
     $vH = 0.0+$vH;

     if ( $vH < 0.0 )   $vH += 1.0;
     elseif ( $vH >= 1.0 )  $vH -= 1.0;
     // 0.0 <= vH < 1.0

     if ( $vH < 0.1667 )   return ( $v1 + 6.0*$vH*($v2 - $v1) );
     elseif ( $vH < 0.5 )  return ( $v2 );
     elseif ( $vH < 0.6667 )  return ( $v1 + (4.0-(6.0*$vH ))*($v2 - $v1) );
     else      return ( $v1 );
    }

// Input: array(float,float,float) being HSL color in { [0.0 .. 1.0), [0.0 .. 1.0), [0.0 .. 1.0) }
// Output: array(int,int,int) being RGB color in { [0..255], [0..255], [0..255] }
function hsl2rgb($hsltrio) {
    $h = $hsltrio[0];
    $s = $hsltrio[1];
    $L = $hsltrio[2];

    if ( $s < 0.001 )                       //HSL from 0 to 1
    {
     $r = $L;
     $g = $L;
     $b = $L;
    }
    else
    {
     if ( $L < 0.5 )    $j = $L * ( 1.0 + $s );
     else      $j = ($L + $s) - ($s * $L);

     $i = (2.0 * $L) - $j;

     $r = Hue_2_RGB( $i, $j, $h + 0.3333 );
     $g = Hue_2_RGB( $i, $j, $h );
     $b = Hue_2_RGB( $i, $j, $h - 0.3333 );
    }

    return array( floor(256.0 * $r), floor(256.0 * $g), floor(256.0 * $b) );
}


function col2string($rgbtrio) {
    global $colornames;

    $r = floor( $rgbtrio[0] );
    $g = floor( $rgbtrio[1] );
    $b = floor( $rgbtrio[2] );

    $str = sprintf("#%02x%02x%02x", $r, $g, $b);

    if( isset($colornames[$str]) )
     return $colornames[$str];
    else
     return $str;
}


// All Netscape named colors
$namedcolors = array(
  "aliceblue" => "#f0f8ff",
  "antiquewhite" => "#faebd7",
  "aqua" => "#00ffff",
  "aquamarine" => "#7fffd4",
  "azure" => "#f0ffff",
  "beige" => "#f5f5dc",
  "bisque" => "#ffe4c4",
  "black" => "#000000",
  "blanchedalmond" => "#ffebcd",
  "blue" => "#0000ff",
  "blueviolet" => "#8a2be2",
  "brown" => "#a52a2a",
  "burlywood" => "#deb887",
  "cadetblue" => "#5f9ea0",
  "chartreuse" => "#7fff00",
  "chocolate" => "#d2691e",
  "coral" => "#ff7f50",
  "cornflowerblue" => "#6495ed",
  "cornsilk" => "#fff8dc",
  "crimson" => "#dc143c",
  "cyan" => "#00ffff",
  "darkblue" => "#00008b",
  "darkcyan" => "#008b8b",
  "darkgoldenrod" => "#b8860b",
  "darkgray" => "#a9a9a9",
  "darkgreen" => "#006400",
  "darkgrey" => "#a9a9a9",
  "darkkhaki" => "#bdb76b",
  "darkmagenta" => "#8b008b",
  "darkolivegreen" => "#556b2f",
  "darkorange" => "#ff8c00",
  "darkorchid" => "#9932cc",
  "darkred" => "#8b0000",
  "darksalmon" => "#e9967a",
  "darkseagreen" => "#8fbc8f",
  "darkslateblue" => "#483d8b",
  "darkslategray" => "#2f4f4f",
  "darkslategrey" => "#2f4f4f",
  "darkturquoise" => "#00ced1",
  "darkviolet" => "#9400d3",
  "deeppink" => "#ff1493",
  "deepskyblue" => "#00bfff",
  "dimgray" => "#696969",
  "dimgrey" => "#696969",
  "dodgerblue" => "#1e90ff",
  "firebrick" => "#b22222",
  "floralwhite" => "#fffaf0",
  "forestgreen" => "#228b22",
  "fuchsia" => "#ff00ff",
  "gainsboro" => "#dcdcdc",
  "ghostwhite" => "#f8f8ff",
  "gold" => "#ffd700",
  "goldenrod" => "#daa520",
  "gray" => "#808080",
  "green" => "#008000",
  "greenyellow" => "#adff2f",
  "grey" => "#808080",
  "honeydew" => "#f0fff0",
  "hotpink" => "#ff69b4",
  "indianred" => "#cd5c5c",
  "indigo" => "#4b0082",
  "ivory" => "#fffff0",
  "khaki" => "#f0e68c",
  "lavender" => "#e6e6fa",
  "lavenderblush" => "#fff0f5",
  "lawngreen" => "#7cfc00",
  "lemonchiffon" => "#fffacd",
  "lightblue" => "#add8e6",
  "lightcoral" => "#f08080",
  "lightcyan" => "#e0ffff",
  "lightgoldenrodyellow" => "#fafad2",
  "lightgray" => "#d3d3d3",
  "lightgreen" => "#90ee90",
  "lightgrey" => "#d3d3d3",
  "lightpink" => "#ffb6c1",
  "lightsalmon" => "#ffa07a",
  "lightseagreen" => "#20b2aa",
  "lightskyblue" => "#87cefa",
  "lightslategray" => "#778899",
  "lightslategrey" => "#778899",
  "lightsteelblue" => "#b0c4de",
  "lightyellow" => "#ffffe0",
  "lime" => "#00ff00",
  "limegreen" => "#32cd32",
  "linen" => "#faf0e6",
  "magenta" => "#ff00ff",
  "maroon" => "#800000",
  "mediumaquamarine" => "#66cdaa",
  "mediumblue" => "#0000cd",
  "mediumorchid" => "#ba55d3",
  "mediumpurple" => "#9370db",
  "mediumseagreen" => "#3cb371",
  "mediumslateblue" => "#7b68ee",
  "mediumspringgreen" => "#00fa9a",
  "mediumturquoise" => "#48d1cc",
  "mediumvioletred" => "#c71585",
  "midnightblue" => "#191970",
  "mintcream" => "#f5fffa",
  "mistyrose" => "#ffe4e1",
  "moccasin" => "#ffe4b5",
  "navajowhite" => "#ffdead",
  "navy" => "#000080",
  "oldlace" => "#fdf5e6",
  "olive" => "#808000",
  "olivedrab" => "#6b8e23",
  "orange" => "#ffa500",
  "orangered" => "#ff4500",
  "orchid" => "#da70d6",
  "palegoldenrod" => "#eee8aa",
  "palegreen" => "#98fb98",
  "paleturquoise" => "#afeeee",
  "palevioletred" => "#db7093",
  "papayawhip" => "#ffefd5",
  "peachpuff" => "#ffdab9",
  "peru" => "#cd853f",
  "pink" => "#ffc0cb",
  "plum" => "#dda0dd",
  "powderblue" => "#b0e0e6",
  "purple" => "#800080",
  "red" => "#ff0000",
  "rosybrown" => "#bc8f8f",
  "royalblue" => "#4169e1",
  "saddlebrown" => "#8b4513",
  "salmon" => "#fa8072",
  "sandybrown" => "#f4a460",
  "seagreen" => "#2e8b57",
  "seashell" => "#fff5ee",
  "sienna" => "#a0522d",
  "silver" => "#c0c0c0",
  "skyblue" => "#87ceeb",
  "slateblue" => "#6a5acd",
  "slategray" => "#708090",
  "slategrey" => "#708090",
  "snow" => "#fffafa",
  "springgreen" => "#00ff7f",
  "steelblue" => "#4682b4",
  "tan" => "#d2b48c",
  "teal" => "#008080",
  "thistle" => "#d8bfd8",
  "tomato" => "#ff6347",
  "turquoise" => "#40e0d0",
  "violet" => "#ee82ee",
  "wheat" => "#f5deb3",
  "white" => "#ffffff",
  "whitesmoke" => "#f5f5f5",
  "yellow" => "#ffff00",
  "yellowgreen" => "#9acd32"
);
$colornames = array_flip($namedcolors);
Hugh Bothwell
A: 

Hugh Bothwell's code seems to give sometimes strange answers. When converting ie. RGB #eb69ff to HSL it gives 0.751567320261 1.67763157895 0.703125

At function rgb2hsl($rgbtrio)
if ( $L < 0.5 ) $s = $max / ( $max + $min );
else $s = $max / ( 2 - $max - $min );

Should that code be

if ( $L < 0.5 ) $s = ($max - $min) / ( $max + $min );
else $s = ($max - $min) / ( 2 - $max - $min );

At least after that I can get reasonable RGB values when using RGBinterpolate( $start, $end, $dist )

Kuitsi
A: 

While working recently on adding color schemes to Lablz webapp platform we needed to solve the same problem. Solution provided by Hugh Bothwell points in the right direction, but has a problem. Hugh says after converting from RGB to HSL you need to interpolate Hue, Saturation and Luminosity. But to create shades of the same color you only need to manipulate Luminosity (luminance), otherwise you will end up with a different color. We use this approach on the server side (in Java) to create variations of colors generated by http://colorschemedesigner.com. We also use Luminosity to determine and adjust the contrast between colors so that we never end up with a colored text unreadable on a colored background.

Before ending up with this approach we tried manipulating RGB color space as mentioned in many other answers here and converting from RGB to HSB and changing Brightness. HSL gave the best results as it goes all the way to the slightest shades closer to white, while manipulation of Brightness in HSB will only get you something like a mustard color when brightness for example is increased to the maximum from the brown.

If you like, I can post the java code we developed.

Gene Vayngrib