CSS border transition for rounded element - css

I'm trying to achieve a transition effect while hover over a rounded element.
The effect should comes from inside out.
body {
background: #eee;
}
.outer-circle {
position: relative;
width: 32px;
height: 32px;
border-radius: 100%;
}
.outer-circle:hover {
width: 34px;
height: 34px;
border: 2px solid #000;
transition: border 300ms;
transition-timing-function: cubic-bezier(0.64, 0.04, 0.35, 1);
}
.inner-circle {
position: relative;
width: 32px;
height: 32px;
margin: 1px;
border:1px solid #999;
border-radius: 100%;
background: brown;
}
<div class="outer-circle">
<div class="inner-circle">
</div>
</div>
How to get this animation ?

The reason why your example appears to be a little broken is because the outer circle is part of the document flow: whenever you change the border-radius, it will cause the entire layout to be repainted. What you need is to take it out of the document flow, e.g. use position: absolute.
In fact, you don't really need two elements: just one is enough. The filled circle should be the main element, and the pseudo-element is just a smaller version of the circle with a border. The pseudo-element will be the outer circle as you know it. The trick is to:
Absolutely position the pseudo-element behind the filled circle
Set its size to be smaller than the filled circle, and this can be done using scale(0.5) or any arbitrary value that will ensure the outline gets hidden.
Then, when the element is hovered on, you can then scale up the pseudo-element as needed, by setting the transform to scale(1).
The advantage of using this method is that you are not transitioning pixel-precise values like border-width, width, or height, and you can offload that transition over to the GPU.
body {
background: #eee;
}
.circle {
position: relative;
width: 32px;
height: 32px;
border-radius: 100%;
}
.circle {
position: relative;
width: 32px;
height: 32px;
margin: 1px;
border-radius: 100%;
background: brown;
}
.circle::before {
/* Final appearance of the outer circle */
width: 36px;
height: 36px;
border: 2px solid #000;
border-radius: 100%;
/* Position it absolutely and center it relative to the circle */
/* Remember to scale it down, so it's hidden nicely in the back */
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0.5);
content: '';
z-index: -1;
transition: all 300ms;
transition-timing-function: cubic-bezier(0.64, 0.04, 0.35, 1);
}
.circle:hover::before {
transform: translate(-50%, -50%) scale(1);
}
<div class="circle">
</div>

Might this be helpful
body {
background: #eee;
}
.outer-circle {
position: relative;
width: 34px;
height: 34px;
border: 2px solid #eee;
border-radius: 100%;
}
.outer-circle:hover {
width: 36px;
height: 36px;
border: 2px solid #000;
transition: border 300ms;
transition-timing-function: cubic-bezier(0.64, 0.04, 0.35, 1);
}
.inner-circle {
position: relative;
width: 32px;
height: 32px;
margin: 1px;
border:1px solid #999;
border-radius: 100%;
background: brown;
}

Try this code.. i think it will much better from now..
css
body {
background: #eee;
}
.outer-circle {
position: relative;
width: 32px;
height: 32px;
border-radius: 100%;
transition: 0.5s all ease 0s;
}
.outer-circle:hover {
width: 34px;
height: 34px;
transition: 0.5s all ease 0s;
}
.outer-circle:hover .inner-circle {
border-color: #000;
}
.inner-circle {
position: relative;
width: 100%;
height: 100%;
border:2px solid brown;
border-radius: 100%;
background: brown;
}

Related

css: how to prevent absolutely positioned :after element from scaling during transition?

I have an absolutely positioned button on the bottom left cornor. The size is fixed at 15px width and height.
The button has an :after element to increase the clickable area size.
When you hover over the button, the button expands. But this also increases size of the :after element.
How do you prevent the :after element from scaling scale(1.5) with the button element?
I tried playing around with width and height properties but this messes up the positioning.
body {
position: relative;
height: 100vh;
padding:0;
margin: 0;
}
p {
margin: 0;
padding: 0;
}
button {
cursor: pointer;
height: 15px;
width: 15px;
border-radius: 50%;
color: white;
border: none;
background: #ffd86e;
position: absolute;
bottom: 15px;
left: 15px;
z-index: 10000;
}
button::after {
content: '';
/* z-index: -100000; */
position: absolute;
bottom: 50%;
left: 50%;
height: 50px;
width: 50px;
transform: translate(-50%, 50%);
background: transparent;
border: 1px solid black;
}
button:hover {
transform: scale(1.5);
transition: transform 0.2s;
}
<p>element is left bottom corner</p>
<button></button>
Invert the styles applied I.E. apply the styles applied to the button to the :after element and vice-versa. because otherwise the :after element will also expand when hovered over the button
button {
position:relative;
border:1px solid #000;
display: block;
padding: 1.5rem 2.5rem;
}
button::after {
content: '';
z-index: -100000;
position: absolute;
bottom: 50%;
left: 50%;
transform: translate(-50%, 50%);
display: block;
cursor: pointer;
height: 15px;
width: 15px;
border-radius: 50%;
color: white;
border: none;
background: red;
z-index: 10000;
}
button:hover:after {
transform: translate(-50%, 50%) scale(1.5);
transition: transform 0.2s;
}
<p>element is left bottom corner</p>
<button></button>
Just create a second button which will act as a disguise. The button than you want has been given class="orgBut" and the disguised button which will be responsible for adding the borders is given class="afBut".
Both have the same position and properties, just the z-index of afBut is set to 0 so that it goes behind the orgBut.
The ::after selector is given to the afBut i.e. the disguised button which is behind your original button. And hover effect is given to the orgBut.
And that's it.
When you hover above the original button the cursor never goes to the button behind it and that is why the borders that you set are left un-affected.
The code is attached!!
`.orgBut {
cursor: pointer;
height: 15px;
width: 15px;
border-radius: 50%;
color: white;
border: none;
background: #ffd86e;
position: absolute;
bottom: 15px;
left: 15px;
z-index: 10000;
}
.afBut {
cursor: pointer;
height: 15px;
width: 15px;
border-radius: 50%;
color: white;
border: none;
background: #ffd86e;
position: absolute;
bottom: 15px;
left: 15px;
z-index: 0;
}
.afBut::after {
content: '';
/* z-index: -100000; */
position: absolute;
bottom: 50%;
left: 50%;
height: 50px;
width: 50px;
transform: translate(-50%, 50%);
background: transparent;
border: 1px solid black;
}
.orgBut:hover {
transform: scale(1.5);
transition: transform 0.2s;
}`
<p>element is left bottom corner</p>
<button class="orgBut"></button>
<button class="afBut"></button>
Feel free for any further issues

CSS - yet another transition not working question

Trying to understand transition css property, but can't seem to figure out why this code is not working. Border needs to go from solid to dotted
.home {
color: #ff652f;
font-weight: 700;
border-bottom: 18px solid #ff652f;
-webkit-transition: border-bottom 3s ease-in-out;
transition: border-bottom 3s ease-in-out;
}
.home {
border-bottom: 18px dashed #ff652f;
}
Made a jsfiddle here - https://jsfiddle.net/h7925b8g/
Would like the transition to happen slowly. Any ideas what I am doing wrong? Any help is greatly appreciated!
As mentioned in comments, border-style is not animatable, so you can't simply use the transition property to change it.
Instead, you can fake it. How exactly you pull this off depends on what you want the transition to look like. One approach is to use a repeating linear-gradient for the dashed effect and then transition that to overlay the border (either a literal border or just some other element that acts like a border).
For example, sliding up from the bottom:
.home {
color: #ff652f;
font-weight: 700;
width: 200px;
padding-bottom: 10px;
position: relative;
}
.home::before,
.home::after {
content: '';
display: block;
width: 100%;
position: absolute;
bottom: 0;
left: 0;
}
.home::before {
height: 10px;
background-color: orange;
z-index: 0;
}
.home::after {
height: 0px;
transition: height 350ms ease;
background-image: linear-gradient(to right, white 0px 10px, orange 10px 20px, white 20px);
background-size: 20px 100%;
background-repeat: repeat;
z-index: 1;
}
.home:hover::after {
height: 10px;
}
<div class="home">Hover me!</div>
Or sliding in from the left:
.home {
color: #ff652f;
font-weight: 700;
width: 200px;
padding-bottom: 10px;
position: relative;
}
.border-animation {
display: block;
position: absolute;
bottom: 0;
left: 0;
z-index: 0;
width: 100%;
height: 10px;
overflow: hidden;
background-color: orange;
}
.border-animation::after {
content: '';
display: block;
width: 100%;
height: 100%;
position: absolute;
bottom: 0;
left: 0;
z-index: 1;
background-image: linear-gradient(to right, white 0px 10px, orange 10px 20px, white 20px);
background-size: 20px 100%;
background-repeat: repeat;
transform: translateX(-100%);
transition: transform 350ms ease;
}
.home:hover .border-animation::after {
transform: translateX(0);
}
<div class="home">Hover me!<span class="border-animation"></span></div>

How to draw a line using pseudo element right below text and ignore the padding?

I want to draw a line below a link and apply animation on it, so I use pseudo element. It produces the line as expected, but if there is a large padding around the link, the line appears far away. Is there a way to ignore the padding and draw the line right below text?
a {
position: absolute;
padding: 20px 0;
top: 50%;
left: 50%;
margin-top: -30px;
margin-left: -30px;
line-height: 20px;
}
a:after {
position: absolute;
bottom: 0;
left: 0;
width: 0;
content: '';
transition: width .3s;
display: block;
}
a:hover:after {
width: 100%;
border-top: 1px solid #333;
}
<a>Link Text</a>
You can just remove the absolute position since the pseudo is set on :after so that it's placed right after the text.
a {
position: absolute;
padding: 20px 0;
top: 50%;
left: 50%;
margin-top: -30px;
margin-left: -30px;
line-height: 20px;
border: 1px solid aqua;
}
a:after {
content: "";
display: block;
border-top: 1px solid #333;
width: 0;
transition: width .3s;
}
a:hover:after {
width: 100%;
}
<a>Link Text</a>
Side note, you might encounter the double tap behavior for the kind of hover effects on touch devices such as phones, tablets. Add this to fix that:
#media (hover: none) {
a:hover:after {
display: none;
}
}
In addition, the effects can also be done with linear-gradient(), example:
a {
display: inline-block;
text-decoration: none;
border: 1px solid aqua;
font-size: 16px;
padding: 20px 0;
background-image: linear-gradient(to bottom, blue, blue);
background-position: 0 38px; /*adjust this based on font-size and padding*/
background-size: 0 1px;
background-repeat: no-repeat;
transition: background-size .3s;
}
a:hover {
background-size: 100% 1px;
}
Link text

How to rotate pseudo element css

I want to recreate this icon using css pseudo elements (as a toggle indicator):
I have created the nececcary pseudo elements using ::after, ::before and tried to rotate them using transform: rotate(90deg).
How can I tell them to rotate around their own center? I have tried transform-origin: 50% 50%; which does not work. Right now, both pseudo elements got the same right: 10px; but they are not placed above each other, instead they are next to each other.
You can check this JS FIDDLE to illustrate the problem.
First you can use :before and :after pseudo elements and create shape like this DEMO
After that you can rotate parent element for 45deg and get desired result.
.el {
margin: 50px;
position: relative;
transform: rotate(45deg);
display: inline-block;
}
.el:before,
.el:after {
content: '';
width: 30px;
height: 30px;
position: absolute;
}
.el:before {
border-top: 4px solid black;
border-left: 4px solid black;
top: -10px;
left: -10px;
}
.el:after {
border-bottom: 4px solid black;
border-right: 4px solid black;
top: 10px;
left: 10px;
}
<div class="el"></div>
Update: You can also add some transition on :hover like this
.el {
margin: 50px;
position: relative;
transform: rotate(45deg);
display: inline-block;
cursor: pointer;
}
.el:before,
.el:after {
content: '';
width: 30px;
height: 30px;
position: absolute;
transition: all 0.3s ease-in;
}
.el:before {
border-top: 4px solid black;
border-left: 4px solid black;
top: -10px;
left: -10px;
}
.el:after {
border-bottom: 4px solid black;
border-right: 4px solid black;
top: 10px;
left: 10px;
}
.el:hover:before {
top: -15px;
left: -15px;
}
.el:hover:after {
top: 15px;
left: 15px;
}
<div class="el"></div>
transform-origin works fine, it's just that
a) 50% 50% (the object's center) is the default, and
b) you have to center the content of the box. That's a bit tricky because the icon you use doesn't require the full line height. Try adding
::before, ::after {
padding-bottom: .17em;
}
modify the style of #pseudo::after as right: 0;
#div {
background: blue;
width: 80px;
height: 80px;
transform: rotate(45deg);
}
/* tested but not working */
#pseudo::after,
#pseudo::before {
/* transform-origin: 50% 50%; */
}
#pseudo::after {
content: '›';
font-size: 50px;
color: green;
right: 0;
position: absolute;
transform: rotate(90deg);
top: 40px;
}
#pseudo::before {
content: '›';
font-size: 50px;
position: absolute;
color: green;
right: 10px;
top: 10px;
transform: rotate(-90deg);
}
<div id="div"></div>
<div id="pseudo"></div>

Triangle with one rounded corner

I want to make only one rounded corner for a triangle but I'm unable to make it.
Here is my code:
.arrow-left {
width: 0;
height: 0;
border-top: 80px solid transparent;
border-bottom: 80px solid transparent;
border-right: 80px solid blue;
}
<div class="arrow-left"></div>
I need the corner pointing left to be rounded as shown in this image :
I know this is a little hacky, but I don't think there is an easy way to do this with a single class.
All I've done is rotated a box 45 degrees with border-radius:10px and then contained it in another div with width set to the desired width of your arrow and overflow:hidden so that everything that spills over is invisible.
.arrow-left {
position: absolute;
width: 100px;
height: 100px;
left: 20px;
background: black;
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
border-radius: 10px;
}
.cover {
position: absolute;
height: 100px;
width: 40px;
overflow: hidden;
}
<div class="cover">
<div class="arrow-left"></div>
</div>
You can make a responsive triangle with one rounded corner with at least 2 approaches :
With CSS:
With one divand a pseudo element and:
absolute positioning
the padding technique to keep the triangle aspect ratio
2d transforms
overflow:hidden;
the transform technique to make the triangle
.arrow-left {
position: relative;
width: 15%;
padding-bottom:15%;
border-radius: 10px;
overflow: hidden;
transform-origin:100% 0;
transform: rotate(-45deg);
}
.arrow-left:after {
content: "";
position: absolute;
top: 0; right:8px;
width:100%; height:141%;
transform-origin:inherit;
transform: rotate(45deg);
background:#000;
}
<div class="arrow-left"></div>
Note that you need to add the vendor prefixes to the transform and transform-origin properties (more info on canIuse)
With inline SVG:
This example uses one path element for the triangle with a bezier curve command for the rounded corner (Q0 5 0.8 4.2 in the d attribute):
svg{
display:block;
width:10%;
}
<svg viewbox="0 0 5 10">
<path d="M5 0 V10 L0.8 5.8 Q0 5 0.8 4.2z" />
</svg>
You can try this and modify according to your needs.
http://jsfiddle.net/K44mE/947/
#player {
margin: 32px;
position: relative;
width: 400px;
height: 250px;
background-color: #222;
}
#inner {
transform: rotate(45deg);
-ms-transform: rotate(45deg);
-webkit-transform: rotate(45deg);
-o-transform: rotate(45deg);
-moz-transform: rotate(45deg);
background-color: silver;
width: 100px;
height: 100px;
top: 20px;
left: -60px;
position: relative;
-moz-border-radius: 20px;
border-radius: 20px;
}
#outer {
position: absolute;
top: 50px;
left: 165px;
width: 70px;
height: 140px;
overflow: hidden;
}
<div id="player">
<div id="outer">
<div id="inner"> </div>
</div>
</div>
use overflow: hidden;
.corner {
position: absolute;
border-radius: 4px;
overflow: hidden;
top: 0em;
right: 0em;
margin: 0em;
padding: 0em;
text-align: center;
border-color: #E8E8E8;
width: 4em;
height: 4em;
z-index: 1;
-webkit-transition: border-color 0.1s ease;
transition: border-color 0.1s ease;
}
.corner:after {
position: absolute;
content: "";
right: 0em;
top: 0em;
z-index: -1;
width: 0em;
height: 0em;
background-color: transparent !important;
border-top: 0em solid transparent;
border-right: 4em solid transparent;
border-bottom: 4em solid transparent;
border-left: 0em solid transparent;
border-right-color: inherit;
-webkit-transition: border-color 0.1s ease;
transition: border-color 0.1s ease;
}
to your code to add this
border-radius:10px

Resources