I am confused with these button animation codes. These codes produce a pulsating effect button, but I am having difficult time interpret how they work together or what is under the hood.
<div >
btn
</div>
style.css:
.btn:link,
.btn:visited {
position: relative;
border-radius: 10rem;
display: inline-block;
margin-top: 6rem;
text-transform: uppercase;
text-decoration: none;
padding: 1.5rem 4rem;
transition: all 1.2s;
}
.btn:hover {
transform: translateY(-.3rem);
box-shadow: 0 1rem 2rem rgba(0, 0, 0, .3);
}
.btn:active {
transform: translateY(-.1rem);
box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .2);
}
.btn--white {
background-color: #fff;
color: #777;
}
.btn--white::after {
background-color: #fff;
}
.btn::after {
content: "";
display: inline-block;
height: 100%;
width: 100%;
border-radius: 10rem;
position: absolute;
top: 0;
left: 0;
z-index: -1;
transition: all .2s;
}
.btn:hover::after {
transform: scaleX(1.4) scaleY(1.6);
opacity: 0;
}
My main confusions are:
-- How do I read ::before/after use plain English, with .btn::after? Can I read it as: after running .btn code, run these code here? or with .btn--white::after { background-color: #fff;} I can read: after .btn--white executed, paint background white?
-- with .btn::after we created empty btn box right behind the original link button, when we use .btn:hover::after isn't the mouse pointer suppose to hover on the original button link instead of the empty button because of Z-index?
-- How does pulsating effect was rendered here? how does the .btn--white::after get called for constantly repainting the empty button?
Related
I have a hover animation on a link. A line is drawn below the text. It's 2px in height. the problem is that it starts with one height and continues with another height.
Why is it doing that? It does not need to calculate anything because 2px is a fixed number.
How can I get around it?
The animated GIF is taken in Chrome.
:root {
--cp-500: #c53e3a;
--cp-700: #8d1d2d;
--cp-800: #721228;
}
.action a {
background: linear-gradient(45deg, var(--cp-500), var(--cp-800));
color: #fff;
border-radius: 100vh;
padding: .5rem 2rem;
display: inline-block;
border: 1px solid var(--cp-700);
transition: box-shadow 150ms ease-in;
box-shadow: 0 1.25rem 1rem -1rem var(--cp-800);
z-index: 1;
text-decoration: none;
position: relative;
}
.action a:hover {
box-shadow: 0 1rem 1rem -1rem var(--cp-800);
background: var(--cp-700);
}
.action a:before {
content: '';
position: absolute;
bottom: .5rem;
left: 2rem;
width: calc(100% - 4rem);
height: 2px;
background: var(--cp-500);
transform: scaleX(0);
transform-origin: top right;
transition: transform 1000ms ease-in;
z-index: -1;
}
.action a:hover:before {
transform-origin: top left;
transform: scaleX(1);
}
<div class="action">
Test
</div>
I was also able to reproduce your issue. As AlexioVay mentioned above, you should add a scaleY also. But it's not enough, you should set the scaleY to be almost the same as scaleX. Now the line has the same height from the start till the end. See this code: https://jsfiddle.net/q236tmuk/30/
I added the following change to your css:
.action a:hover:before {
transform-origin: top left;
transform: scaleX(1) scaleY(0.99);
}
The following scenario will also work well:
.action a:hover:before {
transform-origin: top left;
transform: scaleX(1) scaleY(1.01);
}
On hover the line height is the same from the start till the end. Don't use the same value for scaleX and scaleY, because that way the height will change after the transform event. It's a browser issue. The only solution is to use a small different value for scaleY.
You mentioned that this behaviour occurs when your browser size is 125%. I could also reproduce this behaviour and tested a lot, including attributes like height and max-height which didn't affect anything.
It seems that scaleX is the main issue and because you use an increased browser size, this behaviour is only visible in this specific browser size (or a bigger browser size than 125%). So it may also behave like this at 100%, but can't be seen since 2px is too small to see it with the human eye is my guess.
Therefore I have also added scaleY(1.2) to transform: on .action a:hover:before which prevents this jittery behaviour.
:root {
--cp-500: #c53e3a;
--cp-700: #8d1d2d;
--cp-800: #721228;
}
.action a {
background: linear-gradient(45deg, var(--cp-500), var(--cp-800));
color: #fff;
border-radius: 100vh;
padding: .5rem 2rem;
display: inline-block;
border: 1px solid var(--cp-700);
transition: box-shadow 150ms ease-in;
box-shadow: 0 1.25rem 1rem -1rem var(--cp-800);
z-index: 1;
text-decoration: none;
position: relative;
}
.action a:hover {
box-shadow: 0 1rem 1rem -1rem var(--cp-800);
background: var(--cp-700);
}
.action a:before {
content: '';
position: absolute;
bottom: .5rem;
left: 2rem;
width: calc(100% - 4rem);
height: 2px;
background: var(--cp-500);
transform: scaleX(0);
transform-origin: top right;
transition: transform 1000ms ease-in;
z-index: -1;
}
.action a:hover:before {
transform-origin: top left;
transform: scaleX(1) scaleY(1.2);
}
<div class="action">
Test
</div>
I am using scss and trying to hide an icon and when I hover the button I want the icon to display. I also want to animate it so I can't use display:none as I believe you can't animate that. So I have tried to use opacity and visibility.
I have 2 problems. Firstly, The text in the button is not centered because the icon is there in an invisible state yet when you go to dev tools you can still see it there. Secondly, the icon does not appear on hover.
.btn {
text-transform: uppercase;
text-decoration: none;
padding: 1.5rem 4rem;
display: inline-block;
font-size: 1.6rem;
box-shadow: 0 1rem 2rem rgba($color-black, .2);
&--primary {
background-color: $color-primary;
color: $color-white;
transition: all .2s;
&__icon {
visibility: hidden;
opacity: 0;
}
&:hover {
transform: translateY(-2px);
&__icon {
visibility: visible;
opacity: 1;
}
}
}
}
Discover More <i class="btn--primary__icon icon-basic-clockwise"></i>
I think the problem is that your icon is displayed inline with zero content. I think you might need to change the icon to display: inline-block; and give it some dimensions. You'll want to set the dimensions to 0px when the icon should not be visible.
I converted your code from SCSS to CSS and replaced the $variables with actual CSS colors to make a working snippet...
.btn {
text-transform: uppercase;
text-decoration: none;
padding: 1.5rem 4rem;
display: inline-block;
font-size: 1.6rem;
box-shadow: 0 1rem 2rem rgba(0,0,0, .2);
width: 240px;
}
.btn--primary {
background-color: red;
color: white;
transition: all .2s;
}
.btn--primary__icon {
display: inline-block;
width: 0px;
height: 0px;
visibility: hidden;
opacity: 0;
}
.btn--primary:hover {
transform: translateY(-2px);
}
.btn--primary:hover .btn--primary__icon {
width: 20px;
height: 20px;
background-color: blue;
visibility: visible;
opacity: 1;
}
<a href="#" class="btn btn--primary">
Discover More
<i class="btn--primary__icon icon-basic-clockwise"></i>
</a>
I created a call-to-action button that makes a small animation on click:
Static and showing ADD TO CART
On click: Background animation (duration 1sec) and content = 'Adding to cart'
After 1sec: New background colour and showing ADDED TO CART Go to Cart
Button template:
Basically, I used the ::after to change the background colour as a progress bar and ::before to the content to ADDING TO CART.
All works perfect BUT the text ADDING TO CART is blurry on the mobile version.
Print on the desktop and mobile:
The relevant code:
changeBtn() {
addCartEl.classList.add('global__main-btn--active');
addCartEl.innerHTML = "Added to cart<span>Go to cart</span>"
}
$('#add-to-cart').on('click', changeBtn());
#keyframes adding {
0% {
width: 0%;
opacity: 1;
}
99% {
width: 99%;
opacity: 1;
}
100% {
width: 100%;
opacity: 0;
}
}
#keyframes txt-adding {
0% {
opacity: 1;
}
80% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#keyframes added {
0% {
color: transparent;
background-color: #6abf58;
}
100% {
color: #b4dfab;
background-color: #3f7634;
}
}
.global__main-btn {
font-size: 20pt;
font-weight: 700;
text-transform: uppercase;
color: white;
background-color: green;
padding: 1rem 5rem;
width: 100%;
border-radius: 0.5rem;
border: 1px solid green;
border-bottom: 4px solid green;
margin-bottom: 0.5rem;
max-width: 450px;
}
.global__main-btn::before {
content: "";
background-color: white;
mask-image: url("../assets/svg/cart-plus-solid.svg");
position: relative;
float: left;
width: 30px;
height: 27px;
}
.global__main-btn:hover {
box-shadow: inset 0 0 4rem green;
cursor: pointer;
}
.global__main-btn--active {
border: none;
padding: 0.6rem 5rem;
position: relative;
color: transparent;
animation: added 0.2s 0.8s normal linear forwards;
min-height: 66px;
}
.global__main-btn--active span {
display: block;
font-weight: 300;
font-size: 12pt;
}
.global__main-btn--active:hover {
box-shadow: inset 0 0 4rem green;
}
.global__main-btn--active::before {
content: "";
width: 100%;
height: 100%;
background-color: green;
border-radius: 0.5rem;
position: absolute;
top: 0;
left: 0;
mask-image: none;
animation: adding 1s normal linear forwards;
}
.global__main-btn--active::after {
content: "Adding to cart";
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
width: 100%;
color: white;
animation: txt-adding 1s normal linear forwards;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button type="submit" class="buy__btn global__main-btn" id="add-to-cart">Add to cart</button>
I had a similar issue and figured it has to do with the transform property. As soon as i added a transformation, the text got blurry. Removing it will solve the problem. This seems to be a webkit or blink engine bug.
I'm building a website currently and am experiencing issues with transform: scale. I've got a button, and when a user hovers over it, two things happen:
A background "sweeps" in diagonally
The button label colour changes
The button grows slightly
I have got this working, and it looks really nice, but after implementing point 3, I'm seeing a weird gap to the left hand side when the button grows.
Here is my code: click for demo
HTML
Hover
CSS
body {
text-align: center;
padding-top: 10%;
}
.button {
display: inline-block;
text-transform: uppercase;
font-size: 1.1em;
font-weight: 600;
background: transparent;
transition: all ease .25s;
border: 3px solid green;
color: green;
position: relative;
overflow: hidden;
z-index: 2;
font-family: sans-serif;
padding: 20px 35px;
text-decoration: none;
}
.button:before {
content: ' ';
transition: all ease-out .25s;
width: 200%;
height: 100%;
position: absolute;
top: 0;
left: 0;
transform-origin: 0 0;
z-index: -1;
transform: skewX(-45deg) translateX(-100%);
background: green;
}
.button:hover:before {
transform: translateX(0);
}
.button:hover {
color: white;
transform: scale(1.1);
}
And here's a screenshot of the gap I'm seeing. This issue occurs in Chrome and Safari (I haven't tested Firefox or IE as I can't download them at work).
Screenshot of weird gap
It "only" appears in Chrome but not Firefox (edit: worse in Edge: first it's on the left then on bottom...). Not sure if a rounding error or something else is the cause of that gap, but I find that replacing border by a box-shadow improves the rendering.
There's still a gap that can be seen near the end of the transition but finally disappears so I added 2 box-shadows on :hover: the new one is inset and fills the gap between "border/box-shadow" and content box faster.
Codepen: http://codepen.io/PhilippeVay/pen/oYjZzK?editors=0100
body {
text-align: center;
padding-top: 10%;
}
.button {
display: inline-block;
text-transform: uppercase;
font-size: 1.1em;
font-weight: 600;
background: transparent;
transition: all ease .25s;
box-shadow: 0 0 0 3px green; /* replaces border which caused a gap in Chr, not Fx */
color: green;
position: relative;
overflow: hidden;
z-index: 2;
font-family: sans-serif;
padding: 19px 34px;
text-decoration: none;
}
.button:before {
content: ' ';
transition: transform ease-out .25s;
width: 200%;
height: 100%;
position: absolute;
top: 0;
left: 0;
transform-origin: 0 0;
z-index: -1;
transform: skewX(-45deg) translateX(-100%);
background: green;
}
.button:hover:before {
transform: translateX(0);
}
.button:hover {
color: white;
box-shadow: 0 0 0 3px green, inset 0 0 0 1px green; /* improves end of transition in Chrome */
transform: scale(1.1);
}
Hover
EDIT: playing with the size of the transitioned :pseudo
.button:before {
content: ' ';
transition: all ease-out .25s;
width: calc(200% + 6px);
height: calc(100% + 6px);
position: absolute;
top: -3px;
left: -3px;
transform-origin: 0 3px;
z-index: -1;
transform: skewX(-45deg) translateX(-100%);
background: green;
}
to take into account the border but that doesn't change anything because of overflow: hidden.
So here's my third try: by adding a container (or having the A element as a container) and keeping the border on the child element, it makes that gap disappear (overflow is around the border).
Codepen: http://codepen.io/PhilippeVay/pen/ZBbKWd
body {
text-align: center;
padding-top: 10%;
}
a {
display: inline-block;
overflow: hidden;
background: transparent;
transition: all ease .25s;
color: green;
position: relative;
z-index: 2;
font-family: sans-serif;
text-decoration: none;
}
a > span {
display: inline-block;
text-transform: uppercase;
font-size: 1.1em;
font-weight: 600;
border: 3px solid green;
padding: 20px 35px;
}
a:before {
content: ' ';
transition: all ease-out .25s;
width: 200%;
height: 100%;
position: absolute;
top: 0;
left: 0;
transform-origin: 0 0;
z-index: -1;
transform: skewX(-45deg) translateX(-100%);
background: green;
}
a:hover:before {
transform: translateX(0);
}
a:hover {
color: white;
transform: scale(1.1);
}
<span class="bd">Hover</span>
Fx transitions till the end flawlessly... and "corrects" the width by adding 2px on the right. But it's already visible in your jsbin so it's another story (and less annoying I guess as user will have clicked by then imho)
I want to implement a CSS-only popup for an image, which should be displayed when the user hovers with the mouse over that image. After reading here, for example in this thread, I came up with this solution:
a.tooltip span {
width: 250px;
border: #000 1px solid;
background: #F8F8F8;
display: none;
padding: 10px;
z-index: 1000000;
opacity: 0;
transition: 750ms all;
}
a.tooltip:hover span {
display: inline;
position: absolute;
top: 10px;
left: 25px;
outline: none;
text-decoration: none;
font-size: 70%;
color: #000;
opacity: 1;
}
However, this solution does not make the popup fade-in, it simply pops up without any delay. Also, I want the popup to fade-out when when user moves away the mouse cursor again.
Any ideas what I am doing wrong, or what I should rather try instead?
PS: This is how I call the code:
<a href="#" class="tooltip">
<img src="questionmark.png" />
<span>Tooltip Text.</span>
</a>
You can't add a transition to an element with display:none; you must do it like this:
a.tooltip span {
position: absolute;
top: 10px;
left: 25px;
width: 250px;
border: #000 1px solid;
background: #F8F8F8;
padding: 10px;
z-index: 1000000;
display: inline;
opacity: 0;
transition: 750ms all;
}
a.tooltip:hover span {
outline: none;
text-decoration: none;
font-size: 70%;
color: #000;
opacity: 1;
}
Just use opacity, that's transition-able. Live example: https://jsfiddle.net/wbpbcyfz/1/