I have a few logos in my image assets. These logos will be imported into this website. Each logo has a random color (can be white, black, gray, red, blue, green, etc.) and has a transparent background. For example:
The code below will be applied to display the logo on the website page:
.magic-box {
width: 200px;
height: 100px;
border: 1px solid black;
position: relative;
border-radius: 20px;
background-color: white; /* can be changed */
}
.magic-image {
max-height: 100%;
max-width: 100%;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
.images {
display: flex;
}
<div class="images">
<div class="magic-box">
<img src="https://i.sstatic.net/b7yHv.png" class="magic-image" />
</div>
<div class="magic-box">
<img src="https://i.sstatic.net/IhCH1.png" class="magic-image" />
</div>
<div class="magic-box">
<img src="https://i.sstatic.net/tYjdM.png" class="magic-image" />
</div>
</div>
The problem is when I make the background color of .magic-box
white, then the white logo doesn't show up. When the background color is set to black, the black logo is not visible, and so on.
.magic-box {
width: 200px;
height: 100px;
border: 1px solid black;
position: relative;
border-radius: 20px;
background-color: black; /* can be changed */
}
.magic-image {
max-height: 100%;
max-width: 100%;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
.images {
display: flex;
}
<div class="images">
<div class="magic-box">
<img src="https://i.sstatic.net/b7yHv.png" class="magic-image" />
</div>
<div class="magic-box">
<img src="https://i.sstatic.net/IhCH1.png" class="magic-image" />
</div>
<div class="magic-box">
<img src="https://i.sstatic.net/tYjdM.png" class="magic-image" />
</div>
</div>
How to determine the most appropriate background-color
to be applied to every .magic-box
element programmatically?
Note: Background color can be different for each image
This approach renders the image to a 1x1 px <canvas>
to retrieve the average luminance/brightness to find an appropriate background color.
function adjustBG(image, grayscale = true) {
// try to fix CORS issues
image.crossOrigin = "anonymous";
// draw image on canvas
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
let img = new Image();
img.src = image.src;
img.crossOrigin = "anonymous"; // ADDED
img.onload = function () {
canvas.width = 1;
canvas.height = 1;
ctx.imageSmoothingEnabled = true;
ctx.drawImage(img, 0, 0, 1, 1);
// calculate average color form 1x1 px canvas
let color = ctx.getImageData(0, 0, 1, 1).data;
let [r, g, b, a] = [color[0], color[1], color[2], color[3]];
// calculate relative luminance
let luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
let contrast = +((255 - luminance) / 255).toFixed(2);
let bg = [255 - luminance, 255 - luminance, 255 - luminance].map(
(val) => {
return +val.toFixed(0);
}
);
let filters = [];
// optional convert all to grayscale
if (grayscale) {
filters.push(`grayscale(1)`);
}
// add background color if image is very bright
if (luminance > 160 && contrast < 0.5) {
//console.log(bg, luminance)
image.style.backgroundColor = `rgb(${bg.join(",")})`;
} else {
image.style.backgroundColor = `rgb(255,255,255)`;
}
// enhance contrast
if (contrast < 0.5) {
let newContrast = contrast ? 1/contrast : 1;
filters.push(`contrast(${newContrast })`);
}
image.style.filter = filters.join(" ");
};
let images = document.querySelectorAll("img");
addBGColor(true);
function revert() {
images.forEach((img) => {
img.style.removeProperty("background-color");
img.style.removeProperty("filter");
});
}
function addBGColor(grayscale = true) {
images.forEach((img) => {
adjustBG(img, grayscale);
});
}
function adjustBG(image, grayscale = true) {
// try to fix CORS issues
image.crossOrigin = "anonymous";
// draw image on canvas
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
let img = new Image();
img.src = image.src;
img.crossOrigin = "anonymous"; // ADDED
img.onload = function() {
canvas.width = 1;
canvas.height = 1;
ctx.imageSmoothingEnabled = true;
ctx.drawImage(img, 0, 0, 1, 1);
// calculate average color form 1x1 px canvas
let color = ctx.getImageData(0, 0, 1, 1).data;
let [r, g, b, a] = [color[0], color[1], color[2], color[3]];
// calculate relative luminance
let luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
let contrast = +((255 - luminance) / 255).toFixed(2);
let bg = [255 - luminance, 255 - luminance, 255 - luminance].map(
(val) => {
return +val.toFixed(0);
}
);
let filters = [];
// optional convert all to grayscale
if (grayscale) {
filters.push(`grayscale(1)`);
}
// add background color if image is very bright
if (luminance > 160 && contrast < 0.5) {
//console.log(bg, luminance)
image.style.backgroundColor = `rgb(${bg.join(",")})`;
} else {
image.style.backgroundColor = `rgb(255,255,255)`;
}
// enhance contrast
if (contrast < 0.5) {
let newContrast = contrast ? 1 / contrast : 1;
filters.push(`contrast(${newContrast })`);
}
image.style.filter = filters.join(" ");
};
}
body {
background: #eee;
}
img {
width: 10em;
margin: 1em;
}
<p><button onclick="revert()">revert</button> <button onclick="addBGColor(true)">Add BG color (grayscale)</button> <button onclick="addBGColor(false)">Add BG color (no change)</button></p>
<div class="logos">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='20' text-anchor='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 0, 0)'>LO<tspan fill='rgb(128, 128, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.4)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(255, 0, 0)'>LO<tspan fill='rgb(255, 0, 0)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.4)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 255, 0)'>LO<tspan fill='rgb(255, 128, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.5)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 0, 255)'>LO<tspan fill='rgb(128, 128, 128)'>GO</tspan><tspan fill='rgba(0, 255, 255, 0.4)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(255, 255, 0)'>LO<tspan fill='rgb(255, 255, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 1)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(255, 255, 255)'>LO<tspan fill='rgb(128, 128, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.5)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 255, 255)'>LO<tspan fill='rgb(255, 200, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.75)'>*</tspan></text></svg>">
<img src="https://i.imgur.com/qO6ZdET.png" crossorigin="anonymous" data-contrast="0.69" data-bg="175,175,175" style="background-color: rgb(175, 175, 175);">
</div>
image.crossOrigin = 'anonymous'
Based on Rene van der Lende's comment I've modified the averagecolor.js script and added some features.
The following snippet will also check for transparency in an image as well as grayscale-only color range.
However, this script is significantly slower to to the more detailed color detection.
let images = document.querySelectorAll("img");
function revert() {
images.forEach((img) => {
img.style.removeProperty('background-color');
img.style.removeProperty('filter');
});
}
function addBGColor(options = { grayscale: true, complementraryColor: false, enhanceContrast: true }) {
images.forEach((img) => {
adjustBG(img, options);
});
}
function adjustBG(image, options = { grayscale: true, complementraryColor: false, enhanceContrast: true }) {
let grayscale = options.grayscale;
let complementraryColor = options.complementraryColor;
let enhanceContrast = options.enhanceContrast;
// try to fix CORS issues
image.crossOrigin = 'anonymous';
image.addEventListener('load', e=>{
// check transparency
let hasTransparency = checkImgTransparency(image);
let isGray = checkImgGrayScale(image);
// skip opaque images
if (!hasTransparency) {
console.log('nothing to do', image.src);
return false
}
// get average color based on flattened transparency
let { r, g, b, a, colors } = getAverageColor(image, 24, 24, false);
// calculate relative luminance
let luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
let contrast = +((255 - luminance) / 255).toFixed(2);
let bg = [255 - luminance, 255 - luminance, 255 - luminance];
// calculate complementary color
let colComplemantary = [255 - r, 255 - g, 255 - b];
let filters = [];
// optional convert all to grayscale
if (grayscale && !isGray) {
filters.push(`grayscale(1)`)
}
// add background color if image is very bright
let contrastAdjust = 1 + (luminance / 255);
let colorBG = !complementraryColor ? 'rgb(255,255,255)' : `rgb(${colComplemantary.join(',')})`;
image.setAttribute('data-contrast', contrast);
image.setAttribute('data-bg', bg.join(','));
// almost white
if (luminance > 170 && contrast < 0.5) {
colorBG = `rgb(${bg.join(',')})`;
}
// enhance contrast
if (enhanceContrast && contrast < 0.5) {
let newContrast = contrast ? 1/contrast : 1;
filters.push(`contrast(${newContrast })`);
}
// apply styles
image.style.backgroundColor = colorBG;
image.style.filter = filters.join(' ');
})
// if image is ready loaded
let isloaded = image.complete;
if (isloaded) {
image.dispatchEvent(new Event('load'));
}
}
/**
* based on
* https://matkl.github.io/average-color/average-color.js
*/
function getAverageColor(img, width=24, height=24, flattenTransparency = false) {
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = true;
canvas.width = width;
canvas.height = height;
//document.body.appendChild(canvas)
// flatten transparency
if (flattenTransparency) {
//add rect
ctx.fillStyle = "rgb(255,255, 255)";
ctx.fillRect(0, 0, width, height);
}
ctx.drawImage(img, 0, 0, width, height);
let imageData = ctx.getImageData(0, 0, width, height);
let data = imageData.data;
let [rT, gT, bT, aT] = [0, 0, 0, 0];
let colLength = data.length/4;
// get colors
let colors = [];
for (let i = 0; i < data.length; i += 4) {
r = data[i];
g = data[i + 1];
b = data[i + 2];
a = data[i + 3];
// exclude transparent colors
if(a>128){
rT += r;
gT += g;
bT += b;
aT += a;
} else{
colLength--;
}
// count colors
let colStr = [r, g, b].join('_');
colors.push(colStr)
}
// calculate average color
rT = Math.floor(rT / colLength);
gT = Math.floor(gT / colLength);
bT = Math.floor(bT / colLength);
aT = Math.floor(aT / colLength);
// remove duplicates
colors = [...new Set(colors)];
return { r: rT, g: gT, b: bT, a: aT , colors: colors.length};
}
function colorIsgrayscale(r, g, b, tolerance = 0.25) {
let isGray = false;
let rT = +(r * tolerance).toFixed(0);
let gT = +(g * tolerance).toFixed(0);
let bT = +(b * tolerance).toFixed(0);
let colorAverage = (rT + gT + bT) / 3;
if (colorAverage == rT && colorAverage == gT && colorAverage == bT) {
isGray = true;
}
return isGray;
}
function checkImgGrayScale(img, tolerance = 0.9) {
let isGrayscale = false;
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = true;
let [w, h] = [8, 8];
ctx.drawImage(img, 0, 0, w, h);
let imageData = ctx.getImageData(0, 0, w, h);
let data = imageData.data;
let gray = 0;
for (let i = 0; i < data.length; i += 4) {
let r = data[i];
let g = data[i + 1];
let b = data[i + 2];
let isGray = colorIsgrayscale(r, g, b);
if(isGray){
gray++;
}
}
if(gray===data.length/4){
isGrayscale = true;
}
return isGrayscale;
}
function checkImgTransparency(img) {
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = true;
ctx.drawImage(img, 0, 0, 3, 3);
let imageData = ctx.getImageData(0, 0, 2, 2);
let data = imageData.data;
let hasAlpha = data[3] < 255 ? true : false;
return hasAlpha;
}
body {
background: #eee;
}
img {
width: 10em;
margin: 1em;
}
<p><button onclick="revert()">revert</button>
<button onclick="addBGColor({grayscale: true, complementraryColor: false, enhanceContrast: false})">Add BG color (grayscale)</button> <button onclick="addBGColor({grayscale: false, complementraryColor: true, enhanceContrast: false})">Add BG color (complementary color)</button></p>
<div class="logos">
<img alt="logo white" src="https://i.postimg.cc/FzFQ3n3D/b7yHv.png" class="magic-image" />
<img alt="logo black" src="https://i.postimg.cc/J0TCqcQm/IhCH1.png" class="magic-image" />
<img src="https://i.imgur.com/qO6ZdET.png" >
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='20' text-anchor='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 0, 0)'>LO<tspan fill='rgb(128, 128, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.4)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(255, 0, 0)'>LO<tspan fill='rgb(255, 0, 0)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.4)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 255, 0)'>LO<tspan fill='rgb(255, 128, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.5)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 0, 255)'>LO<tspan fill='rgb(128, 128, 128)'>GO</tspan><tspan fill='rgba(0, 255, 255, 0.4)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(255, 255, 0)'>LO<tspan fill='rgb(255, 255, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 1)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(255, 255, 255)'>LO<tspan fill='rgb(128, 128, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.5)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 255, 255)'>LO<tspan fill='rgb(255, 200, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.75)'>*</tspan></text></svg>">
</div>
Similar to the first approach, we're analyzing the contrast and brightness of the image by rendering a <canvas>
element to calculate appropriate filter property values to enhance contrast(2)
, or inverted very bright colors colors via invert(1)
let images = document.querySelectorAll("img");
function fixImgColors() {
images.forEach((img) => {
adjustLightColors(img);
});
}
function revert() {
images.forEach((img) => {
img.style.removeProperty('background-color');
img.style.removeProperty('filter');
});
}
function adjustLightColors(image) {
// draw image on canvas
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
let img = new Image();
img.src = image.src;
img.onload = function() {
canvas.width = 1;
canvas.height = 1;
ctx.imageSmoothingEnabled = true;
ctx.drawImage(img, 0, 0, 1, 1);
// calculate average color form 1x1 px canvas
let color = ctx.getImageData(0, 0, 1, 1).data;
let [r, g, b] = [color[0], color[1], color[2]];
// calculate relative luminance
let luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
// invert if image is very bright
let filterInvert = luminance > 128 ? 1 : 0;
let contrast = Math.ceil(1 + (luminance / 255));
image.style.filter = `invert(${filterInvert}) grayscale(1) contrast(${contrast}`;
};
}
body {
background: #eee;
}
img {
width: 10em;
margin: 1em;
}
<p><button onclick="revert()">revert</button> <button onclick="fixImgColors()">Adjust colors</button></p>
<div class="logos">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='20' text-anchor='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 0, 0)'>LO<tspan fill='rgb(128, 128, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.4)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(255, 0, 0)'>LO<tspan fill='rgb(255, 0, 0)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.4)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 255, 0)'>LO<tspan fill='rgb(255, 128, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.5)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 0, 255)'>LO<tspan fill='rgb(128, 128, 128)'>GO</tspan><tspan fill='rgba(0, 255, 255, 0.4)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(255, 255, 0)'>LO<tspan fill='rgb(255, 255, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 1)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(255, 255, 255)'>LO<tspan fill='rgb(128, 128, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.5)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 255, 255)'>LO<tspan fill='rgb(255, 200, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.75)'>*</tspan></text></svg>">
</div>
<svg xmlns='http://www.w3.org/2000/svg' width='0' height='0' style="position:absolute">
<defs>
<filter id='fillBlack' filterUnits='userSpaceOnUse'>
<feFlood flood-color='#000' result='flood' />
<feComposite in='flood' in2='SourceAlpha' operator='in' />
</filter>
</defs>
</svg>
This approach is based on a SVG flood filter
Inline a hidden svg to your HTML body:
<svg xmlns='http://www.w3.org/2000/svg' width='0' height='0' style="position:absolute">
<defs>
<filter id='fillBlack' filterUnits='userSpaceOnUse'>
<feFlood flood-color='#000' result='flood' />
<feComposite in='flood' in2='SourceAlpha' operator='in' />
</filter>
</defs>
</svg>
and reference this filter by defining a CSS class.
.fillBlack {
filter: url('#fillBlack');
}
Unfortunately chromium currently struggles with some filters, when embedded as dataURLs.
In Firefox you could also use this:
.fillBlack {
filter: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><filter id='fillBlack' filterUnits='userSpaceOnUse'><feFlood flood-color='black' result='flood'/><feComposite in='flood' in2='SourceAlpha' operator='in'/></filter></svg>#fillBlack");
}
let images = document.querySelectorAll("img");
function applySvgFilter() {
images.forEach((img) => {
img.classList.add('fillBlack');
});
}
function revert() {
images.forEach((img) => {
img.classList.remove('fillBlack');
});
}
body {
background: #eee;
}
img {
width: 10em;
margin: 1em;
}
.fillBlack {
filter: url('#fillBlack');
}
<p><button onclick="revert()">revert</button> <button onclick="applySvgFilter()">Apply svg filter</button></p>
<div class="logos">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='20' text-anchor='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 0, 0)'>LO<tspan fill='rgb(128, 128, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.4)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(255, 0, 0)'>LO<tspan fill='rgb(255, 0, 0)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.4)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 255, 0)'>LO<tspan fill='rgb(255, 128, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.5)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 0, 255)'>LO<tspan fill='rgb(128, 128, 128)'>GO</tspan><tspan fill='rgba(0, 255, 255, 0.4)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(255, 255, 0)'>LO<tspan fill='rgb(255, 255, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 1)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(255, 255, 255)'>LO<tspan fill='rgb(128, 128, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.5)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 255, 255)'>LO<tspan fill='rgb(255, 200, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.75)'>*</tspan></text></svg>">
</div>
<!-- hidden svg filter definition -->
<svg xmlns='http://www.w3.org/2000/svg' width='0' height='0' style="position:absolute">
<defs>
<filter id='fillBlack' filterUnits='userSpaceOnUse'>
<feFlood flood-color='#000' result='flood' />
<feComposite in='flood' in2='SourceAlpha' operator='in' />
</filter>
</defs>
</svg>
(The javaScript in the example above just helps to illustrate the "before/after" effect).