Stopping a margin transition at its initial point - css

Alright, here's what I have a nifty little scroller (they've been done to death but I wanted to take my hand at making one) and I want it to scroll to the left for X amount of pixels, which is no problem. The problem is, if the user hovers over the left side and starts scrolling the text back, I want it to stop at its initial starting point.
body {
background-color: black;
}
.wrapper {
position: absolute;
left: 50%;
margin-left: -250px;
overflow: hidden;
width: 500px;
height: 300px;
z-index: 98;
border: 3px solid 2a3439;
background-color: #353839;
}
.scroller {
color: white;
width: 1980px;
background-color: transparent;
height: 100%;
position: relative;
padding: 5px;
margin-left: 0px;
transition: all 2s linear 10s;
-moz-transition: all 2s linear 10s;
-webkit-transition: all 2s linear 10s;
}
.go-left:hover~.scroller {
margin-left: -250px;
transition: all 2s linear;
-moz-transition: all 2s linear;
-webkit-transition: all 2s linear ;
}
.go-left {
opacity: 0;
height: 300px;
background-color: red;
width: 200px;
z-index: 99;
position: absolute;
top: 0;
}
.go-right {
opacity: 0;
height: 300px;
background-color: red;
width: 200px;
z-index: 99;
position: absolute;
top: 0;
left: 300px
}
.go-right:hover+.scroller {
margin-left: 250px;
transition: all 2s linear;
-moz-transition: all 2s linear;
-webkit-transition: all 2s linear;
}
.image {
display: block;
overflow: hidden;
Height: 490px;
}
In that example, if you hover to the left I don't want it to move past it's starting point, so clamping it. You can see the working model on jsfiddle https://jsfiddle.net/Kaanha/puy6t4og/51/
This wouldn't be hard using some java, but the main thing here is, I need it to be pure CSS only. No java.
Thanks in advance for all help!

Related

CSS allow overflow-y only when transition ends

I am having some troubles styling my div. I would like to allow overflow-y only when the height transition ends (from 80px to 100% of the parent div). If I uncoment the below "overflow-y: auto" line, the overflow-y works fine but the scroller is visible during the animation which does not look good.
.mydiv{
position: absolute;
width: 100%;
bottom: 0;
border-radius: 0 0 2px 2px;
border: solid 1px #eee;
background-color: #fff;
height: 80px;
transition: all 0.5s;
transition-timing-function: ease-in-out;
overflow: hidden;
clear: both;
}
.mydiv:hover{
height: 100%;
border-radius: 2px;
/* overflow-y: auto; !!! */
}
Edit: Sorry, I forgot to add the animation-fill-mode: forwards so it will pause on end frame and stay as long as hovered. Fixed now.
Edit 2: Added code to reverse anim on mouse out.
I think the only way you may be able to do what you are aiming for is with either css animation frames, or javascript.
CSS Animation (transition the properties that should animate through 99% of animation and only transition overflow property between final 1% of animation:
.mydiv:hover{
animation-duration: 0.5s;
animation-name: 'myAnim';
animation-iteration-count: 1;
animation-timing-function: ease-in-out;
animation-fill-mode: forwards;
}
#keyframes myAnim {
0% {
height: 80px;
border-radius: 0 0 2px 2px;
overflow: hidden;
}
99% {
height: 100%;
border-radius: 2px;
overflow: hidden;
}
100% {
height: 100%;
border-radius: 2px;
overflow: auto;
}
}
That will animate on hover, but on mouse out it will just snap back to original state. You can reverse the animation on mouse out but doing so comes with some issues that should be considered. The only way I know to play animation on mouse out with pure css is to add it to the elements default state.
The reverse animation will play on initial page load. The only workarounds I know are javascript based.
The reverse animation will play from its beginning on mouse-out even if the hover anim didn't have time to complete. This can cause a sudden snap if hovered only briefly. I think this can be addressed with css animation-fill-mode: and animation-delay: values, but I have not managed to make it work.
because of the snapping that may happen on very brief hovers, it is better to use a separate anim for mouse-out so the scrollbar doesn't flicker.
.mydiv{
position: absolute;
width: 100%;
bottom: 0;
border-radius: 0 0 2px 2px;
border: solid 1px #eee;
background-color: #fff;
height: 80px;
overflow: hidden;
clear: both;
animation-duration: 0.5s;
animation-name: 'myAnim';
animation-iteration-count: 1;
animation-timing-function: ease-in-out;
animation-fill-mode: forwards;
}
.mydiv:hover{
animation-duration: 0.5s;
animation-name: 'myAnim';
animation-iteration-count: 1;
animation-timing-function: ease-in-out;
animation-fill-mode: forwards;
}
#keyframes myAnim {
0% {
height: 80px;
border-radius: 0 0 2px 2px;
overflow: hidden;
}
99% {
height: 100%;
border-radius: 2px;
overflow: hidden;
}
100% {
height: 100%;
border-radius: 2px;
overflow: auto;
}
}
#keyframes myAnimOut {
0% {
height: 100%;
border-radius: 2px;
overflow: hidden;
}
100% {
height: 80px;
border-radius: 0 0 2px 2px;
overflow: hidden;
}
}

CSS transition between background image and background color

I'm trying to do a basic ease out transition on a panel with a background image. I'm wanting it to fade to background color on hover. I've tried using various transitions non of which are working. I've tried (which i thought would work):
transition:background-image 0.2s ease-in-out;
.panel {
width:200px;
height:200px;
background:#000 url("https://cdn.pixabay.com/photo/2016/03/28/12/35/cat-1285634_1280.png") no-repeat center center / cover;
transition:background-image 0.2s ease-in-out;
}
.panel:hover {
background:#000;
transition:background-image 0.2s ease-in-out;
}
<div class="panel"></div>
You can use this code:
Demo is here: https://output.jsbin.com/yadiwoviwe
.panel {
position: relative;
background: rgba(0,0,0,0) url(https://cdn.pixabay.com/photo/2016/03/28/12/35/cat-1285634_1280.png) no-repeat center center / cover;
width:200px;
height:200px;
transition: background-color 0.2s ease-in-out;
}
.panel:hover {
background-color: rgba(0,0,0,.5);
}
.panel:before {
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
background-color: inherit;
content: ' ';
}
Unfortunately, you can't do this in this way.
The reason is that you're trying to animate the background-image property - a property that isn't animatable.
Instead, you can use a cool little trick that uses a pseudo-element to create the background image instead:
.panel {
width: 200px;
height: 200px;
position: relative;
background: pink;
}
.panel::after {
content: "";
position: absolute;
pointer-events: none;
background: url(https://unsplash.it/200) center center no-repeat;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1;
will-change: opacity;
transition: opacity .1s ease-out;
}
.panel:hover::after {
opacity: 0.5;
}
<div class="panel"></div>
Inspired by this cool little article on CSSTricks
Alternatively, you can manipulate the opacity of the image.
.panel {
width: 200px;
height: 200px;
background: #000;
position: relative;
color: white;
text-align: center;
}
.panel:after {
content: "";
background-image: url('https://cdn.pixabay.com/photo/2016/03/28/12/35/cat-1285634_1280.png');
background-size: 200px 200px;
position: absolute;
top: 0;
left: 0;
width: 200px;
height: 200px;
opacity: 1;
transition: opacity 0.2s ease-in-out;
}
.panel:hover:after {
opacity: 0;
}
<div class="panel"><h1>Text</h1></div>
Outdated answer, transition with image working currently with CSS.
-webkit-transition: all 1s ease-out;
-moz-transition: all 1s ease-out;
-o-transition: all 1s ease-out;
transition: all 1s ease-out;
background-image instead of 'all' and you'll see.

Safari falsely triggering css3 animation

I've tried to make some minor animations on an image, while it's loading, and when a user is hovering it, but there seems to be an issue when it comes to Safari.
When I hover the "a" tag, which should just trigger a "transition animation" it seems trigger the "loadImg" animation, even though it doesn't seem to be very related to each other. It's tested in Chrome, IE, Edge, Firefox and Opera, and it works fine there.
This the the code I find the most relevant to the issue.
<div class="playerInfo">
<div class="avatarName">
<a href="http://steamcommunity.com/profiles/76561198064550827" target="_blank" title="Click to see Magn0053's profile">
<img src="https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/5d/5d8a752dfea20299845bcd57d64ce04125d02d67_full.jpg" alt="Player avatar">
</a>
<figcaption class="playerName">Magn0053</figcaption>
</div>
</div>
and the css
.playerInfo img {
-webkit-animation: 1s loadImg;
position: relative;
transition: 0.3s linear;
width: 184px;
height: 184px;
top: 0px;
left: 0px;
}
.playerInfo a:hover img{
height:175px;
width:175px;
left:4.5px;
top:4.5px;
position: absolute;
}
I also have an example at https://jsfiddle.net/xhjppg93/.
As a rule of thumb, always use transform scale instead of changing width and height when dealing with transitions. This is because it will be gpu accelerated and it'll work a lot better for mobiles. :) Here's a quick fix for you.
.playerInfo {
width: 184px;
height: 227px;
margin: 0 5px;
}
.avatarName {
height: 206px;
position: relative;
}
.playerInfo a {
height: 184px;
width: 184px;
position: absolute;
left: 0;
top: 0;
border-radius: 10px;
margin: 0;
padding: 0;
}
.playerInfo img,
.playerInfo .imgReplacer {
border-radius: 10px;
margin: 0;
padding: 0;
}
.playerInfo img {
animation: 1s loadImg;
-webkit-animation: 1s loadImg;
-moz-animation: 1s loadImg;
-o-animation: 1s loadImg;
position: relative;
transition: 0.3s linear;
width: 184px;
height: 184px;
top: 0px;
left: 0px;
}
.playerInfo a:hover img {
transform: scale(0.95);
}
.playerName {
animation: 1s nameFix;
-moz-animation: 1s nameFix;
-webkit-animation: 1s nameFix;
-o-animation: 1s nameFix;
position: absolute;
bottom: 0;
}
#keyframes nameFix {
0% {
position: absolute;
bottom: 0;
}
100% {
bottom: 0;
position: absolute;
}
}
#keyframes loadImg {
0% {
height: 0px;
width: 0px;
left: 50%;
top: 50%;
position: absolute;
}
100% {
height: 184px;
width: 184px;
left: 0;
position: absolute;
top: 0;
}
}
<div class="playerInfo">
<div class="avatarName">
<a href="http://steamcommunity.com/profiles/76561198064550827" target="_blank" title="Click to see Magn0053's profile">
<img src="https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/5d/5d8a752dfea20299845bcd57d64ce04125d02d67_full.jpg" alt="Player avatar">
</a>
<figcaption class="playerName">Magn0053</figcaption>
</div>
</div>
Try these:
-webkit-transition: 0.3s linear;
-webkit-transition: -webkit-transform 0.3s linear;

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>

CSS Transition Not Returning To Original Shape & Can't Click Multiple Times

Here's the CodePen.
The square changes to a circle as expected when it slides to the right, but when it returns back to the left, it stays a circle instead of changing to a square.
Also, I can only click the <a> once. If I try to click multiple times, it doesn't work.
Trying to do this with only CSS (if possible).
body {
margin-top: 30px;
background: gainsboro;
}
.container {
margin: auto;
width: 100%;
}
.path {
position: relative;
overflow: hidden;
width: 100%;
height: 80px;
x-background: white;
}
#keyframes ani {
0% {
left: 0;
}
50% {
left: 95%;
}
100% {
left: 0;
}
}
.shape:target {
border-radius: 50%;
transition: all .7s ease-in-out;
animation-name: ani;
animation-duration: 2s;
animation-direction: alternate;
animation-fill-mode: none;
}
.shape {
position: absolute;
left: 0;
background-color: slateblue;
width: 80px;
height: 80px;
display: block;
border-radius: none;
transition: border-radius .4s ease-out;
}
<div class="container">
<div class="path">
<span id="elem" class="shape"></span>
</div>
</div>
The closest you can get with just CSS is this, as far as I know:
body {
margin-top: 30px;
background: gainsboro;
}
.container {
margin: auto;
width: 100%;
}
.path {
position: relative;
overflow: hidden;
width: 100%;
height: 80px;
x-background: white;
}
#keyframes ani {
0% {
left: 0;
}
50% {
left: 95%;
}
100% {
left: 0;
}
}
.path a:focus .shape {
border-radius: 50%;
transition: all .7s ease-in-out;
animation-name: ani;
animation-duration: 2s;
animation-direction: alternate;
animation-fill-mode: none;
}
.shape {
position: absolute;
left: 0;
background-color: slateblue;
width: 80px;
height: 80px;
display: block;
border-radius: none;
transition: border-radius .4s ease-out;
}
<div class="container">
<div class="path">
<span id="elem" class="shape"></span>
</div>
</div>
The problem before was triggering the state with :target:. This is tough to debug with sites like Codepen or other embedded editors, since you can't see the hash change. Basically, clicking the link would append #elem to the URL, apply the :target styles to .shape, and stay like that until the hash changes.
This solution uses :focus, which gets you closer to your goal, but not all the way. To repeat the animation, you need to defocus/blur the circle, then click it again.
I'm usually all for CSS-only effects, but I'm pretty sure you'll need Javascript for this. Something as simple as applying a class on click, waiting 2 seconds, then removing the class would accomplish the same effect more reliably.

Resources