Emacs's faces let you set :distant-foreground, which according to the docs, "is like :foreground but the color is only used as a foreground when the background color is near to the foreground that would have been used."

I'm not really sure how "near" is computed, but it doesn't seem to be good enough. I would like to use it with my region face, so that the text is in the same face it's normally in, except when it's unreadable. My region is currently set to :background "lightgoldenrod2". Selecting some white text with this makes it unreadable. When I set :distant-foreground "black", it doesn't change.

How is "near" calculated here? How can I adjust this calculation to be a more reasonable contrast calculation?

  • Ancillary question: what is an easy way to create a buffer with text of all different faces that can be selected so I can test this?
    – asmeurer
    Commented Feb 4, 2015 at 20:24
  • When you set :distant-foreground of what - face region? Try to give a recipe to repro the symptoms you see, preferably starting from emacs -Q. And for a buffer showing different faces, try list-faces-display.
    – Drew
    Commented Feb 5, 2015 at 1:56
  • Yes, setting it on region. It's not hard to repro: M-x customize, search for region, set the properties, try selecting colored text.
    – asmeurer
    Commented Feb 5, 2015 at 3:09

3 Answers 3


In Emacs 27.1, there is a new variable face-near-same-color-threshold, which can be adjusted to control when distant-foreground is chosen over foreground:

Threshold for using distant-foreground color instead of foreground.

The value should be an integer number providing the minimum distance
between two colors that will still qualify them to be used as foreground
and background.  If the value of ‘color-distance’, invoked with a nil
METRIC argument, for the foreground and background colors of a face is
less than this threshold, the distant-foreground color, if defined,
will be used for the face instead of the foreground color.

Lisp programs that change the value of this variable should also
clear the face cache, see ‘clear-face-cache’.

It defaults to 30,000. I am currently experimenting with a value of 160,000. I arrived at this value when I noticed that comments in the active region were unreadable, so I rounded up from this result of color-distance:

ELISP> (color-distance (face-foreground 'font-lock-comment-face) (face-background 'region))
150984 (#o446710, #x24dc8)

This very question was even cited in the discussion that resulted in adding this variable: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=34001

  • This is good to see. However, I'm not able to get it to work with region as I described in the question. No matter what I set face-near-same-color-threshold to, it doesn't seem to use the distant-foreground color that I set for region.
    – asmeurer
    Commented Mar 1, 2021 at 21:11
  • @asmeurer Sorry, can't reproduce here. I made some white-on-white text, set region's :background "LightGoldenrod2" :distant-foreground "black" (no :foreground), (progn (setq face-near-same-color-threshold 300000) (clear-face-cache)), then put the white-on-white text in region and I get black on lightgoldenrod2. Possible sources of error: Emacs too old, different display such as TTY or Gtk versus my macOS (NS port), don't forget (clear-face-cache) after changing face-near-same-color-threshold.
    – Dale
    Commented Mar 3, 2021 at 0:25

I found part of the answer by reading the source code. In xfaces.c, there is (in load_face_colors)

  if (!NILP (dfg) && !UNSPECIFIEDP (dfg)
      && color_distance (&xbg, &xfg) < NEAR_SAME_COLOR_THRESHOLD)
      if (EQ (attrs[LFACE_INVERSE_INDEX], Qt))
        face->background = load_color (f, face, dfg, LFACE_BACKGROUND_INDEX);
        face->foreground = load_color (f, face, dfg, LFACE_FOREGROUND_INDEX);


/* Returns the `distance' between the colors X and Y.  */

static int
color_distance (XColor *x, XColor *y)
  /* This formula is from a paper titled `Colour metric' by Thiadmer Riemersma.
     Quoting from that paper:

     This formula has results that are very close to L*u*v* (with the
     modified lightness curve) and, more importantly, it is a more even
     algorithm: it does not have a range of colors where it suddenly
     gives far from optimal results.

     See <http://www.compuphase.com/cmetric.htm> for more info.  */

  long r = (x->red   - y->red)   >> 8;
  long g = (x->green - y->green) >> 8;
  long b = (x->blue  - y->blue)  >> 8;
  long r_mean = (x->red + y->red) >> 9;

    (((512 + r_mean) * r * r) >> 8)
    + 4 * g * g
    + (((767 - r_mean) * b * b) >> 8);



Since this is in C, I think this means that this is not really customizable (maybe by rewriting the C function in lisp).

Doing some research, it would be nice to get an algorithm that uses http://web.mst.edu/~rhall/web_design/color_readability.html (the "Algorithm" section), which gives a formula and a good recommended contrast ratio from W3C.


It works for me, but yes, you need to pick a color that is "nearer" than that for it to take effect. From emacs -Q.

I set face default to have a white foreground and a background of #000000004. And I set face region to have a distant foreground of black and a background of #ffffffff3.

Selecting white text shows the region with black text (foreground). Selecting another color of text (e.g. green foreground) shows the region with that same color (green) as foreground.

Try closer colors to see if it at least works in your Emacs version. I'm on MS Windows and using a dev version of Emacs 25 from last October (2014).

And while you're at it, you might consider filing an Emacs bug (M-x report-emacs-bug) for (at least) insufficient doc. If there isn't already (and I couldn't find any in the doc or in NEWS), there should perhaps be a user option, to let you control how close "near" needs to be for :distant-foreground to kick in.

  • I'm not denying that it doesn't work. I'm asking how to make it useful. Your "try closer colors" advice is strange. I have lots of colors from lots of faces. I want my region face to work well with all of them. Obviously if I only had one face then distant-foreground would be useless, because it's easy to find two colors that aren't close.
    – asmeurer
    Commented Feb 5, 2015 at 16:38
  • I understand. How to make it useful is precisely the question. That's why I suggested M-x report-emacs-bug. That's for bug reports and enhancement requests. However you want to look at this issue, there is room for improvement, IMO. Users should be able to customize how near "near" is, etc., and be guided in that. Currently, I see no relevant doc or user options.
    – Drew
    Commented Feb 5, 2015 at 16:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.