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
How to Make a Cell of Table Hyperlink
How to Use Z-Index with Relative Positioning
The Right Way of Setting <A Href=""> When It's a Local File
Question Mark in The Middle of a Url Variable
How to Put Img Inline with Text
The Best Way to Parse a JSON in Dart
How to Create a Heart Shape Using CSS
How to Create Chat Bubbles Like Facebook Messenger
How to Put a Space Character Before Option Text in a HTML Select Element
Can You Do This HTML Layout Without Using Tables
Two Input Fields Inside One Label
Ipad Layout Scales Up When Rotating from Portrait to Landscape
How to Stop <Div> Tags Interfering with Counters
Difference Between Applying CSS Rules to HTML Compared to Body
Dashed Border Not Showing in Firefox