Invert CSS font-color depending on background-color

Is there a CSS property to invert the font-color depending on the background-color like this picture?

enter image description here


There is a CSS property called mix-blend-mode, but it's not supported by IE. I recommend using pseudo elements. If you like to support IE6 and IE7 you can also use two DIVs instead of pseudo elements.

enter image description here

.inverted-bar {
    position: relative;
}

.inverted-bar:before,
.inverted-bar:after {
    padding: 10px 0;
    text-indent: 10px;
    position: absolute;
    white-space: nowrap;
    overflow: hidden;
    content: attr(data-content);
}

.inverted-bar:before {
    background-color: aqua;
    color: red;
    width: 100%;
}

.inverted-bar:after {
    background-color: red;
    color: aqua;
    width: 20%;
}
<div class="inverted-bar" data-content="Lorem ipsum dolor sit amet"></div>

Use mix-blend-mode.

blend-modes example

http://jsfiddle.net/1uubdtz6/

div {
    position:absolute;
    height:200px
}

/* A white bottom layer */
#whitebg { 
    background: white; 
    width:400px; 
    z-index:1
}

/* A black layer on top of the white bottom layer */
#blackbg { 
    background: black; 
    width:100px; 
    z-index:2
}

/* Some white text on top with blend-mode set to 'difference' */
span {
    position:absolute; 
    font-family: Arial, Helvetica; 
    font-size: 100px; 
    mix-blend-mode: difference;
    color: white;
    z-index: 3
}

/* A red DIV over the scene with the blend-mode set to 'screen' */
#makered { 
    background-color: red;
    mix-blend-mode: screen;
    width:400px; 
    z-index:4
}
<div id="whitebg"></div>
<div id="blackbg"></div>
<div id="makered"></div>

<span>test</span>

I know this is an old question, but I wanted to add another solution I've been using before I learned of mix-blend-mode.

The idea is to have the information duplicated in two layers, a back and a front, where the back and front have different background and text colors. These are identical in dimension and text. In between, I use a clipping box div to crop the front (top) layer to the desired width, showing the front layer where it is not clipped, and revealing the back layer outside of the clipping window.

This is similar to the "Two div" solution in the accepted answer, but uses the extra clipping box. What's advantageous in this solution is the easy centering of text if desired, and simple, direct selection of the colors.

HTML:

<div class='progress' id='back'>
  <span></span>
  <div class='progress' id='boundbox'>
    <div class='progress' id='front'>
    </div>
  </div>
</div>

CSS:

.progress {
  display: block;
  margin: 0;

  /* Choose desired padding/height in coordination with font size */
  padding: 10px;
  height: 28px;
}

#back {
  position: relative;

  /* Choose a border to your liking, or none */
  border: 1px solid lightgray;

  /* Choose your desired text attributes */
  text-align: center;
  font-family: Calibri, "Sans Serif";
  font-size: 16pt;

  /* Set the desired width of the whole progress bar */
  width: 75%;

  /* Choose the desired background and text color */
  background-color: white;
  color: black;
}

#front {
  position: absolute;
  left: 0;
  top: 0;

  /* Choose the desired background and text colors */
  background-color: navy;
  color: white;
}

#boundbox {
  position: absolute;
  left: 0;
  top: 0;
  overflow: hidden;
}

I use jQuery to programmatically set the percent progress and make sure that the width of the front matches that of the back, and that they have the identical text. This can also easily be done with pure Javascript.

// Set *front* width to *back* width
// Do this after DOM is ready
$('#front').width($('#back').width())

// Based upon an event that determines a content change
// you can set the text as in the below example
percent_complete = 45  // obtain this value from somewhere; 45 is just a test

$('#front').text(percent_complete.toString() + '% complete')
$('#back span').text($('#front').text())
bb_width = (percent_complete * $('#back').width())/100
$('#boundbox').css('width', bb_width.toString())

And here's a fiddle: Progress bar.

enter image description here

I tested this in Chrome, Firefox, Microsoft Edge, and IE version 11.