Font color based on background color

Posted on 2002-06-04
Last Modified: 2013-12-03
How can I determine if a lighter/darker font color needs to be used based on the background color?

For example, I have a TLabel. If I change the TLabel's color to a darker shade, I want the font color to be white (so the text can be seen). And if I change the TLabel's color to a lighter shade, I want the font color to be black.

I hope I explained it well enough to make sense. :)

Can anyone help me figure this out?
Question by:Grieg
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
LVL 17

Expert Comment

ID: 7054847
you could ave a color that sets the boundaries ,


to test this try:

procedure TForm1.Button1Click(Sender: TObject);
if label1.Color > clblue then
label1.Font.Color := clwhite else
label1.Font.Color := clblack;

procedure TForm1.Button2Click(Sender: TObject);
label1.color := clFuchsia;

procedure TForm1.Button3Click(Sender: TObject);
label1.color := clyellow;

clFuchsia is greater than blue so it should change to white here if you click the button and clyellow is les so it would chage it back to white.

i would imagine youll want to fire this on a onpaint or onchange event .
there is probably a better way of doing this but thats all i could think of at moment :)
LVL 34

Expert Comment

ID: 7054938
hello Grieg, I tried to use Inverse color font, but for mid grey colors, I could not read the text, I'm not sure about inthe's < clblue value test for color brightness. Here's a sort of less than mid brightness for white version

procedure TForm1.sbut_DoLabelClrClick(Sender: TObject);
NewColor, FontColor: TColor;
NewColor := RGB(Random(255),Random(255),Random(255));
{if (GetRValue(NewColor)+GetGValue(NewColor)+ GetBValue(NewColor) > 300) and
   (GetRValue(NewColor)+ GetGValue(NewColor)+ GetBValue(NewColor) < 468) then
   FontColor := clBlack else
FontColor := RGB(255-GetRValue(NewColor), 255-GetGValue(NewColor), 255-GetBValue(NewColor));}
if GetRValue(NewColor)+ GetGValue(NewColor)+ GetBValue(NewColor) < 440 then
FontColor := clWhite
FontColor := clBlack;
Label5.Color := NewColor;
Label5.Font.Color := FontColor;

- - - - - - - - - - - - - - - - -
you may could make a testing formula for inverse color but the black and white seem to work for the most part

Author Comment

ID: 7054962

The solution doesn't seem to work with non-standard color values. (I tried it with clBlue as the 'boundary color' then chose something a little darker from the windows color dialog.)

I think I failed to mention that I would be working with 'custom' colors from the TColorDialog, and not just the standard 'cl' values.


Accepted Solution

Cynna earned 100 total points
ID: 7055848

A perfect solution for your problem doesn't exist. What looks good to you doesn't have to feel the same to your customer. This is pretty subjective matter, but you can use reasonably good aproximation, as inthe and Slick suggested.
BUT, if you insist on "close to perfect" solution, you have to make decision based on H,S,L components of the color. The most reasonable solution seems to be using L component (luminiscance), because you are trying to answer question "Is this color dark (enough)?".

Cut&Paste this example:

procedure RGBtoHSL(RGB: TColor; var H, S, L: double);
var R, G, B, D, Cmax, Cmin: double;
  R := GetRValue (RGB) / 255;
  G := GetGValue (RGB) / 255;
  B := GetBValue (RGB) / 255;
  Cmax := MaxNo (R, MaxNo (G, B));
  Cmin := MinNo (R, MinNo (G, B));
// calculate luminosity
  L := (Cmax + Cmin) / 2;
// if L is all we need, we could Exit now...
  if Cmax = Cmin then  // it's grey
    H := 0; // it's actually undefined
    S := 0
  end else begin
    D := Cmax - Cmin;
// calculate Saturation
    if L < 0.5 then
      S := D / (Cmax + Cmin)
      S := D / (2 - Cmax - Cmin);
// calculate Hue
    if R = Cmax then
      H := (G - B) / D
      if G = Cmax then
        H  := 2 + (B - R) /D
        H := 4 + (R - G) / D;
    H := H / 6;
    if H < 0 then
      H := H + 1

function IsColorDark(Color: TColor; Limit: Integer): Boolean;
// Test luminiscance of the color against specified
// limit (1-100) percentage
var h,s,l: Double;
  // Get Hue,Saturation,and Luminisc. of specified color:
  RGBtoHSL(Color, h, s, l);
  // Use Luminisc. to make decision about dark/light case:

// A little demo (place Panel and ColorDialog on Form)...
procedure TForm1.Panel1Click(Sender: TObject);
var LimitPercent: Integer;
  if ColorDialog1.Execute then
  LimitPercent:=60; // ...can be between 1 and 100
  if IsColorDark(Panel1.Color, LimitPercent) then


 1. You can adjust "decision level" to value that looks
    best to you (for me, it was 60). Look at the function
    IsColorDark, and you will easily understand.

 2. If you are still not happy, you can base your decision
    not only on L value, but also on H (hue) or even S.

 3. If you are happy with only L value, you can  
    significantly trim this code by excluding H and S

Author Comment

ID: 7056903
After trying the proposed solutions I decided to go with Cynna's answer, as using the Luminiscance value seemed to produce the best results for me. Here is what I came up with using a slightly modified version of Cynna's code:

function IsColorDark(AColor: TColor): Boolean
 R, G, B, CMax, CMin: Double;
 R := GetRValue(AColor) / 255;
 G := GetGValue(AColor) / 255;
 B := GetBValue(AColor) / 255;
 CMax := MaxNo(R, MaxNo(G, B));
 CMin := MinNo(R, MinNo(G, B));

 // Calculate luminosity and make sure it is less
 // then 50%, or 0.5, indicating a darker color
 Result := ((CMax + CMin) / 2)) < 0.5;


Featured Post

Enroll in July's Course of the Month

July's Course of the Month is now available! Enroll to learn HTML5 and prepare for certification. It's free for Premium Members, Team Accounts, and Qualified Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
If you’ve ever visited a web page and noticed a cool font that you really liked the look of, but couldn’t figure out which font it was so that you could use it for your own work, then this video is for you! In this Micro Tutorial, you'll learn yo…
Suggested Courses
Course of the Month5 days, 12 hours left to enroll

626 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question