The combination of CSS grayscale filter and colored gradient is a powerful design tool for

My goal is to achieve a unique CSS effect where:

  1. An image with a color background is grayscaled and has a gradient overlay; and

  2. Upon hover, the gradient fades out while the color fades in.

I've experimented with two techniques but haven't found a perfect solution yet. One option is to have separate grayscale and color versions of the image to minimize loading times, but I'm exploring CSS-only methods first. Any suggestions would be greatly appreciated!

Thanks!

Technique 1: Gradient plus Background-Blend-Mode

In this approach, I applied the gradient directly to the image's background and achieved the grayscale effect using a white background and the background-blend-mode property.

The main issue here is that the transition doesn't seem to work smoothly - the image jumps between states rather than transitioning gradually.

https://jsfiddle.net/Lparts4j/1/

HTML:

<div class="test"></div>

CSS:

.test {
  width: 400px;
  height: 400px;
  background: linear-gradient(135deg, rgb(0, 47, 75) 0%, rgb(220, 66, 37) 80%), url("http://i.imgur.com/ulb7EVg.jpg");
  background-color: white;
  background-blend-mode: multiply, luminosity;
  background-size: cover;
  -webkit-transition: all .5s ease-in-out;
  -moz-transition: all .5s ease-in-out;
  -o-transition: all .5s ease-in-out;
  transition: all .5s ease-in-out; }

.test:hover {
  background: url("http://i.imgur.com/ulb7EVg.jpg");
  background-color: white;
  background-blend-mode: normal;
  background-size: cover; }

Technique 2: Grayscale Filter plus Gradient in :Before Element

In this method, I used a :before element for the gradient and applied the grayscale effect with the filter property.

The fade effect works well in this scenario. However, I struggled with combining the gradient and grayscale without losing color in the gradient.

https://jsfiddle.net/548afgjf/4/

HTML:

<div class="img img-one"></div>
<div class="img img-two"></div>

CSS:

.img {
    position: relative;
    display: inline-block;
    width: 300px;
    height: 400px; }

.img-one {
    background: url('http://i.imgur.com/ulb7EVg.jpg') center center / cover no-repeat;
   -webkit-filter: grayscale(100%);
    filter: grayscale(100%);
    -webkit-transition: all .5s ease-in-out;
    -moz-transition: all .5s ease-in-out;
    -o-transition: all .5s ease-in-out;
    transition: all .5s ease-in-out;
}
.img-one:before {
    content:'';
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    opacity: .6;
    background: rgb(0, 47, 75);
    /* Remaining CSS properties omitted for brevity */
}
.img-one:hover {
    -webkit-filter: grayscale(0%);
    filter: grayscale(0%);
}
.img-one:hover:before {
    opacity: 0; }

.img-two {
    background: url('http://i.imgur.com/ulb7EVg.jpg') center center / cover no-repeat;
    /* Remaining CSS properties omitted for brevity */
}
.img-two:before {
    content:'';
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    opacity: .6;
    background: rgb(0, 47, 75);
    /* Remaining CSS properties omitted for brevity */
}
.img-two:hover:before {
    opacity: 0; }

Answer №1

In the past, I experimented with achieving a greyscale effect and found that the best method to ensure it worked consistently across all browsers was by utilizing SVG elements and applying SVG filters. You might need to take a similar approach for successful implementation.

To begin, you will have to define the SVG filter within your page (the example below only creates a greyscale effect, further research is needed for colorization).

<svg>
  <defs>
    <filter id="greyscale">
      <feColorMatrix type="matrix" values="0.3333 0.3333 0.3333 0 0
      0.3333 0.3333 0.3333 0 0
      0.3333 0.3333 0.3333 0 0
      0 0 0 1 0" />
    </filter>
  </defs>
</svg>

Next, wrap your image within an SVG element:

<svg class="applyFilter" width="100px" height="100px">
  <image class="svgImg" xlink:href="image.png" height="100px" width="100px" />
</svg>

Finally, apply the filter in your CSS:

svg.applyFilter .svgImg {
  filter: url(#greyscale);
}

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

I recently applied a CSS style to a webform, which is functioning properly on the master page but not on a specific webform

I have implemented CSS on my master page and it is displaying properly, however, when I try to apply the same CSS to a specific web form, the styles are not showing up. Even though I have added the necessary icon code to this web form, the icon is not vis ...

The content spills over when applying the Bootstrap Grid system

I am working on creating a display heading that includes images on both the left and right sides of the heading. The layout looks great on larger displays, but as I shrink the display size, the text in the heading overflows the column on the right, causing ...

Switch the dropdown icon in ng-bootstrap when clicked

Click me to switch icon from fa-angle-up to fa-angle-down. Initially displaying the fa-angle-up icon, clicking it will change it to fa-angle-down. <div class="col text-right"> <div ngbDropdown placement="top-right" class="d-inline-block"> ...

How can I apply max-width and max-height to a background image?

It seems like a simple task. I am currently transitioning my layout to become more fluid by working on creating scalable images. While using the img tag and setting max-width to 100% is effective, I am considering using a div with the image set as its bac ...

Generating various header graphics through PHP's header include feature

I'm currently working on a multi-page website that utilizes a header include feature. The background image is already set within a container in the header using CSS, but now I want to have different header images for each page. Since I am still new to ...

Positioning the image to appear behind the Canvas

As I near the end of the game, I'm encountering an issue where the background image overlaps the Canvas. How can I resolve this problem? -Translated by Google Link to game Link to game with background ...

When the width of the screen is less than 992 pixels, my div will be hidden

I have been working with the bootstrap4 layout, and I noticed that when the screen width is less than 992px, the yellow-div is overlapping the brown-div. Can someone explain why this is happening and suggest a solution? Below is the code snippet: .head ...

Creating an Angular 7 Template using HTML CSS and Javascript

I recently acquired a template that comes with HTML, CSS, and Javascript files for a static webpage. My goal is to integrate these existing files into my Angular project so I can link it with a Nodejs application to create a full-stack webpage with backend ...

Is it possible to create a CSS design where alternating table rows have two different heights?

Looking to design a table where the height of every other row is approximately one-third of the preceding row. I've managed to style this with an inline method, but I'm curious if it's possible to create separate tags for different tr styles ...

Avoid auto-scaling of div content

I need the .content within the main container .box to resize proportionally to match the width of the .box exactly, without being smaller. .box { width: 95%; background-color: red; padding: 20px; text-align: center; margin: 55px auto 40px; } . ...

If the DIV does not contain a P tag, then the minimum height of the div should be removed

I have a div that contains an h2 and p tag. I am curious if there is a way to remove the styling from the div if the P tag does not exist. Here is the markup and styling: <style> .hotel-header { min-height: 100px; } </style> <div class="h ...

Ways to retrieve the parent DIV's width and adjust the child DIV's width to match

Attached is my question with the HTML and a screenshot. Within a DIV container (DIV with ID=ctl00_m_g_a788a965_7ee3_414f_bff9_2a561f8ca37d_ctl00_pnlParentContainer), there are two inner DIVs - one for the left column TITLE (DIV ID=dvTitles) and the other f ...

Adjust the column count in mat-grid-list upon the initial loading of the component

My goal is to implement a mat-grid-list of images with a dynamic number of columns based on the screen size. Everything works perfectly except for one small glitch – when the grid first loads, it defaults to 3 columns regardless of the screen size until ...

HTML input field's placeholder text is truncated at the end

My HTML input form has a field with placeholder text that extends beyond the padding and gets cut off at the end. https://i.sstatic.net/9r46F.png I am unable to pinpoint the source of this issue. ...

Toggle the visibility of a div depending on a value that is loaded on the page

I need help with a functionality that will hide or show the following div based on the value of <%= ItemCount%>. If the number is less than five, I want the div to be hidden. On the other hand, if it is above 5, then the div should be visible. Any ...

CSS3 rotation animation - begins to rotate and then halts at a specific angle

I attempted to develop a function that initiates a spin, replaces an image, and then stops the spin. However, when I remove the spin class, it jerks abruptly. How can I halt the spinning smoothly at a specific frame? setTimeout(function() { $('. ...

Modifying the dimensions of mat-card in Angular Material

https://i.stack.imgur.com/CP16N.png I am struggling to make both components the same height, similar to the left form. I have tried adjusting margins and padding but nothing seems to work. Below is the HTML code for the parent element: <mat-tab label= ...

How can I display only the initial image using php?

I need to hide all images except the first one. I do not want to use a SELECT query with LIMIT 0,1 every time. How can I select all images but display only the first one? Currently, I am using the Photoswipe plugin - you can find more information here. Th ...

What is the best way to align two buttons side by side when they are each contained in separate forms?

Is there a way to align the submit buttons in two separate forms side by side? The first form should display as a block level element, while the second form can be inline-block. <form action="#"> <div class="form-group"> <lab ...

How come the div elements in my list are expanding beyond their container?

Below is a simplified version of my code that illustrates the issue I'm facing. I am trying to enclose all the elements within a box and enable scrolling for the .content section. So far, all my attempts at resolving this problem have been unsuccessfu ...