CSS transitions flickering during multiple changes - css

In short, I have a button with a darker bottom border, and, on hover, I want the button to move down a little and shrink the border (to give the effect of pressing it).
However, it jitters slightly as it animates, completely killing the feel of the button "pressing".
Here's a Fiddle demonstrating the issue, along with the CSS in question:
.btn {
color: grey;
background: lightgrey;
border: 0 rgba(0, 0, 0, .1) solid;
border-bottom-width: 4px;
font-family: sans-serif;
padding: 10px;
position: relative;
text-decoration: none;
top: 0;
transition: all 250ms;
}
.btn:hover {
top: 2px;
border-bottom-width: 2px;
}
I'm not using the prefixes like -webkit here for the sake of simplicity.
The main issue is the bottom border. The button slides down fine, but the border appears to be doing something different (and isn't smooth).
Any ideas here?

Try to replace the top transition with transform: translateY(2px), also replace the bottom border with a ::before pseudo element and animate it's scale property:
https://jsfiddle.net/qjfstq1c/1/
.btn, .btn:before {
transition: all 250ms;
transform-origin: top center;
}
.btn {
display: inline-block;
color: grey;
background: lightgrey;
font-family: sans-serif;
padding: 10px;
position: relative;
text-decoration: none;
}
.btn:before {
content: '';
position: absolute;
top: 100%; left: 0; right: 0;
border-top: 4px solid #bebebe;
}
.btn:hover {
transform: translateY(2px);
}
.btn:hover:before {
transform: scaleY(.5);
}

Related

How can I make a transition from left to right?

I wanted my button to change the background color on hover with a transition from left to right. This is what I tried:
.btn {
background-color: transparent;
transition-property: background-color, left, right;
transition-duration: 1s;
color: #007eb6;
border: 1px solid #007eb6;
&:hover {
background-color: #007eb6;
color: #fafafa;
border: 1px solid #007eb6;
}
Here is a codepen you can use (Its not mine)
The trick is to set background-position to 0% and on hover change it to 100%
<button>Bangladesh</button>
CSS Code
button {
background-color: red;
color: #fff;
border: none;
outline: none;
padding: 20px 60px;
font-size: 20px;
text-transform: uppercase;
position: relative;
z-index: 1;
cursor: pointer;
}
button::before {
content: "";
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 0;
background-color: green;
transition: .5s;
z-index: -1;
}
button:hover::before {
width: 100%;
}

How can I create an even spaced separated outline with border radius?

I've been trying some solutions found around the web, but they all are just a bit . . . off.
We have a design for a button's :focus style, like so:
That's 2px of empty space and a 2px outline.
Here's what we are doing now:
&::after {
border-radius: 18px;
content: "";
display: block;
margin: -2px;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
&:focus::after {
box-shadow: 0 0 0 2px blue;
}
which is almost good. See how it is just off-keel?
Is there a more reliable approach to this sort of design problem? Nudging the position properties by .5 pixels can hack it into shape but it just breaks elsewhere and makes my CSS bone ache.
you can try with border and background-clip:
button {
height: 50px;
border-radius: 25px;
width: 120px;
text-align: center;
color: #fff;
transition: .2s;
margin: 30px;
border: 3px solid transparent; /* we start transparent */
padding: 3px; /* control the space */
background: green content-box; /* color only the content */
}
button:hover {
border-color: blue; /* change color on hover */
}
body {
background:#f2f2f2;
}
<button>Accept</button>

css hover color change from right till 25% of the div

I have a div element inside of it I have some links. I want the colour of the div to change on mouse hover not to full length of width but only 25% of the div.
When I use the hover properties, it changes the colour of the entire div.
Also please suggest which tag I should put my hover properties- span tag or a tag.
How can I get a smooth transition animation during the colour change?
.c-label {
display: inline-block;
text-align: left;
}
.cloud-label {
display: inline-block;
float: left;
margin: 5px 0;
opacity: 1;
width: 50%;
line-height: 1.2;
font-size: 120%;
text-align: left;
}
.cloud-label a {
transition: all 0.5s;
background: #000;
border-radius: 3px;
color: #fff;
display: block;
font-size: 14px;
padding: 7px 20px;
position: relative;
margin-left: 20px;
text-decoration: none;
transition: color .15s linear;
-webkit-transition: color .15s linear;
-moz-transition: color .15s linear;
}
.cloud-label a::before {
content: "";
display: block;
border-style: solid;
border-color: transparent #138D89 transparent transparent;
border-width: 15.2px;
width: 0px;
left: 0px;
position: absolute;
margin-left: -29px;
margin-top: -15px;
top: 50%;
}
.cloud-label a::after {
content: "";
display: block;
position: absolute;
width: 8px;
height: 8px;
background-color: #fff;
border-radius: 50%;
top: 50%;
margin-top: -4px;
left: -3px;
}
.cloud-label :hover {
background-color: #138D89;
}
<div class="c-label">
<span class="cloud-label">
Gadgets
</span>
</div>
not to full length of width but only 25% of the div
You can use linear-gradient for this.
Also please suggest which tag I should put my hover properties- span tag or a tag
In principle, this does not require additional tags
How can I get a smooth transition animation during the colour change?
When hovering, you need to change the property background-position from one to other side (for example, from left to right).
Result
.link {
position: relative;
display: inline-block;
margin-left: 10px;
padding: 5px 10px;
color: #fff;
font-weight: 700;
text-decoration: none;
background: linear-gradient(to left, #138D89 25%, #000 25%) left / 135% 100% no-repeat;
transition: 0.3s;
}
.link:hover {
background: linear-gradient(to left, #138D89 25%, #000 25%) right / 135% 100% no-repeat;
}
.link::before {
content: "";
position: absolute;
top: 0;
right: 100%;
border-right: 15px solid #138D89;
border-top: 13px solid transparent;
border-bottom: 15px solid transparent;
}
.link::after {
content: "";
position: absolute;
top: 50%;
left: 0;
transform: translate(-50%, -50%);
width: 10px;
height: 10px;
box-sizing: border-box;
background: #fff;
border-radius: 50%;
}
<a class="link" href="">Lorem ipsum dolor sit amet.</a>
And same code on CodePen

CSS button - transparent arrow on both sides

I am trying to create the button below by using the pseudo-elements before and after. I do not want to manipulate the HTML DOM. I'm searching for a solution with pure CSS.
How is it possible to make the currently white border-color of these triangles transparent?
//EDIT: The marked topic does not answer my question because I need a different angle than just rotating a square. It is also not transparent. I don't want to manipulate the DOM.
//SOLVED: This is the result after using Kate Millers solution:
//EDIT2: There is another problem with the solution I use now:
Is there a way to fix the border-width of the triangles (left and right)?
Here you can see how the size changes to 14.4 and 26.4px, 26.4px:
The best solution is to reverse the triangles (so you're adding top and bottom triangles that match the button, but not on the sides). You can technically make "transparent" triangles, but you can't have that transparency apply to a different object.
One of the most important things I changed was that the background color and padding of the button has to apply to the span element (which means each button will need an interior span), not .btn.
If you replace all of your CSS about the buttons with the below, you'll have a solution that gets you at least 90% of the way there. The angle isn't perfect because it's stopping at the text. If you want to make the angle truly perfect, you'll probably need to do some absolute positioning, which would make it messy as your button sizes change.
The non-code way you can also achieve this is to create a .png or .svg with triangles that match the color of your button and insert them into the :before and :after with content: ' ';
body { margin: 20px; background:#c2c2c2; }
.btn {
display: inline-block;
text-shadow: 0 1px 0 #000;
font-weight: bold;
text-transform: uppercase;
}
.btn {
padding: 11px 40px;
color: #fff;
position: relative;
background: #a00;
}
.btn:before, .btn:after {
content: '';
border-top: 20px solid #a00;
border-bottom: 20px solid #a00;
position: absolute;
top: 0;
}
.btn:before {
border-left:20px solid transparent;
left: -20px;
}
.btn:after {
border-right:20px solid transparent;
right:-20px;
}
.btn.inset:before, .btn.inset:after {
content: '';
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
position: absolute;
top: 0;
}
.btn.inset:before {
border-right:20px solid #a00;
left: -40px;
}
.btn.inset:after {
border-left:20px solid #a00;
right:-40px;
}
<div class="btn">Text in my little banner button</div>
<div class="btn inset">Text in my little banner button</div>
I don't use, and am not really familiar with, LESS... but you can create a similar element using a span and a wrapper with pseudo elements. It does take 2 triangles for each side (hence the span).
body { margin: 20px; background: #ddd; }
.btn {
display: inline-block;
padding: 11px 40px;
color: #fff;
position: relative;
background: #a00;
text-shadow: 0 1px 0 #000;
font-weight: bold;
text-transform: uppercase;
}
.btn:after,
.btn span:after,
.btn:before,
.btn span:before {
content: "";
width: 0;
height: 0;
display: block;
position: absolute;
right: 0;
border: 10px solid transparent;
}
.btn:after {
top: 0;
border-right-color: #ddd;
border-bottom-color: #ddd;
}
.btn span:after {
bottom: 0;
border-right-color: #ddd;
border-top-color: #ddd;
}
.btn:before {
top: 0;
left:0;
border-left-color: #ddd;
border-bottom-color: #ddd;
}
.btn span:before {
bottom: 0;
left:0;
border-left-color: #ddd;
border-top-color: #ddd;
}
<div class="btn"><span>Text in my little banner button</span></div>
I realize the ends aren't really transparent, they just match the background color to appear transparent.

how can i add to rectangle with arrows border [duplicate]

I would like to make a button like these one just with CSS without using another element.
Button Image
Since the button has a border attached, I think I normally need both, the :before and :after elements to create just one arrow at one side. So to make one arrow at each side I would need another span element inside the link.
The second method I tried is the one you see below. But with this solution they are not properly centered and each side of the arrow is different in length.
Has someone a solution?
/* General Button Style */
.button {
display: block;
position: relative;
background: #fff;
width: 300px;
height: 80px;
line-height: 80px;
text-align: center;
font-size: 20px;
text-decoration: none;
text-transform: uppercase;
color: #e04e5e;
margin: 40px auto;
font-family: Helvetica, Arial, sans-serif;
box-sizing: border-box;
}
/* Button Border Style */
.button.border {
border: 4px solid #e04e5e;
}
.button.border:hover {
background: #e04e5e;
color: #fff;
}
/* Button Ribbon-Outset Border Style */
.button.ribbon-outset.border:after,
.button.ribbon-outset.border:before {
top: 50%;
content: " ";
height: 43px;
width: 43px;
position: absolute;
pointer-events: none;
background: #fff;
}
.button.ribbon-outset.border:after {
left: -3px;
margin-top: -40px;
transform-origin: 0 0;
box-sizing: border-box;
border-bottom: 4px solid #e04e5e;
border-left: 4px solid #e04e5e;
transform: rotate(57.5deg) skew(30deg);
}
.button.ribbon-outset.border:before {
right: -46px;
margin-top: -40px;
transform-origin: 0 0;
box-sizing: border-box;
border-top: 4px solid #e04e5e;
border-right: 4px solid #e04e5e;
transform: rotate(57.5deg) skew(30deg);
}
.button.ribbon-outset.border:hover:after {
background: #e04e5e
}
.button.ribbon-outset.border:hover:before {
background: #e04e5e
}
Click me!
CodePen Demo
Here is another alternate way to get this done with only one element.
This approach works like below:
Two pseudo-elements :before and :after which are about half the size (including borders) of the main .button element. The height of each pseudo-element is 34px + 4px border on one side (top/bottom) and 2px on the other side.
The top half of the shape is achieved using the :before element whereas the bottom half is achieved using the :after element.
Using a rotateX with perspective to achieve the tilted effect and positioning to place the two elements such that they form the expected shape.
/* General Button Style */
.button {
position: relative;
display: block;
background: transparent;
width: 300px;
height: 80px;
line-height: 80px;
text-align: center;
font-size: 20px;
text-decoration: none;
text-transform: uppercase;
color: #e04e5e;
margin: 40px auto;
font-family: Helvetica, Arial, sans-serif;
box-sizing: border-box;
}
.button:before,
.button:after {
position: absolute;
content: '';
width: 300px;
left: 0px;
height: 34px;
z-index: -1;
}
.button:before {
transform: perspective(15px) rotateX(3deg);
}
.button:after {
top: 40px;
transform: perspective(15px) rotateX(-3deg);
}
/* Button Border Style */
.button.border:before,
.button.border:after {
border: 4px solid #e04e5e;
}
.button.border:before {
border-bottom: none; /* to prevent the border-line showing up in the middle of the shape */
}
.button.border:after {
border-top: none; /* to prevent the border-line showing up in the middle of the shape */
}
/* Button hover styles */
.button.border:hover:before,
.button.border:hover:after {
background: #e04e5e;
}
.button.border:hover {
color: #fff;
}
<!-- Library included to avoid browser prefixes -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
Click me!
Fixed Width Demo | Dynamic Width Demo
Output Screenshot:
This is tested in Chrome v24+, Firefox v19+, Opera v23+, Safari v5.1.7, IE v10.
As-is, this would degrade quite well in IE 8 and IE 9 into a square button with borders. However, due to the nullification of one border (border-bottom for :before and border-top for :after) it would leave a white area (resembling a strike-through line) in the middle. This can be overcome by adding a couple of IE < 10 specific styles using conditional comments like in this demo.
<!--[if IE]>
<style>
.button.border:after{
top: 38px;
}
.button.border:hover:before, .button.border:hover:after {
border-bottom: 4px solid #e04e5e;
}
</style>
<![endif]-->
Output Screenshot from IE 9 and IE 8:
This is just a simpler alternative to Harry's answer.
This approach uses scale() and rotate(45deg) transforms. Using this approach, you can very easily change the angle of right and left chevrons.
Fiddle
div {
height: 70px;
width: 200px;
margin-left: 40px;
border-top: 4px solid #E04E5E;
border-bottom: 4px solid #E04E5E;
position: relative;
text-align: center;
color: #E04E5E;
line-height: 70px;
font-size: 21px;
font-family: sans-serif;
}
div:before, div:after {
content:'';
position: absolute;
top: 13px;
height: 40px;
width: 40px;
border: 4px solid #E04E5E;
-webkit-transform: scale(0.8,1.25) rotate(45deg);
-moz-transform: scale(0.8,1.25) rotate(45deg);
-ms-transform: scale(0.8,1.25) rotate(45deg);
transform: scale(0.8,1.25) rotate(45deg);
}
div:before {
left: -22px;
border-top: 0px solid transparent;
border-right: 0px solid transparent;
}
div:after {
right: -22px;
border-bottom: 0px solid transparent;
border-left: 0px solid transparent;
}
div:hover, div:hover:before, div:hover:after {
background-color: #E04E5E;
color: #EEE;
}
<div>HELLO!</div>
Want a wider arrow? Simply decrease scale() transform's x value : Fiddle (wide)
Narrower one? Increase scale() transform's x value : Fiddle (narrow)
Note: IE 8 and below don't support CSS Transforms (9 supports with -ms- prefix), so you can check out this site for supporting them: IE Transform Translator
I forked your Pen
Codepen Demo
The essential changes are that I removed the side borders from the main button (as they were superflous
/* Button Border Style */
.button.border {
border-top: 4px solid #e04e5e;
border-bottom: 4px solid #e04e5e;
}
and changed a couple of values to tweak it all into place
/* Button Ribbon-Outset Border Style */
.button.ribbon-outset.border:after,
.button.ribbon-outset.border:before {
top: 50%;
content: " ";
height: 43px;
width: 43px;
position: absolute;
pointer-events: none;
}
.button.ribbon-outset.border:after {
left:0;
margin-top:-40px;
transform-origin:0 0;
box-sizing:border-box;
border-bottom:4px solid #e04e5e;
border-left:4px solid #e04e5e;
transform:rotate(57.5deg) skew(30deg);
}
.button.ribbon-outset.border:before {
right:-43px;
margin-top:-40px;
transform-origin:0 0;
box-sizing:border-box;
border-top:4px solid #e04e5e;
border-right:4px solid #e04e5e;
transform:rotate(57.5deg) skew(30deg);
}
I got the answer myself. It was a problem of the transform property of the :before and :after elements.
CSS changed:
/* Button Border Style */
.button.border {
border-top:4px solid #e04e5e;
border-bottom:4px solid #e04e5e;
}
/* Button Ribbon-Outset Border Style */
.button.ribbon-outset.border:after, .button.ribbon-outset.border:before {
height: 42px;
width: 42px;
}
.button.ribbon-outset.border:after {
left:0;
border-bottom:5px solid #e04e5e;
border-left:5px solid #e04e5e;
transform:rotate(45deg) skew(19deg,19deg);
}
.button.ribbon-outset.border:before {
right:-42px;
border-top:5px solid #e04e5e;
border-right:5px solid #e04e5e;
transform:rotate(45deg) skew(19deg,19deg);
}
Updated Codepen

Resources