Change Text Color If Background Image Is Not White

Change text color if background image is not white?

An idea is to color the text with an inverted background.

Here is an idea considering radial-gradient:

.box {  padding: 50px;  background: radial-gradient(circle at 70% 0px, #fff 45%, purple 45.5%) fixed;}
p { font-size: 25px; font-weight: bold; /*Should be the same background but inverted color*/ background: radial-gradient(circle at 70% 0px, purple 45%, #fff 45.5%) fixed; background-clip: text; color: transparent; -webkit-background-clip: text; -webkit-text-fill-color: transparent;}
<div class="box">  <p>Some text here Some text here Some text here Some text here </p></div>

Change text color to white on any non-white background

Here is an idea that rely on background coloration and not mix-blend-mode. The trick is to have a gradient with the same dimension as the image that you move the same way to simulate the blend mode:

const box = document.querySelector(".box");const h1 = document.querySelector("h1");window.addEventListener('mousemove', function(event) {  box.style.left = `${event.pageX - 50}px`;  box.style.top = `${event.pageY - 50}px`;    h1.style.backgroundPosition = `${event.pageX - 50}px ${event.pageY - 50}px`;});
.wrapper {  background-color: white;}h1 {  position: relative;  z-index: 2;  color: white;  background:     /*gradient                   position   /    size  */    linear-gradient(#fff,#fff) -100px -100px/100px 100px fixed no-repeat,    #000;  -webkit-background-clip: text;  background-clip: text;  -webkit-text-fill-color: transparent;  color: transparent;}
.box { width: 100px; height: 100px; position: absolute; z-index: 1; background-image: url("https://placekitten.com/100/100")}
<div class="wrapper">  <h1>Lorem Ipsum</h1></div><div class="box"></div>

How to change font color based on background image with javascript?

Explanation


Here is an example showing how to get the average using a canvas rendered to a 1x1-px scale. From there we set the header background and then apply a light or dark class based on the luminance of the aforementioned average.

Notes


Note 1:
There is some extra code to allow for easier visualization, this is commented and can be removed.

Note 2: The below code is not guaranteed to run on all browsers. Please see this thread for more specifics.

Note 3: This code only works with local images and CORS-enabled image URLs due to it's reliance on canvas.drawImage. Please see this for more information.

Example 1:

this example shows the functionality. It uses two image URLs in the JS to toggle between.

/* 

THE TOGGLE ACTION

*/

/* The urls for toggling between */
const urlLight = 'https://images.unsplash.com/photo-1484503793037-5c9644d6a80a?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=930&q=80';
const urlDark = 'https://images.unsplash.com/photo-1517999144091-3d9dca6d1e43?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=627&q=80';
let currentUrl = urlLight;

const toggle = document.getElementById('toggle');

toggle.addEventListener("click", function() {
if (currentUrl === urlLight) {
currentUrl = urlDark;
} else {
currentUrl = urlLight;
}

getImageBrightness(currentUrl, function(brightness) {

const header = document.getElementById("header");
header.style.backgroundImage = `url(${currentUrl}`;

header.classList.remove("dark");
header.classList.remove("light");

console.log(brightness);

if (brightness > 225 / 2) {
header.classList.toggle("dark");

} else {
header.classList.toggle("light");
}
});

});

/*

Important get brightness code

*/

function getImageBrightness(imageSrc, callback) {
var img = document.createElement("img");
img.src = imageSrc;
img.style.display = "none";
img.crossOrigin = "anonymous";
document.body.appendChild(img);

var colorSum = 0;

img.onload = function() {
// create canvas
var canvas = document.createElement("canvas");
canvas.width = this.width;
canvas.height = this.height;

var ctx = canvas.getContext("2d");
ctx.drawImage(this, 0, 0);

var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
var data = imageData.data;
var r, g, b, avg;

for (var x = 0, len = data.length; x < len; x += 4) {
r = data[x];
g = data[x + 1];
b = data[x + 2];

avg = Math.floor((r + g + b) / 3);
colorSum += avg;
}

var brightness = Math.floor(colorSum / (this.width * this.height));
callback(brightness);
}
}

getImageBrightness(currentUrl, function(brightness) {

const header = document.getElementById("header");
header.style.backgroundImage = `url(${currentUrl}`;

header.classList.remove("dark");
header.classList.remove("light");

if (brightness > 225 / 2) {
header.classList.toggle("dark");

} else {
header.classList.toggle("light");
}
});
.dark {
color: black;
}

.light {
color: white;
}

* {
text-align: center;
}

#header {
padding: 2rem 0;
font-size: 4rem;
background-size: cover;
margin-bottom: 1rem;
background-position: center center;
}
<div id="header">
Header
</div>

<button id='toggle'>
Toggle Background
</button>

Change font color based on background image

I felt I should post an answer to explain what is going on with OPs example.

Simply settings a fill: white on an SVG does not fully reproduce the desired result. OP's example also requires a parent div with mix-blend-mode: difference set as well.

You can actually reproduce this without any SVGs at all. You simply need an element with a color/fill of white, and a parent element with mix-blend-mode: difference. This has to do with how the blending mode of difference works with the color white over a background.

function _Swap() {
document.querySelector(".backgroundDiv").style.background = (document.querySelector(".backgroundDiv").style.background == "rgb(0, 0, 0)") ? "rgb(255, 255, 255)" : "rgb(0, 0, 0)";
}
.backgroundDiv {
background: #FFF;
padding: 4em;
}

.test {
mix-blend-mode: difference;
}

p {
color: #FFF;
}
<div class="backgroundDiv">
<div class="test">
<p>This is a test</p>
</div>
</div>
<input type="button" value="Swap Background Color" onclick="_Swap()">

How do I set a background-color for the width of text, not the width of the entire element, using CSS?

Put the text in an inline element, such as a <span>.

<h1><span>The Last Will and Testament of Eric Jones</span></h1>

And then apply the background color on the inline element.

h1 {
text-align: center;
}
h1 span {
background-color: green;
}

An inline element is as big as its contents is, so that should do it for you.

Setting text color to inverted background color

div {
background: linear-gradient(to right, #fff, #000);
width: 100vh;
height: 50vh;
}

span {
font-size: 30vh;
mix-blend-mode: difference;
filter: invert(1);
}
<div>
<span>Test</span>
</div>


Related Topics



Leave a reply



Submit