button text is blurred when css translated on hover - html

I'm using a button that moves up on hover. Check it out: https://jsfiddle.net/jmt3yk1v/. Unfortunately, button text becomes blurry when it is in the "hover" state. I've test it on different screens and the pattern seems to be that devices with devicePixelRatio around 1 and slightly above seem to have the most troubles. On Retina displays, there are no issues at all.
So if you are on non retina display, you will definitively see the blurry text. What would be the fix for this problem? Should I avoid css translates or can the blurriness be mitigated.
html:
Linky Button
css:
.bg{
background: linear-gradient(45deg, #275a77 0%, #38c195 100%);
}
.btn {
border-radius: 5px;
color: #fff;
cursor: pointer;
display: inline-block;
font-weight: 400;
letter-spacing: .5px;
margin: 0;
text-transform: uppercase;
-webkit-appearance: none;
}
.btn-default {
border: 0;
/* background: #2a7741; */
padding: 11px 30px;
font-size: 14px;
transition-duration: 0.2s;
transition-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);
}
.inline-block{
display: inline-block;
}
.btn:hover {
transform: translate3d(0,-3px,0);
box-shadow: 0 5px 8px #22222233;
}

If you use negative margin for animation, the blur seems to be gone
.btn:hover {
margin-top: -3px:
box-shadow: 0 5px 8px #22222233;
}

Related

::after pseudo element overflowing element, using overflow:hidden; has extra space

I am trying to make a button with a hover effect and ::after pseudo class is involved.
The ::after pseudo-class covers 100% of the button's height and width, even more just to be sure; then when :hover, the ::after element's width will shrink to 0.
My problem is that I can't precisely size the ::after element, so I simply added overflow: hidden; to the button so that it will cut out the overflowing parts of the ::after pseudo-element. But it cropped a little too much, leaving one pixel between the border and the ::after pseudo-element covering the button.
.btn {
font-family: inherit;
background-color: transparent;
text-decoration: none;
padding: 1rem 1.5rem;
font-size: 2.3rem;
color: #fff;
border: solid 3px #EF9C43;
width: 50%;
border-radius: 100rem;
text-transform: uppercase;
font-weight: 400;
transition: color 0.3s, transform 0.3s, box-shadow 0.3s;
position: relative;
box-shadow: 1rem 1rem 4rem rgba(31, 31, 31, 0.5);
z-index: 5;
backface-visibility: hidden;
overflow: hidden;
}
.btn::after {
content: "";
position: absolute;
top: -2px;
left: -2px;
background-color: #EF9C43;
width: 110%;
height: 110%;
z-index: -1;
transition: width 0.3s;
}
.btn:hover {
font-weight: 600;
color: #1f1f1f;
transform: translateY(-0.3rem);
box-shadow: 1rem 1.5rem 2rem rgba(31, 31, 31, 0.6);
}
.btn:active {
transform: translateY(-0.1rem);
box-shadow: 1rem 1.25rem 2.5rem rgba(31, 31, 31, 0.5);
}
.btn:hover::after {
width: 0;
}
<button class="btn btn--orange">Hire our services</button>
Here is the codepen of my case: https://codepen.io/CoolBoiDave/pen/bGLdwxE
Any help would be appreciated! (PS: sorry for bad english)
I don't know why would you use an ::after pseudo element when all you need is to
transition a background-image.
Also, you could use an inset box-shadow instead of border.
.btn {
background-color: transparent;
padding: 1rem 1.5rem;
font: 400 2.3rem sans-serif;
text-transform: uppercase;
color: #fff;
border: 0;
border-radius: 4rem;
font-weight: 400;
transition: color .3s, background-position .3s, box-shadow .3s;
box-shadow: 0 1rem 4rem rgba(0,0,0,0.3), inset 0 0 0 3px #EF9C43;
background-image: linear-gradient(90deg, rgba(255,145,0,1) 50%, rgba(0,0,0,0) 50%);
background-size: 200%;
}
.btn:hover,
.btn:active {
background-position: 100%;
color: #1f1f1f;
box-shadow: 0 1.5rem 2rem rgba(0,0,0,0.3), inset 0 0 0 3px #EF9C43;
}
<button class="btn btn--orange">Hire our services</button>

Weird quick switching between normal and hover state CSS

I just created a custom styled button with an effect when hovering. However if you are unlucky and find a specific spot while hovering on the button it quickly switches between the normal and hover state.
My code:
button {
height: 34px;
padding: 0 16px;
border-radius: 4px;
margin: 8px;
border: none;
background: red;
color: #fff;
transition: background .2s, transform .2s;
outline: none;
cursor: pointer;
}
button:hover {
box-shadow: 4px 4px 0 0 blue;
transform: translate(-1px, -1px);
}
button:active {
background: green;
box-shadow: 2px 2px 0 0 blue;
}
<button>I am a button</button>
Code
Is there a trick to solve this issue?
The cause is the transform on hover. As soon as you stop hovering, the button goes back to place. If you've only moved one pixel away, you are now hovering the button again, which moves 1px away, and now is not hovered, and so on.
The best solution would be to remove the transform effect.
If you can't, a simple solution would be to add a transparent border around the button when it's hovered. You'll have to go another pixel to stop hovering the button, and when the hover stops you'll be outside of the new button position.
button {
height: 34px;
padding: 0 16px;
border-radius: 4px;
margin: 8px;
border: none;
background: red;
color: #fff;
transition: background .2s, transform .2s;
outline: none;
cursor: pointer;
}
button:hover {
box-shadow: 4px 4px 0 0 blue;
transform: translate(-1px, -1px);
border: 1px solid transparent;
}
button:active {
background: green;
box-shadow: 2px 2px 0 0 blue;
}
<button>I am a button</button>
A solution could be to add a container with a small padding, and check the hover on it instead of the button. Since it doesn't move, you shouldn't have the problem.
#buttonContainer {
display: inline-block;
padding: 2px;
}
button {
height: 34px;
padding: 0 16px;
border-radius: 4px;
margin: 8px;
border: none;
background: red;
color: #fff;
transition: background .2s, transform .2s;
outline: none;
cursor: pointer;
}
#buttonContainer:hover button{
box-shadow: 4px 4px 0 0 blue;
transform: translate(-1px, -1px);
}
button:active {
background: green;
box-shadow: 2px 2px 0 0 blue;
}
<div id="buttonContainer">
<button>I am a button</button>
</div>

How to make a button with no border (gradient background) the same size as a button with a border (outline)?

I'm using Bootstrap v4 as the base for this code. Essentially, my problem is this: I'd like to make use of a gradient background for primary buttons, but we make use of outline as well. Because there's not really support for gradient borders, I'm not sure how best to ensure that both buttons end up being the same height & width with that missing 2px border on the primary buttons.
The above screenshot shows the problem. I did come up with this as one fix (which works great in Chrome):
background-color: var(--background) !important;
background-image: var(--gradient-background) !important;
border-width: 2px !important;
border-style: solid !important;
border-image-source: var(--gradient-background) !important;
border-image-slice: 1 !important;
Which (in Chrome) results in this:
which accurately depicts what I want my end result to look like. However, in Firefox, there's a weird bug which ends up like this:
And finally, setting the border to a transparent color adds a weird effect to the edges in both browsers:
Here's a Codepen that's messy but shows correctly the issue with transparent borders: https://codepen.io/anon/pen/ymvYQX
So I'm looking to do any of the following -
1) I would love some help figuring out how to get rid of the bug on Firefox so it renders exactly the same as it does on Chrome.
2) Alternatively, how else can I fix the original issue? Is there another way to force resizing of the buttons? What about a better alternative for the gradient border lines?
Thanks for your help!
You need to increase background-size to cover also the borders, else, you'll see it repeating:
.btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active, .show > .btn-primary.dropdown-toggle {
color: #fff;
background-color: #074c81;
border-color: #074575;
}
.btn:not(:disabled):not(.disabled):active, .btn:not(:disabled):not(.disabled).active {
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
}
.btn-primary:hover {
color: #fff;
background-color: #08548d;
border-color: #074c81;
}
.btn:hover {
color: #58595b;
text-decoration: none;
}
button:not(:disabled), [type="button"]:not(:disabled), [type="reset"]:not(:disabled), [type="submit"]:not(:disabled) {
cursor: pointer;
}
.Button_root__2FLmr:hover, .Button_root__2FLmr:active, .Button_root__2FLmr:focus {
outline: none !important;
box-shadow: none !important;
}
.DrawerGroup_root___Kf5l button {
margin: 1rem 1rem 0 0 !important;
}
.btn-primary {
color: #fff;
background-color: #0a69b1;
border-color: #0a69b1;
box-shadow: none;
}
.btn {
display: inline-block;
font-weight: 400;
color: #58595b;
text-align: center;
vertical-align: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: transparent;
border: 2px solid transparent;
padding: 0px 0.75rem;
font-size: 1rem;
line-height: 1.5;
border-radius: 9px;
-webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
button, [type="button"], [type="reset"], [type="submit"] {
-webkit-appearance: button;
}
.Button_gradientBackground__2z0L9 {
background-color: #279DD9 !important;
background-image: linear-gradient(-60deg, #279DD9, #1169B2);
border: 2px solid transparent !important;
background-position:center;
background-size: calc(100% + 4px);/* or 101% is also fine */
}
.btn-outline-secondary {
color: #6c757d;
border-color: #6c757d;
}
.Button_root__2FLmr {
padding: 2px 1rem !important;
min-width: 7rem;
white-space: nowrap;
}
<div class="DrawerGroup_root___Kf5l">
<button type="button" class="Button_root__2FLmr Button_gradientBackground__2z0L9 btn btn-primary">save</button>
<button type="button" class="Button_root__2FLmr btn btn-outline-secondary">cancel</button>
</div>
The easiest way I know of to get "borderless" items that perfectly line up with your bordered items, is simply to use a transparent border.
border-color: rgba(0,0,0,0);
To handle the background issues, you can offset and grow the background image using a combination of background-size and background-position
E.g.
button {
background: linear-gradient(-60deg, #279DD9, #1169B2);
border: 2px solid #000;
width: 80px;
background-size: 84px;
background-position: -2px;
}
#b {
border-color: rgba(0, 0, 0, 0);
}
<button id="a">Button 1</button>
<button id="b">Button 2</button>
No need to hard code any value. All you need is to add background-origin: border-box;ref so that your background consider the border area too. By default it's padding-box so it will cover the padding area then will repeat inside border:
.btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active, .show > .btn-primary.dropdown-toggle {
color: #fff;
background-color: #074c81;
border-color: #074575;
}
.btn:not(:disabled):not(.disabled):active, .btn:not(:disabled):not(.disabled).active {
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
}
.btn-primary:hover {
color: #fff;
background-color: #08548d;
border-color: #074c81;
}
.btn:hover {
color: #58595b;
text-decoration: none;
}
button:not(:disabled), [type="button"]:not(:disabled), [type="reset"]:not(:disabled), [type="submit"]:not(:disabled) {
cursor: pointer;
}
.Button_root__2FLmr:hover, .Button_root__2FLmr:active, .Button_root__2FLmr:focus {
outline: none !important;
box-shadow: none !important;
}
.DrawerGroup_root___Kf5l button {
margin: 1rem 1rem 0 0 !important;
}
.btn-primary {
color: #fff;
background-color: #0a69b1;
border-color: #0a69b1;
box-shadow: none;
}
.btn {
display: inline-block;
font-weight: 400;
color: #58595b;
text-align: center;
vertical-align: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: transparent;
border: 2px solid transparent;
padding: 0px 0.75rem;
font-size: 1rem;
line-height: 1.5;
border-radius: 9px;
-webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
button, [type="button"], [type="reset"], [type="submit"] {
-webkit-appearance: button;
}
.Button_gradientBackground__2z0L9 {
background-color: #279DD9 !important;
background-image: linear-gradient(-60deg, #279DD9, #1169B2);
border: 2px solid transparent !important;
background-position:center;
background-origin: border-box;
}
.btn-outline-secondary {
color: #6c757d;
border-color: #6c757d;
}
.Button_root__2FLmr {
padding: 2px 1rem !important;
min-width: 7rem;
white-space: nowrap;
}
<div class="DrawerGroup_root___Kf5l">
<button type="button" class="Button_root__2FLmr Button_gradientBackground__2z0L9 btn btn-primary">save</button>
<button type="button" class="Button_root__2FLmr btn btn-outline-secondary">cancel</button>
</div>
Related question for more detail: Why doesn't this radial-gradient complete the circle?

Button disappearing briefly on hover

I have never run into this issue before. My input/button disappears for a brief moment when I hover over it.
Does anyone know why this would happen?
.button {
padding: 10px 12px;
border: 1px solid #BE1E2D;
border-radius: 2px;
box-sizing: border-box;
font-family: 'Muli', sans-serif;
font-size: 1.4rem;
color: #FFF;
background: linear-gradient(to bottom right, #BE1E2D, #981824);
text-transform: uppercase;
text-decoration: none;
transition: all .3s ease-in-out;-webkit-transition: all .3s ease-in-out;
cursor: pointer;
}
.button:hover {
background: #BE1E2D;
transition: all .3s ease-in-out;-webkit-transition: all .3s ease-in-out;
}
<input type="submit" value="Submit" class="button">
THIS POST IS FOR REFERENCE ONLY
As Turnip stated; the issue is that you're apply a transition: onto a gradient background so the background needs to be reset from null the first time the transition is effected.
You do not need to set a transition in the :hover state.
There's no need for transition all; only set transitons on the elements you actually want to change.
Removing the gradient issue (commented out) solves the problem.
You seem to have syntax issue: to right bottom is the correct syntax; not "to bottom right" it is [left|right] [top|bottom]
Therefore your question is an exact duplicate of Use CSS3 transitions with gradient backgrounds
Slowing down the transition and increasing the colour differences for clarity below:
.button {
padding: 10px 12px;
border: 1px solid #BE1E2D;
border-radius: 2px;
box-sizing: border-box;
font-family: 'Muli', sans-serif;
font-size: 1.4rem;
color: #FFF;
background: #981824;
/*background: linear-gradient(to right bottom, #BE1E2D, #99CC55);*/
text-transform: uppercase;
text-decoration: none;
transition: background 1s ease-in-out;
-webkit-transition: background 1s ease-in-out;
cursor: pointer;
}
.button:hover {
/*background: #BE1E2D;*/
background: #99CC55;
}
<input type="submit" value="Submit" class="button">
And with Gradients,
Partial Answer:
After my various fixes, now after the first instance where it loads from white, the gradient transition works correctly (on more Firefox) :
.button {
padding: 10px 12px;
border: 1px solid #BE1E2D;
border-radius: 2px;
box-sizing: border-box;
font-family: 'Muli', sans-serif;
font-size: 1.4rem;
color: #FFF;
background: linear-gradient(to right bottom, #BE1E2D, #99CC55);
text-transform: uppercase;
text-decoration: none;
transition: background 1s ease-in-out;
-webkit-transition: background 1s ease-in-out;
cursor: pointer;
}
.button:hover {
background: #BE1E2D;
}
<input type="submit" value="Submit" class="button">

Is it possible for the color to 'erase' the background in CSS?

I really doubt what I am asking is possible but it's still worth a try.
I am trying to create a button that normally has background-color: transparent; color: white; and when you hover over it, those properties should swap. The problem is that if you just swap them then all you see is a white button. If you know the background colour of the containing element then you can get the colour from there but If the button is over an image or a canvas then this won't work.
This is how I've been doing it so far
html,
body {
height: 100%;
}
#container {
background-color: #38404D;
height: 100%;
}
.ghost-button {
background-color: transparent;
border: 1px solid #ffffff;
outline: none !important;
transition: all 0.8s;
margin: 10px 10px;
padding: 6px 7px;
cursor: pointer;
color: #ffffff;
}
.ghost-button:hover {
background-color: #ffffff;
color: #38404D;
}
.ghost-button:active {
box-shadow: inset 0 0 8px 0px #888888;
}
<div id="container">
<button class="ghost-button">Hover Here</button>
</div>
UPDATE
It seems that quite a few people were confused by the question. I am asking if there is a way to do the exact same thing I've done above but on top of an image or a canvas (instead of a solid colour). See example below
html,
body {
height: 100%;
}
#container {
background-image: url("http://www.freegreatpicture.com/files/147/17878-hd-color-background-wallpaper.jpg");
height: 100%;
}
.ghost-button {
background-color: transparent;
border: 1px solid #ffffff;
outline: none !important;
transition: all 0.8s;
margin: 10px 10px;
padding: 6px 7px;
cursor: pointer;
color: #ffffff;
}
.ghost-button:hover {
background-color: #ffffff;
color: #38404D;
}
.ghost-button:active {
box-shadow: inset 0 0 8px 0px #888888;
}
<div id="container">
<button class="ghost-button">Hover Here</button>
</div>
Yes, it IS possible in CSS with mix-blend-mode.
Answer's update in April 2021: Currently it have a very solid support (95% globally) although Safari doesn't have hue, saturation, color, and luminosity blend modes. Of course, IE isn't a considerable thing if you expect to use it (like many of other cool CSS features of the last years).
.ghost-button {
/* Important part */
mix-blend-mode: screen;
background: #000;
color: #fff;
/* Button cosmetics */
border: .125em solid #fff;
font: 2em/1 Cursive;
letter-spacing: 1px;
outline: none !important;
transition: all .8s;
padding: .5em 1em;
cursor: pointer;
}
.ghost-button:hover {
/* Important part */
background: #fff;
color: #000;
}
#container {
background: url('http://www.freegreatpicture.com/files/147/17878-hd-color-background-wallpaper.jpg') center/cover;
/* Also works with background-color or gradients: */
/* background: linear-gradient(to right, red, yellow); */
/* Container positioning */
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
html, body {
margin: 0;
}
<div id="container">
<button class="ghost-button">Hover Here</button>
</div>
As you can see, the secret here is using mix-blend-mode: screen along with the black color for the "erased" part, since black is mixed with the background when using this screen mode.
No, it isn't possible in CSS! You could try to set the color with JS to mimic this effect.
body {
height: 100%;
}
#container {
background-color: #38404D;
height: 100%;
}
.ghost-button {
background-color: transparent;
border: 1px solid #ffffff;
outline: none !important;
transition: all 0.8s;
margin: 10px 10px;
padding: 6px 7px;
cursor: pointer;
color: #ffffff;
}
.ghost-button:hover {
background-color: none;
color: red;
}
.ghost-button:active {
box-shadow: inset 0 0 8px 0px #888888;
}
<div id="container">
<button class="ghost-button">Hover Here</button>
</div>
hover color is set to red you can update it.