Update the color of the text depending on the background color

When hovering over my CTA, a sliding effect occurs. However, I am facing an issue with the text being difficult to read depending on the background color. To better understand what I'm trying to achieve, you can view the demo here:

Demo on CodePen

The main components of this demo are: HTML:

<div class="at-about-fab">
  <div class="at-about-fab__thumbnail">
    <img alt="Fiat Professional" src="https://fiatprofessionaleastlondon.co.za/wp-content/uploads/2018/02/CallUs.png" />
  </div>
  <div class="at-about-fab__meta">
    <h2>Call Us Now</h2>
    <p><a href="te:555-555-5555">555 555 5555</a></p>
  </div>
</div>

The CSS code for this setup is as follows:

.at-about-fab {
  z-index: 999999;
  position: fixed;
  right: 20px;
  bottom: 20px;
  display: flex;
  align-items: center;
  flex-direction: row;
  transform: translateX(100%);
  transition: 0.2s ease;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;

  &:before {
    content: "";
    position: absolute;
    display: block;
    top: 50%;
    left: -58px;
    width: 58px;
    height: 48px;
    transform: translateY(-50%);
  }

  &:hover {
    transform: translateX(0%);

    .at-about-fab__meta {
      opacity: 1;
    }
  }

  ...
}

If you have any suggestions or advice on how to improve this implementation, especially without relying heavily on JavaScript, it would be greatly appreciated. Thank you in advance!

Answer №1

Here is a suggestion you can try:

Concept

  • Implement a mouseover event on the main container.
  • Within this event handler, define a variable to store the classname that needs to be added.
  • When hovering:
    • Retrieve all sections.
    • Compare the boundaries of the current section with the icon's boundary.
    • If the top of the icon exceeds the top of the section, update the className variable.
    • If not, exit the loop.
    • Remove all existing classes and add the className to the container. You will also need to define corresponding classes in CSS.

Example: View Updated CodePen

var iconContainer = document.querySelector('.at-about-fab');

iconContainer.addEventListener('mouseover', function () {
  var bounds = this.getBoundingClientRect();
  var sections = document.querySelectorAll('.section');
  var className = '';
  Array.from(sections).some(function(el) {
    var currentBounds = el.getBoundingClientRect();
    if(bounds.top > currentBounds.top) {
      className = el.getAttribute('id');
    }
    else {
      return true;
    }
  });
  this.classList.remove('section1', 'section2', 'section3', 'section4');
  this.classList.add(className);
})

Answer №2

Sharing offsite links that could be removed is not recommended, but here's a valuable resource to get started: 7 Practical Tips for Cheating at Design

The summary has been provided in the comments to the CSS.

.at-about-fab {
  z-index: 999999;
  position: fixed;
  /* Adjusted the right property to enhance text block visibility - feel free to disregard*/
  right: 0px;
  bottom: 20px;
  /* Opted for a background color that blends well, like white, which aids readability for those with visual impairments. Added some padding for better spacing */
  background-color: white;
  padding: 5px 20px;
  display: flex;
  align-items: center;
  flex-direction: row;
  transform: translateX(100%);
  transition: 0.2s ease;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;


  &:before {
    content: "";
    position: absolute;
    display: block;
    top: 50%;
    left: -58px;
    width: 58px;
    height: 48px;
    transform: translateY(-50%);
  }

  &:hover {
    transform: translateX(0%);

    .at-about-fab__meta {
      opacity: 1;
    }
  }

  &__thumbnail {
    position: absolute;
    top: 50%;
    left: -58px;
    background: #FFFFFF;
    width: 48px;
    height: 48px;
    border: 1px solid #EEEEEE;
    border-radius: 100%;
    padding: 4px;
    box-sizing: border-box;
    transform: translateY(-50%);
    overflow: hidden;
    cursor: pointer;

    img {
      display: block;
      width: 100%;
      border-radius: 100%;
    }
  }

  &__meta {
    font-family: 'Open Sans', sans-serif;
    opacity: 0;
    transition: 0.2s ease;

    h2,
    p {
      margin: 0;
      padding: 0;
    }

    h2 {
      color: #444444;
      font-size: 14px;
      font-weight: 600;
    }

    p {
      /* For better readability, I went with a lighter shade of grey (#999) instead of #444 */
      color: #999;
      font-size: 12px;
      font-weight: 400;
    }

    a {
      color: inherit;
      font-weight: 400;
      text-decoration: none;
    }
  }
}

/* Sample styling for testing */
.content{
    position:relative;
}


#wrapper
{
    position:relative;
}

.section
{
    width: 100%;
    text-align:center;
    padding:250px 0;
    border:1px solid #666;
}

#section1
{
    background: #fff;
}

#section2
{
    background: #000;
    color:#fff;
}

#section3
{
    background: #444444;
}

#section4
{
    background: #BA2322;
}

Take a look at this Codepen Demo

Answer №3

To achieve the desired effect, you can implement mix-blend-mode: exclusion; by utilizing the data attribute in conjunction with the ::after selector:

.at-about-fab {
  z-index: 999999;
  position: fixed;
  right: 20px;
  bottom: 20px;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
      -ms-flex-align: center;
          align-items: center;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
      -ms-flex-direction: row;
          flex-direction: row;
  -webkit-transform: translateX(100%);
          transform: translateX(100%);
  -webkit-transition: 0.2s ease;
  transition: 0.2s ease;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
.at-about-fab:before {
  content: "";
  position: absolute;
  display: block;
  top: 50%;
  left: -58px;
  width: 58px;
  height: 48px;
  -webkit-transform: translateY(-50%);
          transform: translateY(-50%);
}
.at-about-fab:hover {
  -webkit-transform: translateX(0%);
          transform: translateX(0%);
}
.at-about-fab:hover .at-about-fab__meta {
  opacity: 1;
}
... (CSS code continues) ...

#section4 {
  background: #BA2322;
}
<!-- Credits -->
<!-- Developer - Andy Tran (https://andytran.me) -->
<!-- Design - Andy Tran (https://andytran.me) -->
<div class="at-about-fab">
  <div class="at-about-fab__thumbnail">
    <img alt="Fiat Professional" src="https://fiatprofessionaleastlondon.co.za/wp-content/uploads/2018/02/CallUs.png" />
  </div>
  <div class="at-about-fab__meta">
    <h2>Call Us Now</h2>
    <p><a href="te:555-555-5555">555 555 5555</a></p>
  </div>
</div>

<!-- Just for the sake of testing -->
<div class="content">
  ... (HTML code continues) ...
</div>

You can view the updated codepen with SCSS here.

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

In Javascript, determine the root cause of a boolean expression failing by logging the culprit

Within my JavaScript code, I have a complex predicate that comprises of multiple tests chained together against a value. I am looking for a way to log the specific location in the expression where it fails, if it does fail. Similar to how testing librarie ...

What is the best way to define a custom route in react-router-dom?

My goal is to have the URL display "/login" in the address bar when I am on the login page. // App.js <Routes> {isLoggedIn ? ( <Route path="/" element={<Root onLogout={handleLogout} />}> <Route index e ...

Pass data from a Firebase JavaScript callback function in the Data Access Layer (DAL) to another function in the controller

I have been developing a basic chat application that enables users to send messages in a group chat and see them instantly updated. To achieve this, I opted for Firebase and spent time familiarizing myself with its web API. However, I encountered difficult ...

Is there a way to modify the appearance of blocks in Scratch/Blockly?

I am currently working on customizing the appearance of the blocks in Scratch by looking into adjusting the GitHub repository of scratch-blocks (https://github.com/LLK/scratch-blocks). There is a chance that I might need to modify the GitHub repository of ...

Obtain the content enclosed within parentheses using JavaScript

const str = "(c) (d)"; I need to separate the given string into an array The result should be [0] => 'c' [1] => 'd' ...

Guide on how to modify the CSS styling of a particular <td> element when its parent contains a specific class

.webgrid-table td, th { border: 1px solid #98bf21; padding: 3px 7px 2px; } I am facing an issue where the style defined above is being applied to all td elements. However, I want to exclude the styling for a td that is within a tr element with the ...

Error: Async API Call Triggering Invalid Hook Invocation

When working with my functional component, I encountered an issue while trying to implement a react hook like useMemo or useEffect. It seems that the error may be caused by the asynchronous nature of the API call. In the service file: export const getData ...

The left-floated image extends beyond the boundaries of the div

I have a situation where text and an image are combined but the cat image goes outside of the parent div. Is there a solution to this issue? View the code here <div style="border:1px solid #CCCCCC"> <img style="float: left;" src="http://plac ...

What is the best way to access the id attribute of a <td> element within a <tr> using jQuery?

Can someone assist me with this issue? Is there a way to get the ID of the first or second td element instead of using a loop? Here is an example: "<tr class='test_point' id="+fileName+"><td><img src='"+ROOT_PATH+"/assets/d ...

Discover the method for two form fields to submit data to a distant page, located two pages away

Currently, I'm trying to figure out the best approach for having two fields submitted to a page that is located two pages away. To provide more context, let me elaborate on the situation. On the initial page, there will be two fields - workshop title ...

Implementing an API call in Vue JS on the app.vue component of a single page application

My project is experiencing delays in API requests due to a large amount of data. I have tried adding a cache, but the page still appears white upon creation. I am considering moving the API call to app.vue to speed up the request. Is there a way to do this ...

Text Alignment in a Responsive Design

Is there a way to create a responsive container that automatically centers all items inside it on the page, regardless of the screen size? Thanks :) Images are not included in this code snippet, but here's the code: HTML <!DOCTYPE html> <h ...

Error: Property 'onclick' cannot be set on a null object

JavaScript isn't my strong suit, so I'm struggling to solve this issue. The console is showing me the following error message: Uncaught TypeError: Cannot set property 'onclick' of null <script> var modal = document.getE ...

The most effective method for transferring asynchronous data to pages in Next.js

My current directory structure: - components - NavBar - Header - Layout - pages - pages - demo.js - _app.js - index.js // index.js import React from 'react'; import NewLayout from "../../components/NewLayout/NewLayou ...

When a user scrolls over an element with a data-attribute,

Looking to create a dynamic header effect on scroll? I have two headers, menu1 by default and menu2 hidden with display:none. In specific sections of my website, I've added a special attribute (data-ix="change-header") to trigger the header change. T ...

Add more functionality to the server.js script

I have the server.js file, which serves as the entry point for my Node application and is responsible for invoking three different functions (these functions are only called once when the server is up, such as creating child processes, validation, etc), wh ...

Adapting designs within an Embedded Frame - JQuery

I am dealing with a dialog type popup that appears when a button is clicked by the user. Inside this popup, there is a form that needs to be submitted in order to change the width and height of the popup using the following code: $(document).ready(functio ...

Display the status in the textbox once a dropdown value has been selected

I have a function that allows me to add shops. Within this function, I am able to select whether the shop is OPEN or CLOSED. The goal is for the status of the shop, either OPEN or CLOSED, to appear in a textbox on another modal. When creating a user and ...

Looking for a jQuery Gantt Chart that includes a Treeview, Zoom functionality, and editing capabilities?

I am in need of integrating a dynamic Gantt Chart tool into a room booking solution using jQuery. The Gantt chart should be highly interactive, allowing for drag-and-drop functionality, a tree view on the left to group tasks, and a zoom feature for adjusti ...

Trouble with Styling React-Toastify in TypeScript: struggling to adjust z-index in Toast Container

Currently in the process of developing a React application utilizing TypeScript, I have incorporated the React-Toastify library to handle notifications. However, encountering some challenges with the styling of the ToastContainer component. Specifically, ...