how does CSS determine which way to animate a transition? - css

I have this code for a banner that will reveal a drop down section when hovered over:
The HTML code below:
<div id="top_wrapper" class="hori_wrapper wrapper">
<div id="top" class="hori_banner banner"></div>
<div id="top_reveal" class="hori_reveal reveal"></div>
</div>
And the CSS:
.wrapper {
border: dashed;
position: relative;
}
.banner {
background: blue;
position: relative;
}
.reveal {
background: red;
position: absolute;
z-index: 1;
}
.hori_wrapper {
width: 300px;
height: 50px;
clear: both;
}
.hori_banner {
width: 300px;
height: 50px;
}
.hori_reveal {
width: 300px;
height: 0px;
}
#top:hover + #top_reveal, #top_reveal:hover {
-webkit-transition: height 1s ease-in .5s;
-o-transition: height 1s ease-in .5s;
-moz-transition: height 1s ease-in .5s;
-transition: height 1s ease-in .5s;
height: 300px;
top: 50px;
}
Basically, what I'd like to know is: how does CSS determine that it should animate downwards and not some other direction?
Thanks!

All that happens is that it transitions to what would happen if the property was set normally.
In other words, if the height was 300px, and the top was 50px, what would it look like?
It's nothing more complex like that, and is why for browsers that don't support transitions things still work, just with no animation.

Related

Safari CSS transition on scale with border radius

I came across a strange issue on Safari. Please take a look at: https://codepen.io/enguerranws/pen/PomzqWe
If you go hover the lightly red box, you'll notice a transition on an element inside.
If you test it in Chrome or Firefox, the animation runs as expected: it's a small black circle that scales up.
On Safari, it goes weird: it's a black square with some kind of transparency that goes round and fully opaque when the transition ends.
Here's the relevant part of code:
#test:hover #circle {
transform: scale(200);
}
#circle {
position: absolute;
transition: -webkit-transform .5s ease-in-out;
transition: transform .5s ease-in-out;
/* transition: all 1s ease; */
width: 2px;
height: 2px;
top: 30px;
border-radius: 10px;
mix-blend-mode: difference;
background-color: #000;
}
Does anyone as quick and dirty hack for this?
EDIT:
Actually, I found a way to get around this issue using width and height values for transform.
Try to use will-change: transform;. Added to your code:
#test {
width: 400px;
height: 400px;
position: relative;
overflow: hidden;
padding: 40% 10px;
background: rgba(255,0,0,.1);
}
#test:hover #circle {
transform: scale(1);
}
#circle {
position: absolute;
transition: transform .5s ease-in-out;
will-change: transform;
transform: scale(.005); /* point */
transform-origin:left top;
width: 2px;
height: 2px;
top: 30px;
border-radius: 400px;
width: 400px;
height: 400px;
background-color: #000;
}
<div id="test">
<div id="circle"></div>
Text here
</div>

Css div ease in and out

I am trying to make my div fade in and out with only css. Could someone please help me.
.overlay {
display: none;
}
.image:hover .overlay {
box-sizing: border-box;
display: block;
height: 100%;
left: 0;
-moz-box-sizing: border-box;
position: absolute;
top: 0;
-webkit-box-sizing: border-box;
width: 100%;
}
I would suggest using the opacity property that can be animated with transition.
Try the following:
#container {
position: relative;
width: 50px;
height: 50px;
}
img {
width: 100%;
height: 100%;
background-color: black;
}
.overlay {
position: absolute;
background-color: blue;
width: 100%;
height: 100%;
top: 0;
opacity: 0;
transition: opacity 1s ease-in-out;
-o-transition: opacity 1s ease-in-out; /* for compatibility with older versions of Opera */
-ms-transition: opacity 1s ease-in-out; /* for compatibility with IE and Edge */
-moz-transition: opacity 1s ease-in-out; /* for compatibility with Firefox */
-webkit-transition: opacity 1s ease-in-out; /* for compatibility with Chrome, Safari... */
}
#container:hover>.overlay {
opacity: 1;
}
<p>Try hovering over the image:</p>
<div id="container">
<img>
<div class="overlay"></div>
</div>
Note: <img> is a self-contained tag. That is, it cannot contain elements.
You will need a wrapping div as shown in the example with a container that contains both your image and the overlay.
I hope this helps.

Changing size on hover: ugly flicker/"shaking" effect

I want to change the size of an HTML element on mouse over. It works in general. However, at least in Firefox, it creates an ugly flicker effect, when the mouse is right at the bottom edge of the DIV: the browser will then keep resizing even if the mouse is not moved at all. Is there anything I can do about that?
.my-hover-square {
width: 240px;
height: 240px;
position: absolute;
display: -webkit-inline-box;
-webkit-transition: height 1s;
/* Safari */
transition: height 1s;
-webkit-transition: width 1s;
/* Safari */
transition: width 1s;
background: pink;
}
.my-hover-square:hover {
width: 450px;
height: 200px;
}
<div class="my-hover-square"></div>
Your second transition is overriding the first
You need to combine them:
transition: height 1s, width 1s;
.my-hover-square {
width: 240px;
height: 240px;
transition: height 1s, width 1s;
background: pink;
}
.my-hover-square:hover {
width: 450px;
height: 200px;
}
<div class="my-hover-square"></div>
.my-hover-square {
width: 240px;
height: 240px;
position: absolute;
display: -webkit-inline-box;
/* -webkit-transition: height 1s;
Safari
transition: height 1s;
-webkit-transition: width 1s;
Safari
transition: width 1s;
*/
transition: width 1s, height 1s;
-webkit-transition: width 1s, height 1s;
background: pink;
}
.my-hover-square:hover {
width: 450px;
height: 200px;
}
<div class="my-hover-square"></div>
If you write transition: height 1s; and write transition: width 1s;, it's duplicate.
So only transition: width 1s; can be active.
When you want to use multiple attribute with transition,
You shoulde use like this transition: width 1s, height 1s, ...;
You could wrap it:
.hover-container {
min-width: 240px;
height: 240px;
}
.hover-container>.my-hover-square {
width: 240px;
height: 240px;
position: absolute;
display: -webkit-inline-box;
-webkit-transition: height 1s;
/* Safari */
transition: height 1s width 1s;
-webkit-transition: width 1s;
/* Safari */
transition: width 1s;
background: pink;
}
.hover-container:hover>.my-hover-square {
width: 450px;
height: 200px;
}
<div class="hover-container">
<div class="my-hover-square"></div>
</div>
For me, it's freaking out because you're changing the height of the div, which moves it away from the mouse pointer, which removes the :hover pseudo class, which results in the div resizing, which moves it back under the mouse pointer, which adds the :hover pseudo class. Rinse and repeat. I don't think it's possible to keep the resize and not have this happen using pure css.
.my-hover-square {
width: 240px;
height: 240px;
position: absolute;
display: -webkit-inline-box;
-webkit-transition: height 1s;
/* Safari */
transition: height 1s;
-webkit-transition: width 1s;
/* Safari */
transition: width 1s;
background: pink;
}
.my-hover-square:hover {
width: 450px;
}
<div class="my-hover-square"></div>

Why most of the sidebar examples have left 250 and margin-left -250?

Looking at most of the examples in bootstrap, I see that sidebars have css of left:250px and margin-left:-250px.
Why not just have left: 0px which would give the same result?
Example:
#sidebar-wrapper {
z-index: 1000;
position: fixed;
left: 250px;
width: 0;
height: 100%;
margin-left: -250px;
overflow-y: auto;
background: #000;
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
transition: all 0.5s ease;
}
I noticed in one project that used the practice, there were various #media queries that changed the sidebar to have different widths (and therefore different corresponding values for left and margin-left) at different window sizes.
One feature of doing this is that to hide the sidebar, one could simply call left: 0, and it would move the sidebar by its full width regardless of the current width of the sidebar. This is better than using display: none because it can be animated to slide off of the screen, and different than calling width: 0 because the sidebar could still be visible in the case that it wasn't going off-screen.
For example:
$("button").click(function() {
$(".sidebar, .content").toggleClass("hiddenSidebar");
});
body { margin: 0 }
.content {
left: 100px;
position: relative;
transition: all 0.4s ease 0s;
}
.sidebar {
width: 100px;
left: 100px;
margin-left: -100px;
height: 500px;
background: black;
position: fixed;
transition: all 0.4s ease 0s;
}
#media (max-width: 767px) {
.content { left: 50px; }
.sidebar {
width: 50px;
left: 50px;
margin-left: -50px;
}
}
.hiddenSidebar { left: 0; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sidebar"></div>
<div class="content">
<button>Toggle Sidebar!</button>
</div>

Transition doesn't work on pseudo-element

I want use transition effect in CSS3 but the effect doesn't work.
I think I probably made a mistake but I don't see where it is.
On hover, I want make a border with transition in pseudo-element before. I make a codepen : http://codepen.io/Tef/pen/JYBMgR
<div class="container wrap">
<div class="row">
<div class="box">
<a href="#">
<img src="http://placehold.it/90x90/000000" alt="" />
</a>
</div>
</div>
</div>
.wrap {
margin-top: 50px;
}
.wrap a {
position: relative;
display: inline-block;
-webkit-transition: all 1s;
-moz-transition: all 1s;
-o-transition: all 1s;
-ms-transition: all 1s;
transition: all 1s;
}
.wrap a:hover:before {
content: '';
border: 7px solid #ffffff;
opacity: .7;
width: 90px;
height: 90px;
position: absolute;
left: 0;
top: 0;
}
There are a few issues in your code:
:before only exists on :hover, but it should always be there in order to show an animation.
transition is defined on a, but should actually be on a:before (which is conceptually a different DOM element).
There is no initial state of the border, so transition on hover will just start at defaults, and transition backwards on un-hover won't work. To solve this, just add an initial border state like 0px solid transparent.
Here's your fixed example: http://codepen.io/anon/pen/wKxmvB
Two main issues here. First, you're adding a transition the the anchor element, not it's "::before" pseudo-element. Secondly, you're setting no inital state for the pseudo-element, you're setting everything on hover. If you want to transition you need an initial state and an end state. For example:
.wrap {
margin-top: 50px;
a {
position: relative;
display: inline-block;
&::before{
-webkit-transition: all 1s;
-moz-transition: all 1s;
-o-transition: all 1s;
-ms-transition: all 1s;
transition: all 1s;
content: '';
border: 0 solid #ffffff;
opacity: 0;
width: 90px;
height: 90px;
position: absolute;
left: 0;
top: 0;
}
&:hover {
&::before {
border: 7px solid #ffffff;
opacity: .7;
}
}
}
}
Notice the transition is on the pseudo element, and I've set the initial values for the inital state for this element (opacity: 0 + border: 0)

Resources