Hard problem Animation CSS3 with gradient color on click with icon

How to ensure that when clicking on the icon a colored background appears gradually?
I chose the heart icon for users to select and save their favorite.
And I want the background color to disappear if the user deselects their favorite.

I use just CSS3 , not jquery or JS. I don’t understand why my code doesn’t work

Thank you for your help.

.fa-heart:hover::after {
  opacity: 1;
}
.fa-heart::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: linear-gradient(0deg, #9356dc, #ff79da);
  opacity: 0;
  transition: opacity 250ms;
}
.fa-heart {
  cursor: pointer;
}
              <h3></h3>

              <p class="paragraph"></p>

              <div class="position-icon">

                <div class="position-heart-1">

                  <i class="fas fa-heart"></i>

                </div>

              </div>

            </div>
.fa-heart::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: linear-gradient(0deg, #9356dc, #ff79da);
  opacity: 0;
  transition: opacity 250ms;
}

This…

transition: opacity 250ms;

is saying to transition in 250 milliseconds.

ms” stands for milliseconds. 1ms = 1/1000 of a second.
250ms = 0.25 seconds, which is pretty fast (250 thousandths or 25 hundredths of a second).

The lower that number, the faster it happens. The higher the number, the slower.

Now, with that knowledge, experiment with that number and try to slow the transition down.

Test it with say, 5 seconds (5000ms) and see the difference.

1 Like

As for the heart icon, I am not seeing any icons when I test your code. There is no text, icons or images in between the tags. It is a blank page.

Is that all of your code?

Please clarify.

I use icon from https://fontawesome.com/ .

when I look at the transition, it is good, but I don’t understand why it forms a square which is placed above the icon, being a junior I have really struggled for 2 days.

I have ma container with h1, p and icon and I put css for icon. I add a font face for the icon and I have the link on html for fontawesome. Is that perhaps why the icon does not appear when you test? Thank you for your help, I’m sorry for the mistake when I write.

And I want the background color to disappear if the user deselects their favorite = but For this effect we must add the :active pseudo element ?
But I don’t understant why the background does not take the shape of the square.
I have 2 problem, I search why…
art

like this image, I select your post,
I
I wish the same by adding my transition
Heart

************************************************************************
EDIT: The information in this reply is incorrect.
I wasn’t familiar with “FontAwesome” at the time of this reply.
Disregard this reply and see more recent replies below.
************************************************************************

The icon appears to be an SVG. Scalable Vector Graphics which can be used as an image. But you need more than just…


              <h3></h3>
              <p class="paragraph"></p>
              <div class="position-icon">
                <div class="position-heart-1">
                  <i class="fas fa-heart"></i> <!-- this line !-->
                </div>
              </div>
            </div>

Those are empty HTML tags. You have defined the tags and attributes, but you have not placed any content between them.

You need to download that icon. Save as svg file, which you can open in a text editor like notepad, notepad++, etc.

In there you will see the code that makes the SVG icon.

You need to copy the tag in that file and put it between the tags on your HTML document.

              <h3></h3>
              <p class="paragraph"></p>
              <div class="position-icon">
                <div class="position-heart-1">
                  <i class="fas fa-heart"><svg></svg></i> <!-- this line !-->
                </div>
              </div>
            </div>

In that file, the svg tags are

<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="heart" 
class="svg-inline--fa fa-heart fa-w-16" role="img" xmlns="http://www.w3.org
/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M462.3 62.6C407.5
 15.9 326 24.3 275.7 76.2L256 96.5l-19.7-20.3C186.1 24.3 104.5 15.9 49.7 62.6c-62.8 53.6-66.1 149.8-9.9 207.9l193.5 199.8c12.5 12.9 32.8 12.9 45.3 
0l193.5-199.8c56.3-58.1 53-154.3-9.8-207.9z"></path></svg>

I am not familiar with all the attributes and properties of SVG, so you will have to research that, how to change the size, color, etc.

It’s ok… but lets focus on one problem at a time :smiley:

Thank you very much for your help, I will search :slight_smile: I understand :slight_smile:

Ok, so I think I misunderstood you in the beginning. My apologies…

My previous post was not very good information now that I realize that “Font Awesome” is a CSS library for adding custom icons by using <i></i> tags for the SVG icon placement, properties, class, etc.

So I downloaded the free package from Hosting Font Awesome Yourself and set it up in my www directory of my WAMP setup to test it.

I configured a test HTML page with:

<head>  
<link href="./css/fontawesome.css" rel="stylesheet">
  <link href="./css/brands.css" rel="stylesheet">
  <link href="./css/solid.css" rel="stylesheet">
  <link href="./css/all.css" rel="stylesheet">
  <link href="./css/mystyles.css" rel="stylesheet">
  <script defer src="./js/all.js"></script>
  <script defer src="./js/brands.js"></script>
  <script defer src="./js/solid.js"></script>
  <script defer src="./js/fontawesome.js"></script>
</head>

to import all the dependencies (without worrying about something missing) and then got the shape to work properly.

then I made my own "mystyles.css" style sheet which imported above… so I could add some additional CSS and override some of the "Font Awesome" defaults without having to mess with their "all.css" file.

so in my custom "mystyles.css" file I have this:

body {

}

h1 {
  color: navy;
  margin-left: 20px;
}

.position-heart-1 {
  font-size: 2em;

}

.fa-heart:hover::after {
  opacity: 1;
  color: #ff79da;
  
}
.fa-heart::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  color: #ff79da;
  opacity: 0;
}

.fa-heart {
  cursor: pointer;
  color: #9356dc;
}



.color-trasition-hover {
  color: /* #ff79da; */ #9356dc;
  transition: color 5000ms;
 
}

.color-trasition-hover:hover {
  color: #ff79da;
}

and in the "HTML" file, I have this…

</html>
<head>
  <link href="./css/fontawesome.css" rel="stylesheet">
  <link href="./css/brands.css" rel="stylesheet">
  <link href="./css/solid.css" rel="stylesheet">
  <link href="./css/all.css" rel="stylesheet">
  <link href="./css/mystyles.css" rel="stylesheet">
  <script defer src="./js/all.js"></script>
  <script defer src="./js/brands.js"></script>
  <script defer src="./js/solid.js"></script>
  <script defer src="./js/fontawesome.js"></script>

<title>
</title>
</head>

</style>

<body>

<h3></h3>

            <div>

              <p class="paragraph"></p>

              <div class="position-icon">

                <div class="position-heart-1">

                  <i class="fas fa-heart fa-2x color-trasition-hover"></i>

                </div>

              </div>

            </div>
            
</body>
</html>

I added another class to the tag:

<i class="fas fa-heart fa-2x color-transition-hover"></i>

so now I get this when I load the page and hover over it…

slowly transitions to this…

I am not really familiar with the “Font Awesome” product. They have some documentation at their site Basic Use , with links to other topics at the right of that page .

The gradient color is not working for me. I looked at their site, and saw information about animations and things, but I did not find anything about using gradient colors.

I did get it working with a transition from a single solid color to another single solid color, as you can see in the screenshot. It transitions from that purple to pink on mouse hover. Then back to purple after moving the mouse away.

So this will take more research.

Sorry, for the long post (because of the screenshots and code).

So you want it to be like this?..

1
hsxB9Brpka

or like this?..

2
NOTT5rxNvK

or something else?

Sorry for answers to late I want effect 2. It’s very complicated but I change code, I will send my code now, I want background inside heart.

I search and I see properties :
background-clip: border-box|padding-box|content-box|initial|inherit;

Sorry for answers to late I want effect 2. It’s very complicated but I change code, I will send my code now, I want background inside heart on click (:focus) and : Hover.

It might be easier to use the SVG version.

Anyway, you can try using stacking for the icons. Here is a simple example with just one icon. You need to adjust the JS if you have more than one.
https://codepen.io/lasjorg/pen/JjWNmwJ

2 Likes

@lasjorg “Awesome Font!” (pun intended :smiley:) Thanks for that. I think that’s exactly what devastud wanted in terms of the aesthetics.

@devastud Take a look at that codepen that lasjorg posted. It uses very minimal JS. It’s basically one function that does a toggle. So it’s not “pure” CSS, but much less code and very clean and straightforward, easy to understand.

I also want to point out that if you plan to use a pure CSS solution to make a “real” working “like” button, you are not going to be able to track “likes” and save the state of the toggle button in pure CSS.

If you try keep the state of the toggle by using the pseudo-element’s visited property as if it was a clicked link (assuming someone could get that to work, I could not) it is not a reliable solution.

What happens when a user reloads the page or clears browser history/cache? And storing client side session browser cookies is not a reliable way to store info that needs to be more permanent either.

You would need a programmatic way to handle the logic of the counter and save the state of the toggle. You don’t want a page reload or clearing of browser history/cache to reset the visited link color (toggle it back to unvisited/not clicked), or clear the number of “likes” counter. So the state and counter info would need to be stored on server side and served to the user when they visit the page.

This is why sites use something like JSON and a database or some file that is stored on the server, which is updated as necessary, for this functionality. That is how (or at least one way) sites like this site and other social media sites save the number of “likes” and the status of the “likes” toggle button element.

I’m not seeing a way to do this in CSS, as this goes beyond the styling of content and is not what CSS is for. Even if there was some way, it would be far less complicated to just use some combination of JS, JSON, AJAX for that part.

If you plan on doing a lot of things like this, or doing a lot of front-end development, it would benefit you a lot to learn JS, JSON, JQuery at some point in the future.

Just to clarify, there is no jQuery in that Codepen it’s just plain JS used to toggle a class on and off.


I mainly used JS because it’s a state change and I have come to find that I like to keep CSS clean of that (for the most).

You can do stuff with pseudo-classes but unless you are dealing with HTML elements where that makes sense, for example, :focus for an input element, or :active for a button element, I don’t really think it should be used, or at least used sparingly.

You can also toggle state in CSS using hidden checkbox elements and the :checked pseudo-class (checkbox hack). But in my opinion, unless you absolutely can’t use JS (for whatever reason) I wouldn’t go with such solutions.

2 Likes

@devastud As for the reason the background was appearing on top of the shape as a square block covering the shape…

background: property is referring to the layer behind the text/font/image.

You needed to work directly with the icon (font) itself and fill it with a color.

FontAwesome basically turns an SVG into a font which they call an icon, so it is basically like text. Any property you can apply to text, you should be able to apply to the icon.

In the content property of the pseudo-element class, it uses unicode characters like content: "\f004"; for the heart. Simply changing that value to some other unicode character (you can get this from their site) will change the icon to something else.
For example, \f005 is a star.

FontAwesome uses the font-weight: property to set thickness of the icon.

  • They use font-weight: 400 for the outline version, which they call “regular” and

  • They use font-weight: 900 for the filled version, which they call “solid”.

When you use the background: property in the context of pseudo-element::before or pseudo-element::after, you are specifying the background layer, the layer behind the text. That is why it was covering up the icon’s shape with a square block. It was basically bringing that layer to the top.

CSS uses a “box model” and layers for styling, positioning, etc. You can see this if you open Chrome or Firefox’s “Web Developer” tools and using the “Inspect Element” tool.

Oh, right my mistake. Plain JS. Yes. I see it. I’ve been awake a long time and my brain is becoming mushy :grin: I will edit that reply to save confusion.

Thanks!

2 Likes

@devastud

One last thing. I think it is important to get our terminology straight for clarification and understanding…

The pink in the image below is a “gradient” color which is a “transition” (not to be confused with CSS transition property) of 2 or more colors in a static image (not animated)…

graidient-color

I have always had trouble using gradient colors with CSS transition effect, so I try to avoid them. When I have tried in the past, it just immediatley changes with no delay/fade-in effect. Also, with these FontAwesome icons (fonts) when I tried to make the heart a gradient color, it would just turn the heart black. I don’t understand why, I am not a CSS expert, I am a learner, like you.

The image below is using a “gradient” color for the page background color,
body element background property set to "-webkit-gradient(linear, left top, left bottom, from(#9356dc), to(#ff79da));"

The image below shows the page’s body element background property set to "-webkit-gradient(linear, left top, left bottom, from(#9356dc), to(#ff79da));"

the font (icon) element’s background: property set to white;

and icon’s (font) color property set to grey;

See how they are layers and you have to target or specify the proper one to get the desired outcome.

Finally, the image below shows an animated CSS transition effect using CSS hover element, transition: property set to “5000ms”; (5 seconds)
(page body background is white;, icon (font) background color set to white; , icon (font) color transitions gradually from grey; to red; over 5s; seconds)…here I set font-weight: 900; in pseudo-element::before and pseudo-element:hover::before; because it delay wasn’t working correct when going 400 to 900 (to make solid… probably the wrong approach though… but I wanted to demonstrate the transition. You can tell I am not a CSS expert :smiley:).

I think the terminology and what it all means within context, is what was causing confusion here.

in the end, I think lasjorg’s solution is much better.