How to smoothen transition of width and height? - html

I have created this animation but it is not smooth. When you hover over the blue circle, a multicolored circle opens up but the opening is shaky, not 100% smooth. Can the animation be smoothened and how?
#container {
border: 1px solid black;
width: 600px;
height: 600px;
position: relative;
}
#circle {
margin: 0;
padding: 0;
border: 1px solid black;
width: 50px;
height: 50px;
border-radius: 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
overflow: hidden;
transition: width 0.2s, height 0.2s;
}
#circle a {
margin: 0;
display: block;
padding: 0;
width: 250px;
height: 220px;
position: absolute;
top: 50%;
left: 50%;
transform-origin: 0 0;
}
#circle a:hover {
opacity: 0.5;
cursor: pointer;
}
#trap1 {
background-color: green;
transform: rotate(0deg) skewX(30deg);
}
#trap2 {
background-color: yellow;
transform: rotate(60deg) skewX(30deg);
}
#trap3 {
background-color: red;
transform: rotate(120deg) skewX(30deg);
}
#trap4 {
background-color: blue;
transform: rotate(180deg) skewX(30deg);
}
#trap5 {
background-color: orange;
transform: rotate(240deg) skewX(30deg);
}
#trap6 {
background-color: purple;
transform: rotate(300deg) skewX(30deg);
}
#hide {
position: absolute;
top: 50%;
left: 50%;
z-index: 1;
transform: translate(-50%, -50%);
width: 50px;
height: 50px;
border-radius: 50%;
background-color: cyan;
}
#circle:hover {
width: 500px;
height: 500px;
}
<div id="container">
<div id="circle">
<div id="hide"></div>
<a id="trap1"></a>
<a id="trap2"></a>
<a id="trap3"></a>
<a id="trap4"></a>
<a id="trap5"></a>
<a id="trap6"></a>
</div>
</div>

Reason: (no links/source to back-up, it is just an educated guess)
I've run into similar a case in the past and what I've managed to find out is that the shake happens due to (I believe) a sub-pixel rendering issue.
When height and width are transitioned, the updates to the element seem to happen pixel by pixel. For example, in the below snippet there are two div elements whose height and width are being transitioned (first one increases by 3px over 5s while second increases by 5px). The key thing to note here is that for the first div there are three visible steps while there are five steps for the second one (meaning they increase pixel by pixel).
div{
display: inline-block;
height: 100px;
width: 100px;
background: red;
border: 1px solid;
margin: 10px;
transition: all 5s linear;
}
div:nth-child(1):hover{
height: 103px;
width: 103px;
}
div:nth-child(2):hover{
height: 105px;
width: 105px;
}
<div></div>
<div></div>
Now you would ask me how does this have any connection with the shake. The connection is that the height and width increase pixel by pixel but the translate(-50%, -50%) means that the no. of px by which to translate the element is sometimes in fractions and it seems like some corrections happen during the actual transition to overcome these fractional values.
Solution: (or a work-around)
Instead of using translate(-50%, -50%) trick for horizontal + vertical centering, if we directly position the element by providing the top and left in pixels, you'd see that there is no shake. Based on my understanding, this is because browsers transition all 4 properties (height, width, top and left) pixel by pixel and hence there are no fractional values that cause the correction.
(Tested on the latest Chrome + Windows 10.)
#container {
border: 1px solid black;
width: 600px;
height: 600px;
position: relative;
}
#circle {
margin: 0;
padding: 0;
border: 1px solid black;
width: 50px;
height: 50px;
border-radius: 50%;
position: absolute;
top: 275px;
left: 275px;
overflow: hidden;
transition: all 0.2s;
}
#circle a {
margin: 0;
display: block;
padding: 0;
width: 250px;
height: 220px;
position: absolute;
top: 50%;
left: 50%;
transform-origin: 0 0;
}
#circle a:hover {
opacity: 0.5;
cursor: pointer;
}
#trap1 {
background-color: green;
transform: rotate(0deg) skewX(30deg);
}
#trap2 {
background-color: yellow;
transform: rotate(60deg) skewX(30deg);
}
#trap3 {
background-color: red;
transform: rotate(120deg) skewX(30deg);
}
#trap4 {
background-color: blue;
transform: rotate(180deg) skewX(30deg);
}
#trap5 {
background-color: orange;
transform: rotate(240deg) skewX(30deg);
}
#trap6 {
background-color: purple;
transform: rotate(300deg) skewX(30deg);
}
#hide {
position: absolute;
top: 50%;
left: 50%;
z-index: 1;
transform: translate(-50%, -50%);
width: 50px;
height: 50px;
border-radius: 50%;
background-color: cyan;
}
#circle:hover {
width: 500px;
height: 500px;
left: 50px;
top: 50px;
}
<div id="container">
<div id="circle">
<div id="hide"></div>
<a id="trap1"></a>
<a id="trap2"></a>
<a id="trap3"></a>
<a id="trap4"></a>
<a id="trap5"></a>
<a id="trap6"></a>
</div>
</div>

Related

Why do I get a faint border around the border of a rotated div in CSS?

I am doing a this challenge on CSS Battle and get a very thin border around the rotated div object. Why is that? How can I get rid of it? When I submit it on the website it also scores only 98.somewhat %, so it's not just a rendering problem.
<div id="a"></div>
<div id="b"></div>
<div id="c"></div>
<style>
body {
background: #222730;
margin: 0;
}
div {
position: absolute;
background: #4CAAB3;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
#a {
width: 400px;
height: 150px;
}
#b {
z-index: 1;
border: solid 50px #222730;
width: 150px;
height: 150px;
transform: translate(-50%, -50%) rotate(45deg);
}
#c {
z-index: 2;
background: #393E46;
border-radius: 25px;
width: 50px;
height: 50px;
}
</style>
It's coming from the background property of #b (inherited from div).
Simply shift this property setting to be exclusive to #a:
body {
background: #222730;
margin: 0;
}
div {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
#a {
width: 400px;
height: 150px;
background: #4CAAB3;
}
#b {
z-index: 1;
border: solid 50px #222730;
width: 150px;
height: 150px;
transform: translate(-50%, -50%) rotate(45deg);
}
#c {
z-index: 2;
background: #393E46;
border-radius: 25px;
width: 50px;
height: 50px;
}
<div id="a"></div>
<div id="b"></div>
<div id="c"></div>
You can simplify your code like below:
html {
background:
linear-gradient(#4CAAB3 0 0)center/100% 150px repeat-x /* the bar below the rotate square */
#222730
}
body {
width: 150px;
height: 150px;
margin: 25px auto;
border: 50px solid #222730; /* the border */
background:
#4CAAB3 padding-box /* the main color */
radial-gradient(1px, #393E46 24px, #0000 25px); /* the circle */
transform: rotate(45deg);
}

Limit hover area of CSS shapes to :after

I am trying to make a sort of Venn-Diagram that is going to be used for navigation later.
I have three intersecting ellipsoids created with CSS shapes. Each ellipsoid, as well as their two intersections, will be distinct links later on. Also, when you hover over them they should pop out as per transform: scale(1.3).
My issue is that I'm using ellipsoids which are partially transparent with :after to create the intersections, which creates a problem when hovering over them because the :hover condition gets triggered when hovering anywhere on the partially transparent ellipsoid and not just the :after part. This means that the nonintersecting areas are not hoverable because they are obstructed by the other invisible ellipsoid.
I think the example will make this clearer.
Here is the code:
CSS:
.venn-container{position: relative; left: 0;}
.cat_one{
width: 400px;
height: 200px;
background: red;
border-radius: 200px / 100px;
position: absolute;
float: left;
opacity: 0.5;
}
.cat_two{
width: 400px;
height: 200px;
background: green;
border-radius: 200px / 100px;
position: absolute;
float: left;
left: 240px;
opacity: 0.5;
}
.cat_three{
width: 400px;
height: 200px;
background: blue;
border-radius: 200px / 100px;
position: absolute;
float: left;
left: 480px;
opacity: 0.5;
}
.int1{
background: transparent;
width: 400px;
height: 200px;
border-radius: 200px / 100px;
position: relative;
opacity: 0.5;
overflow: hidden;
float: left;
}
.int1:after{
background: black;
position: absolute;
content: '';
border-radius: 200px / 100px;
width: 400px;
height: 200px;
left: 240px;
}
.int1:hover{
transform: scale(1.3);
left: -35px;
}
.int2{
background: transparent;
width: 400px;
height: 200px;
border-radius: 200px / 100px;
position: relative;
opacity: 0.5;
overflow: hidden;
float: left;
left: 80px;
}
.int2:after{
background: black;
position: absolute;
content: '';
border-radius: 200px / 100px;
width: 400px;
height: 200px;
left: -240px;
}
.int2:hover{
transform: scale(1.3);
left: 115px;
}
HTML:
<div class="venn-container">
<div class="cat_one"></div>
<div class="cat_two"></div>
<div class="cat_three"></div>
<div class="int1"></div>
<div class="int2"></div>
</div>
And here is a fiddle: https://jsfiddle.net/y3Lvmuqg/2/
I would like the :hover to only get triggered in the intersections, and later make cat_one and cat_two hoverable outside the intersections.
I don't know if there is a way I'm doing this is the best and I'm open to suggestions.
Thanks for getting back to me #ge0rg I spent about an hour fiddling with CSS and HTML and came up with this code using just divs with background colors, hover events and border radius's (along with a few z-index and positioning techniques).
Hope you enjoy your reworked venn diagram...
You may have to mess around with the size, and definetly will have to mess with the positioning (however they're all inside a div and so it makes it so that you can just position the div and the rest will happen magically) I added a background color to the div just to show that nothing was transparent, and I also added a always on top function for viewing a section, and I hope you enjoy!
.Venn {
background: linear-gradient(to bottom right, blue, lightblue);
}
.d1:hover, .d2:hover, .d3:hover {
color: #565656;
animation: top 2s steps(2, end) forwards;
-webkit-animation: top 2s steps(2, end) forwards;
box-shadow: 0px 0px 20px white;
}
.d1, .d2, .d3 {
overflow-wrap: break-word;
}
.d1 center, .d3 center {
position: absolute;
top: 50%;
left: 50%;
transform: translateY(-50%) translateX(-50%);
}
.d1 {
padding: 10px;
width: 100px;
height: inherit;
z-index: 1;
position: absolute;
border-radius: 100%;
top: 0px;
}
.d3 {
padding: 10px;
width: 100px;
height: inherit;
z-index: 2;
position: absolute;
border-radius: 100%;
top: 0px;
left: 81px;
}
.d1:hover, .d3:hover {
transform: scale(1.05);
}
.d2 {
border-radius: 100% 0;
height: 90px;
width: 87.5px;
transform: rotate(-45deg) scale(.7);
position: absolute;
top: 15px;
left: 55.35px;
z-index: 3;
border: 1px solid black;
}
.d2b {
transform: rotate(45deg);
padding: 0;
margin: 0;
}
.d2b center {
position: relative;
left: 20px;
}
.d2:hover {
transform: rotate(-45deg);
}
.Venn {
height: 100px;
}
-webkit #keyframes top {
99% {
z-index: previous;
background-image: none;
}
100% {
z-index: 7;
}
}
#keyframes top {
99% {
z-index: previous;
background-image: none;
}
100% {
z-index: 7;
}
}
<div class="Venn" style="position: relative; left: 50px; width: 300px; height: 100px;">
<div class="d1" style=" background-color: grey;">
<center> 1 </center>
</div>
<div class="d2" style=" background-color: #AAAAAA;">
<div class="d2b" style="max-width: inherit;">
<center> 2 </center>
</div>
</div>
<div class="d3" style=" background-color: lightgrey;">
<center> 3 </center>
</div>
</div>
For those of you who would prefer a JSfiddle/ CodePen here you go a Codepen.

Hover on parent to trigger transform property

I am attempting to use a hover effect to transform my second arrow #arrowDown2 to go down to show both arrows. I am wanting the hover to trigger on arrowDownWrap.
What am I doing wrong?
#blue {
width: 100%;
height: 300px;
background: blue;
}
#arrowDownWrap {
position: absolute;
bottom: 120px;
left: 50%;
-webkit-transform: translate(-50%,0);transform: translate(-50%,0);
cursor: pointer;
}
#arrowDownWrapInner {
position: relative;
bottom: 40px;
}
#arrowDown, #arrowDown2 {
border: solid #FFF;
border-width: 0 3px 3px 0;
width: 25px;
height: 25px;
display: block;
padding: 3px;
-webkit-transform: rotate(45deg);transform: rotate(45deg);
position: absolute;
top: 0;
left: 0;
}
#arrowDownWrap:hover #arrowDown2 {
-webkit-transform: rotate(45deg), translate(0, 40px);transform: rotate(45deg), translate(0, 40px);
}
<div id="blue">
<div id="arrowDownWrap">
<div id="arrowDownWrapInner">
<i id="arrowDown"></i>
<i id="arrowDown2"></i>
</div>
</div>
</div>
To specify multiple CSS transform properties, no comma is necessary.
Just list them one after another.
For example:
transform: rotate(45deg) translate(0, 40px);
Working example:
#blue {
position: relative;
width: 100%;
height: 150px;
background: blue;
}
#arrowDownWrap {
position: absolute;
bottom: 100px;
left: 50%;
-webkit-transform: translate(-50%, 0);
transform: translate(-50%, 0);
cursor: pointer;
}
#arrowDownWrapInner {
position: relative;
bottom: 20px;
}
#arrowDown,
#arrowDown2 {
border: solid #FFF;
border-width: 0 3px 3px 0;
width: 25px;
height: 25px;
display: block;
padding: 3px;
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
position: absolute;
top: 0;
left: 0;
background-color: red;
}
#arrowDownWrap:hover #arrowDown2 {
-webkit-transform: translate(0, 50px) rotate(45deg);
transform: translate(0, 50px) rotate(45deg);
}
<div id="blue">
<div id="arrowDownWrap">
<div id="arrowDownWrapInner">
<i id="arrowDown"></i>
<i id="arrowDown2"></i>
</div>
</div>
</div>

How center my spinner when it rotate - CSS Animation

I created a spinner in css and I put it in center without animation it works but when I start animation my spinner move away. Specifically When I use "#keyframes spinner" rule.
How I can keep it in center position?
.spinner-animation{
width: 500px;
height: 500px;
position: relative;
background: gray;
}
.spinner-animation > .spinner{
width: 400px;
height: 400px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
border-radius: 50%;
box-shadow: inset 3px 3px 3px red;
animation: spinner 1.2s linear infinite;
}
.spinner-animation > .content{
display: inline-block;
width: 300px;
height: 300px;
border-radius: 50%;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
background-color: black;
text-align: center;
line-height: 300px;
color: white;
}
#keyframes spinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
<div class="spinner-animation">
<span class="spinner"></span>
<div class="content">Loading...</div>
</div>
I modified the animation and added a transform-origin to the spinner :D
.spinner-animation{
width: 500px;
height: 500px;
position: relative;
background: gray;
}
.spinner-animation > .spinner{
width: 400px;
height: 400px;
position: absolute;
left: 50%;
top: 50%;
transform-origin: top left;
transform: translate(-50%,-50%);
border-radius: 50%;
box-shadow: inset 3px 3px 3px red;
animation: spinner 1.2s linear infinite;
}
.spinner-animation > .content{
display: inline-block;
width: 300px;
height: 300px;
border-radius: 50%;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
background-color: black;
text-align: center;
line-height: 300px;
color: white;
}
#keyframes spinner {
0% {
transform: rotate(0deg) translate(-50%,-50%);
}
100% {
transform: rotate(360deg) translate(-50%,-50%);
}
}
<div class="spinner-animation">
<span class="spinner"></span>
<div class="content">Loading...</div>
</div>
Put the span in another container and apply position: absolute to this container
.spinner-animation {
width: 500px;
height: 500px;
position: relative;
background: gray;
}
.holder {
position: absolute;
width: 400px;
height: 400px;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.holder .spinner {
display: block;
width: 100%;
height: 100%;
border-radius: 50%;
box-shadow: inset 3px 3px 3px red;
animation: spinner 1.2s linear infinite;
}
.spinner-animation>.content {
display: inline-block;
width: 300px;
height: 300px;
border-radius: 50%;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background-color: black;
text-align: center;
line-height: 300px;
color: white;
}
#keyframes spinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
<div class="spinner-animation">
<div class="holder">
<span class="spinner"></span>
</div>
<div class="content">Loading...</div>
</div>
The transform in your animation is overwriting the translate() positioning, you need to add translate() to your animation transform property.
.spinner-animation{
width: 500px;
height: 500px;
position: relative;
background: gray;
}
.spinner-animation > .spinner{
width: 400px;
height: 400px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
border-radius: 50%;
box-shadow: inset 3px 3px 3px red;
animation: spinner 1.2s linear infinite;
}
.spinner-animation > .content{
display: inline-block;
width: 300px;
height: 300px;
border-radius: 50%;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
background-color: black;
text-align: center;
line-height: 300px;
color: white;
}
#keyframes spinner {
0% {
transform: translate(-50%,-50%) rotate(0deg);
}
100% {
transform: translate(-50%,-50%) rotate(360deg);
}
}
<div class="spinner-animation">
<span class="spinner"></span>
<div class="content">Loading...</div>
</div>
Flex-box solution: Display the parent element as a flex element, and align (vertically) and justify (horizontally) its absolutely positioned children to the center.
.spinner-animation{
width: 500px;
height: 500px;
background: gray;
display: flex;
align-items: center;
justify-content: center;
}
.spinner-animation > .spinner{
width: 400px;
height: 400px;
position: absolute;
border-radius: 50%;
box-shadow: inset 3px 3px 3px red;
animation: spinner 1.2s linear infinite;
}
.spinner-animation > .content{
display: inline-block;
width: 300px;
height: 300px;
border-radius: 50%;
position: absolute;
background-color: black;
text-align: center;
line-height: 300px;
color: white;
}
#keyframes spinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
<div class="spinner-animation">
<span class="spinner"></span>
<div class="content">Loading...</div>
</div>

Add pointer to the bottom of a div as a continuation of its background image

I'm looking for a way to stack divs, with a pointer leading into the next div that is a continuation of the previous div's background image.
I've looked around and I've seen some options, but in all of them the bottom div has to be a solid color.
For example: http://jsfiddle.net/nhqKb/
#container{
height: 300px;
background: url('http://farm8.staticflickr.com/7358/9532233404_58763bd668_b.jpg') no-repeat;
position: relative;
}
#one {
position: absolute;
width: 100px;
left: 0;
bottom: 0;
border-bottom: 20px solid green;
border-right: 20px solid transparent;
}
#two {
position: absolute;
left: 120px;
bottom: 0;
right: 0;
border-bottom: 20px solid green;
border-left: 20px solid transparent;
}
<div id="container">
<div id="one"></div>
<div id="two"></div>
</div>
Is there any way to implement this using divs with background images instead of solid colors?
You can use skewX and pseudo elements to make this.
#container {
background: url('https://images.unsplash.com/photo-1440635592348-167b1b30296f?ixlib=rb-0.3.5&q=80&fm=jpg&w=1080&fit=max&s=a029f986631f264fdbc8c0272cab9c40') no-repeat;
height: 300px;
position: relative;
overflow: hidden;
}
#one {
background-color: rgba(0, 0, 0, 0.3);
bottom: 0;
left: 0;
padding-bottom: 15px;
position: absolute;
width: 100%;
}
#one:before,
#one:after {
background-color: inherit;
bottom: 100%;
content: '';
padding-bottom: inherit;
position: absolute;
width: 50%;
}
#one:before {
right: 50%;
-ms-transform-origin: 100% 100%;
-webkit-transform-origin: 100% 100%;
transform-origin: 100% 100%;
-ms-transform: skewX(45deg);
-webkit-transform: skewX(45deg);
transform: skewX(45deg);
}
#one:after {
left: 50%;
-ms-transform-origin: 0 100%;
-webkit-transform-origin: 0 100%;
transform-origin: 0 100%;
-ms-transform: skewX(-45deg);
-webkit-transform: skewX(-45deg);
transform: skewX(-45deg);
}
HTML code:
<div id="container">
<div id="one"></div>
</div>