What is the easiest way to modify the color of a basic PNG image in a web browser?

While working on a website project, I encountered instructions for mouseover styles in the design that got me thinking:

It's straightforward to achieve with javascript or css image swapping... but here's the catch. There will be multiple icon links throughout the site - each paired with text, and some may require different colors or adjustments to the blue shade. It would be a hassle to create new versions of each image for every color variation, and it would be a nightmare if any color changes were needed. Wouldn't it be great if you could manage text and image colors in one place with css?

I did some research, and opinions on changing the color in an image seem divided between using CSS3 masks or utilizing SVG. CSS Masks are tempting due to their simplicity, but they have limited browser support - while SVG is recommended by W3C but requires images to be in .svg format (using .png options can get complicated and have spotty support).

So, does anyone know of a solution that allows me to effectively change the color of a flat .png image with good browser support? Extra points for simplicity/elegance, but I'm open to anything as long as it only needs a path to a .png image and a hex color. Thank you!


Edit 1: Just to clarify, this project excludes IE9-10 - we're focusing on compatibility with IE8 and 11. Thanks!


Edit 2: Other unsuccessful considerations

I thought about creating an inverted "stencil" version of each icon and overlaying it on a background color. However, this presents an issue for users and content editors since these icons will be used elsewhere, and a white stencil on a white background serves no purpose.

I also looked into the answers on this related question, but filters don't seem to accept hex values nor are they fully supported. Using an icon font might be an option, but it wouldn't be easily customizable for non-tech-savvy users - and having an easy "upload-to-cms" feature is crucial here.

Answer №1

Resolution & Example

The issue has been resolved, and here is a JSFiddle demo for reference.

###Advantages

  • User-friendly interface.
  • Available color selection in all JavaScript recognized formats.
  • Customizable icon colors excluding white.

###Drawbacks

  • Dependent on the tinycolor.js library to support various color formats. (Yet, it can be eliminated with self-created conversion functions)

  • Operates solely on IE9+ due to utilization of HTML5 canvas. (However, programming for IE always poses challenges).

  • Requires source images to reside on the same server as canvas cannot fetch from cross-origin sources, using Data URI for demonstration purposes. (There is a workaround available if desired).

##HTML Markup

<input type="text" value="#669dbb">
<button>Alter color</button>
<img src="data:image/png;base64,(..)">

Straightforward structure - an <input> field for selecting the target color, and a <button> for executing the changes. (Initial value mimics the light blue shade present in your default icon).

##JavaScript Logic

var img = document.querySelector("img");
var button = document.querySelector("button");
var text = document.querySelector("input");
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");

button.onclick = function () {
    updateColor(text.value);
};

updateColor = function (inputColor) {
    canvas.setAttribute("width", img.width);
    canvas.setAttribute("height", img.height);
    context.drawImage(img, 0, 0);
    var dataObject = context.getImageData(0, 0, canvas.width, canvas.height);
    var data = dataObject.data;
    for (var i = 0; i < data.length; i += 4) {
        var r = data[i],
            g = data[i + 1];
            b = data[i + 2];
            a = data[i + 3];
        var notTranslucent = a != 0;
        var nonBackground = ( notTransparent && r != 255 && g != 255 && b != 255 );
        if (nonBackground) {
            var input = tinycolor(inputColor);
            var rgb = input.toRgb();
            data[i] = rgb.r;
            data[i + 1] = rgb.g;
            data[i + 2] = rgb.b;
            data[i + 3] = a;
        }
    }
    context.putImageData(dataObject, 0, 0);
    img.src = canvas.toDataURL();
}

##Elucidation

Focusing primarily on the modifyColor() function, while other code segments handle preparatory tasks.

  • Aligning width & height of <img> and <canvas>.
  • Drawing image onto the canvas.
  • Extracting pixel array data from entire canvas.
  • Examining data elements individually to retrieve pixel values.
  • Array[0] = Red
  • Array[1] = Green
  • Array[2] = Blue
  • Array[3] = Alpha.
  • Determining if the pixel is part of the background by checking opacity and presence of white.
  • Applying selected color transformation to pixels.
  • Updating canvas with modified data for rendering.
  • Converting canvas to Data URI, connecting it back to <img>.

#Additional Information

To avoid intensive setup processes, a library named AmazingIcon.js (Github) is provided for achieving similar outcomes:

##Head Section

<script src=tinycolor.js></script>
<script src=amazingicon.js></script>

##Body Section

<a class="amazingIcon" href="some-url" data-src="icon-image-url">icon-label</a>

Incorporating the data-src attribute allows creation of pseudo-custom attributes.

##Javascript Operations

AmazingIcon.parseDocument();

AmazingIcon.hover(function(icon,ev){
    icon.setColor("lightblue");
});

Running AmazingIcon.parseDocument() transforms designated anchors with amazingIcon class into Amazing Icons.

The AmazingIcon.hover(callback) feature enables hover events for all amazing icons, providing both (icon,event) parameters for customized actions. (Further information in documentation).

##Style Sheet Specifications

.AmazingIconObject{
      display: inline-block;
      vertical-align: top;
      text-align: center;
      margin-right: 5px;
      word-wrap: break-word;
      width: 100px;
      font-family: Verdana;
      font-weight: bold;
      color: lightcoral;
      margin-right: 5px;
      text-decoration: none;
}

For detailed insights regarding functionality, modifications or reproduction, refer to the Github repository for complete freedom in adjustments.

##Demonstration Preview

Due to limitations on showcasing with non-crossorigin content, visual depiction is presented for illustrative purpose.

Trusting this elucidates matters effectively. Until next time!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to make an HTML form show fields depending on certain conditions?

Initially, I created an index page containing a form with various fields. The utility was built to handle all the fields, but now there's been a change in requirements. What I need is for only the Controller Type and Test Type fields to be displayed f ...

Another choice for object-fit:contain workaround for IE

Is there an alternative option to object-fit: contain that is compatible with Internet Explorer? Below is a snippet of my code: .cbs-Item img { height: 132px ! important; width: 132px ! important; object-fit: contain; <div class="cbs-Ite ...

Ways to move the scroll to the bottom of the div by clicking

Can anyone help with why my scroll code isn't working? I'm trying to make the scroll go to the bottom when I click on $('#openDiv'). For example, when you enter a chat room on stackoverflow, the scroll is automatically at the bottom, a ...

What is the best approach to transfer information from the client side to a node

I have an ejs page that looks like this: <%- include('../blocks/header', {bot, user, path}) %> <div class="row" style="min-width: 400px;"> <div class="col" style="min-width: 400px;"> <div class="card text-white mb-3" & ...

I'm looking to center my btn button vertically and horizontally over two images using Bootstrap 5 in a responsive manner. How can I achieve this?

Any tips on how to position my btn button both vertically and horizontally in the center on top of two images? I want it to look like this: https://i.sstatic.net/Rezrd.png This is the code for my button: <a class="btn btn-primary" href=" ...

Is there a way to modify the FixedTableHeader jQuery plugin to include a fixed first column in addition to the fixed header?

I've been experimenting with a jQuery plugin I found at to create a stylish table with fixed headers, sorting options, and other interesting features. While the plugin is great, I also considered using jqGrid for its impressive capabilities. However, ...

place an image next to a div element

Currently, I have a table-like structure with two columns that I am struggling to make mobile responsive. Take a look at the code snippet below: setTimeout(function() { odometer.innerHTML = '1925' }) .fiftyFiftySection { back ...

Is there a way to use the <form> element with the specified action attribute and a <button> element of type submit to create a button that functions as a hyperlink?

Here is my approach to creating stylish buttons. <span class='button button-orange' id='sign-up'><input type='button' value='Sign up here' /></span> When adding an anchor tag (with href) around th ...

Retrieve the initial entry from a Container for every row in the Table

I'm facing an issue with a table I have on my website. Here is the structure: <table id="fieldContainer"> <tr><td><input id="input1"></td><td><input id="input2"></td></tr> <tr><td>< ...

Resize images smoothly without disrupting the anchor scrolling

I have created a website with the following design: (Caution: The site is built using AngularJS on a server that may not serve it correctly - please visit directly instead of using browser reload.) However, I am facing two conflicting requirements... ...

Change the text in a CSS checkbox label when it is selected

There is an innovative Pure-CSS accordion that caught my eye, but I have a unique feature in mind that I would like to incorporate. What I am looking for is the ability for the labels to dynamically change based on the state of the checkboxes without relyi ...

What is the method for defining the href attribute using the parameter passed through ejs?

For my node.js express application, I am utilizing ejs as the view engine. One of the pages in this application is a profile page that displays a user's information. Within this page, there is an anchor tag with the user's email address as the va ...

Displaying or concealing list elements in Angular 6

I am working on a simple Angular app that displays a list of items. I want the behavior to be such that when the first item in the list is clicked, its description (card) should be displayed. And, if the second item is clicked and its description is displa ...

How can I design a custom status update box inspired by the look and feel of Facebook

I have searched extensively online for a guide on creating a CSS box similar to Facebook's status update callout box. This box features a square shape with a small notch at the top. Could someone assist me in crafting a CSS design for this type of bo ...

The "if" statement carries out the identical action each time it is executed

Despite my efforts to toggle the value of the turn variable every time the if statement runs, I keep encountering the same outcome. It appears that turn consistently evaluates as 2. Below is the code snippet in question: $(function() { var turn = 2; ...

Arrangement of Columns in a Vertical Bootstrap Layout

When the xs layout displays as expected, how can I move the sidebar up to the navigation in order to eliminate the gap between them in the lg layout? <div class="row"> <div class="col-xs-12 col-lg-3 col-lg-push-9"> navigation & ...

Designing Interactive Interfaces using React Components for Dynamic Forms

Is there a way to implement dynamic forms using React Components? For instance, I have a form displayed in the image below: How do I structure this as a React component? How can I incorporate interactivity into this component? For example, when the "+ A ...

In AngularJS, the process of replacing text using a filter can be achieved by following

Currently in the process of learning Angular, but I've hit a roadblock and can't seem to find a solution. I have a website that provides USPS shipping options, and I need to replace the default text with my own. The vendor's option shows &ap ...

What are some ways I can safeguard my CSS from injected elements?

I have created an HTML widget that is inserted into various websites without the use of iframes. However, I am encountering issues where the CSS of some sites is affecting the appearance of my elements, such as text alignment, underlining, and spacing. Is ...

Combining days and months in a date time using PHP

I am looking to create a textBox where users can input a date and time, followed by selecting an option from a dropdown menu that triggers a calculation. For instance: if ($exampleMonth === 11 && $exampleDay > 30) { $exampleMonth = 12; ...