Modify text by adjusting text color based on the contrast with the background color using knockout databinding

I am working with a table that contains data from my database:

Here is the ViewModel structure:

function alertViewModel(i) {
    var self = this;
    self.Id = ko.observable(i.Id);

self.AlertType = ko.observable(i.AlertType);
self.Category = ko.observable(i.Category);
self.Color = ko.observable(i.Color);
self.AlertText = ko.observable(i.AlertText);
self.update = function (data) {
    if (typeof (data.AlertType) != 'undefined') self.AlertType(data.AlertType);
    if (typeof (data.Category) != 'undefined') self.Category(data.Category);
    if (typeof (data.Color) != 'undefined') self.Color(data.Color);
}
};

In the cshtml file, I present the data in this way:

<table class="table" id="alertstable">
                                <tbody data-bind="foreach: alerts">
                                    <tr data-bind="style: { backgroundColor: Color }">
                                        <td>
                                            <b data-bind="text: AlertText">Message</b>
                                        </td>

                                    </tr>
                                </tbody>
                            </table>

Each row of the table can have a different background color, and depending on that color, the text color should change to black or white. Here is a code snippet demonstrating the contrast calculation:

function getContrastYIQ(hexcolor){
    var r = parseInt(hexcolor.substr(0,2),16);
    var g = parseInt(hexcolor.substr(2,2),16);
    var b = parseInt(hexcolor.substr(4,2),16);
    var yiq = ((r*299)+(g*587)+(b*114))/1000;
    return (yiq >= 128) ? 'black' : 'white';
}

I am looking for a way to dynamically change the text color based on the background color. Any help with implementing this functionality would be greatly appreciated. Thank you!

Answer №1

To enhance the viewmodel, consider implementing a Knockout Computed Observable for controlling text color, such as "TextColor". This computed property would rely on the existing Color observable and utilize a specific function like the following example:

self.TextColor = ko.computed(function() {
    return getContrastYIQ(self.Color());
});

Lastly, include a color binding within the current style binding on tr element:

databind="style: { backgroundColor: Color, color: TextColor }"

Answer №2

After conducting some thorough research, I managed to uncover the solution:

  1. To begin with, I included this line in the viewmodel:

    self.TextColor = ko.observable(i.TextColor);

  2. When loading the viewmodel with data from the database, I added:

    element['TextColor'] = getContrastYIQ(element.Color);

  3. Further modifications were made in the cshtml file by adding:

    databind="style: { backgroundColor: Color, color: TextColor }"

  4. The getContrastYIQ() function underwent the following changes:

    function cutHex(h) { return (h.charAt(0) == "#") ? h.substring(1, 7) : h }

    function HexToR(h) { return parseInt((cutHex(h)).substring(0,2),16) }

    function HexToG(h) { return parseInt((cutHex(h)).substring(2, 4), 16) }

    function HexToB(h) { return parseInt((cutHex(h)).substring(4, 6), 16) }

    function getContrastYIQ(hexcolor) { var r = HexToR(hexcolor); var g = HexToG(hexcolor); var b = HexToB(hexcolor); var yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000; return (yiq >= 128) ? 'black' : 'white'; }

This implementation worked flawlessly for me. Hopefully, it can be of assistance to others as well!

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

The scroll bar of the Bootstrap modal keeps playing peekaboo every time a new modal is triggered

After trying numerous solutions without success, I am posting this question regarding an issue with the scrolling behavior of Bootstrap modals. Here is the scenario: I have 2 Modals: Modal-1 and Modal-2. When a user is inputting information in Modal-1 ...

DIV with Scrollbar

Is there a method to ensure that both scrollbars are displayed, regardless of whether vertical or horizontal scrolling is required? Currently, I am only seeing one scrollbar when needed. I want to achieve this without restricting the use of the Height or ...

Image tinting color picker tool (using HTML, CSS, and web technologies)

I'm currently exploring ways to apply a filter or tint on top of an image using CSS/HTML or some lightweight solution. For example, Ideally, my goal is to only have one image displayed on the page and overlay it with a transparent filter based on a ...

Creating a hover effect for displaying image masks

My website features a profile page displaying the user's photo. I am attempting to create a functionality where when the user hovers over their photo, a transparent mask with text appears allowing them to update their profile picture via a modal. How ...

CSS - Layering <divs> on top of clear <div>'s

Is there a method to eliminate the transparency of content/images within a <div> that is transparent? Below is the provided HTML: <div id="main-button-wrapper" class="left"> <div id="button-bg-layer" class="box-bg-layer corner ...

CSS Issue with Background Image not Fully Covering Viewport Width

Why isn't the CSS background covering the entire viewport width when using media query @media (max-width: 62.5em)? I've attempted to use background-size: cover, background-position: top left, and background-repeat: no-repeat, but nothing seems t ...

Reduce the height of the navigation bar

I used the header example from Bootstrap's documents here: https://getbootstrap.com/docs/5.3/examples/headers/# The code I have is: <div class="container fixed-top bg-white"> <header class="d-flex flex-wrap justify-conte ...

What is the reason behind my phone burger not working and how can I resolve the problem?

I am facing an issue with the burger menu icon on my website. When I click on the burger icon, it doesn't transform into a cross as intended. Even though I can see that the class .active is being added in the DOM, the menu doesn't respond to the ...

Media query failing to adjust properly

On my website's "about" page, I'm attempting to implement a media query but encountering an issue. In the original CSS, I structured the "information" section into 2 columns with right padding to prevent the content from extending all the way to ...

Replace minor components (SVG) within the primary SVG illustration

I'm interested in transforming SVG elements into the main SVG element. For example, let's say the black square represents the main SVG element. I want to change elements 1, 2, and 3 to different SVG elements using JavaScript code. However, I am u ...

Having trouble with the Bootstrap float right class? Your buttons are refusing to respond?

Currently, I am experimenting with ExpressJS and EJS rendering. I have noticed that the Bootstrap float-right class is not working properly on the navbar. I even attempted using d-flex, but the issue persists. I am unsure if I am missing something in my co ...

JavaScript failing to accurately measure the length

Currently experiencing a Javascript issue where the length of an element is not displayed correctly when using .length, even though it shows up in Chrome console. Here is what it looks like in Chrome console <html xmlns="http://www.w3.o ...

What is the best way to add animation to switch between table rows?

I am looking to add animation effects when table rows appear and disappear. Initially, I attempted using a CSS transition, but it did not work due to the change in the display property. Subsequently, I opted for an animation, which provided the desired o ...

When utilizing state in ReactJS to modify the color of my button, the change does not take effect on the first click. How can I troub

Whenever I click the button that routes to different locations via an API, the route works fine but the button color doesn't change on the first click. To address this issue, I implemented the useState hook and CSS to dynamically change the button co ...

Revamp selected bootstrap attribute

Imagine a scenario where there is: @media (min-width: 576px) { #projects-edit-middle-column .equal-columns-wrapper .equal-columns { width: 50%; padding-right: 25px; } } This is being utilized within a container: <div class="equal-columns ...

Changing navigation position while scrolling to a different anchor using fullpage.js

Currently, I have a lengthy scrolling webpage that utilizes fullpage.js. The navigation is fixed in position over the page and each active slide is highlighted by its corresponding link. My goal is to have the link move to the top position when it's ...

Issue with CSS on various mobile devices

Using this CSS to display a fixed part at the bottom of the mobile screen, I noticed that it works well on the Samsung Grand Prime but appears narrower on the Samsung J7 Max. Here is the code snippet and images for reference: .footer { position: fixed ...

"Media queries in CSS don't consistently apply all styles when reaching the minimum

The CSS styles I am using are as follows: @media (min-width: 1280px) { .window-padding { padding-top: 20px; padding-bottom: 20px; padding-left: 30px; padding-right: 30px; } } @media (min-width: 769px) { .windo ...

Accessing pseudo elements when their sibling is hovered can be achieved by using CSS selectors and combinators

I am struggling with the following html code: <div class="content"> <h2><a href="#">Hero</a></h2> <h2>Hero</h2> <div class ="tricky"></div> </div> The "co ...

Arrange four divisions so that they are displayed in pairs on each row when the viewport width is smaller

I have a row of 4 div elements aligned horizontally from left to right. Each div takes up 25% of the screen width. I am looking for a solution to make them wrap when the user resizes the screen instead of overlapping each other. .MenuSett { margin-to ...