I'm making a css animation (for starters just in Chrome, to avoid needing to retype a bunch of browser specific code a hundred times) with quite a lot going on:
First these steps simultaneously:
Children of element fade out
Height of element changes to fixes height
Background color of element changes
Next step:
Fade in a hidden element
As for what I have, all of step 1 seems to work. I'm tryng to do this all by adding a single class to the element itself, but this causes some difficulties with step 2. Because when the class is added the hidden element should be display: block;, but this unfortunately causes it to already take up space when the first steps are still going on.
Here is a live demo. It only needs to be 1-way, so you have to re-run the fiddle to try the animation again.
This is some basic html:
<div class="card">
<div class="check"><svg style='width:100px;height:100px; margin: 10px auto 10px auto; z-index:20; display: block;' viewBox='0 0 24 24'><path fill='red' d='M10,17L5,12L6.41,10.58L10,14.17L17.59,6.58L19,8M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z' /></svg></div>
<div>Random content</div>
</div>
And a part of the css:
.card.done div:not(.check){
transition: opacity .5s ease-in-out;
opacity: 0;
}
.check:not(.done){
display: none;
margin: auto;
opacity: 0;
transition: opacity 1s 0.5s ease-in-out;
}
.check svg{
height:100px;
margin:10px auto 10px auto;
}
.card.done div.check{
display: block;
opacity: 1;
-webkit-animation-name: fadeInFromNone;
-webkit-animation-duration: 1s;
}
#-webkit-keyframes fadeInFromNone {
0% {
display:none;
opacity: 0;
}
50% {
display: block;
opacity: 0;
}
100% {
display: block;
opacity: 1;
}
}
.card.done{
transition: height .5s ease-in-out;
background-color: #4CAF50;
height: 120px !important;
}
I not entirely sure I understand the problem but I think what your wanting is the SVG element to not take up space which you can do by making it position absolute
http://jsfiddle.net/p9czu73n/
.card.done div.check{
position:absolute;
margin-left:-50px;
left:50%;
....
}
just use:
$(".card").css("height", "auto");
or use add
height:auto; to .card class
anything will fine
Related
I have these 3 rules:
.thingy{
display:inline-block;
position:relative;
width: 5em;
height: 5em;
background-color:#FF0000;
left:0em;
transition: left 4s linear, background-color 4s;
}
.thingy:active{
left:10em;
transition: left 0s linear;
}
.thingy:hover{
background-color:#00FF00;
transition: background-color 0s linear;
}
and this bit of basic HTML:
<div class="thingy"></div>
When the <div> is clicked, it will move to the right, as expected. However, whenever it is hovered over while it is returning to it's original position, it will snap back immediately.
I want it to, while returning to it's original position from being clicked, to be able to swap it's background-color (or any other property) then fade back to it's normal values without overriding any other transition currently going on.
For the purposes of the code, I can only use pure CSS, and I cannot utilize #key-frames or any property associated to it, such as animation-duration.
You can use CSS variable for this task
.thingy {
display: inline-block;
position: relative;
width: 5em;
height: 5em;
background-color: #FF0000;
left: 0em;
transition:
var(--t-left,left 4s linear),
var(--t-back,background-color 4s);
}
.thingy:active {
left: 10em;
--t-left: left 0s;
}
.thingy:hover {
background-color: #00FF00;
--t-back: background-color 0s
}
<div class="thingy"></div>
I have a parent div wrapped around a scaled child div. The child div starts off with transform:scale(0,0); & expands to transform:scale(1,1); when a button is clicked.
.content-wrapper {
display: inline-block;
background-color: #ddf;
padding: 10px;
clear: both;
}
.content {
padding: 10px;
background-color: #fff;
display: flex-block;
overflow: hidden;
transform:scale(0,0);
transform-origin:top;
transition:transform 1s ease-out;
}
.content.open {
transform:scale(1,1);
}
However the parent div content-wrapper stays at the same size of the child div content - even when the child is "closed".
The desired behaviour is when the child div is closed the parent div shrinks to only wrap around the button.
JSFiddle of Example
Is it possible to wrap the parent div around the child div when it's "closed" in this example?
This will be a little challenging because the background color is attached to the content container. I would remove the background color from the main container, then make it a separate div positioned absolute
<div class="content">
...
<div class="content-bg"> //contains your background color
then manipulate that based on your click handler.
I've updated the JSFiddle http://jsfiddle.net/ztxa5kwu/90/
CSS for the new div:
.content-bg{
position: absolute;
background-color: #ddf;
left: 0;
right: 0;
bottom: 0;
top: 0;
z-index: -1;
transition: all .5s ease;
transform-origin: bottom right;
}
Notice the transform-origin: bottom right; to scale the background towards your button. In the JSFiddle, I made the button take on a border the same color as the background, but you could easily edit the size of the new <div class="content-bg"></div> to fit around your button.
Hope that helps, and gets you in the right direction.
Try this:
.content {
background-color: #fff;
overflow: hidden;
transform:scale(0,0);
transform-origin:top;
transition:transform 1s ease-out;
display: block;
padding: 0;
height: 0; width: 0;
}
.content.open {
padding: 10px;
height: auto; width: auto;
transform: scale(1,1);
}
Edit: Play with this:
.content {
padding: 0;
background-color: #fff;
display: block;
overflow: hidden;
transform-origin:top;
transition: transform 1s ease-out, max-width 0.5s ease-out 0.4s, max-height 1s ease-out;
transform: scale(0,0); max-width: 0; max-height: 0;
}
.content.open {
padding: 10px;
transition: transform 1s ease-out, max-width 1s ease-out, max-height 8s ease-out;
transform: scale(1, 1); max-width: 1920px; max-height: 1080px;
}
I found this comment on an older question:
This method only partially achieves the desired effect but doesn't
actually remove the space. The transformed box acts like a
relatively positioned element - the space is taken up no matter how it
is scaled. Check out this jsFiddle which takes your first one and
just adds some bogus text at the bottom. Note how the text below it
doesn't move up when the box height is scaled to zero. – animuson♦ Jul
29 '13 at 20:37
So with that in mind I used the max-height/ max-width hack to get something close to what I was after: http://jsfiddle.net/BaronGrivet/ztxa5kwu/176/
.content {
padding: 10px;
background-color: #fff;
display: flex-block;
overflow: hidden;
transform:scale(0,0);
transform-origin:top;
transition:all 1s ease-out;
max-width: 0;
max-height: 0;
}
.content.open {
transform:scale(1,1);
max-width: 500px;
max-height: 500px;
}
How can I realize a smooth transition for my mobile menu?
The transform property is working, but I want it to happen slowly..
My Sass looks like this
.mobile-nav
display: none
position: relative
width: 100%
background: $white
padding: 30px 0 20px
transform: translateY(-100%)
#media (max-width: 775px)
.mobile-nav.is-o
display: block
transform: translateY(0%)
The main obstacle you're facing is that the display property is not animatable.
Like a light switch, display: none is off and display: block is on. There's no middle ground, no fade effects, no CSS transitions.
However, there are multiple other properties you can use for transitions. Among them:
height
opacity
z-index
background-color
Here's an example:
.mobile-nav-toggle {
font-size: 2em;
cursor: pointer;
}
.mobile-nav {
display: inline-block;
overflow: hidden;
width: 0;
height: 0;
opacity: 0;
transition: width 1s, height 1s, opacity 0s 1s, background-color 0s 2s;
}
.mobile-nav-toggle:hover + .mobile-nav {
width: 150px;
height: 150px;
opacity: 1;
background-color: lightgreen;
transition: 1s;
}
<div class="mobile-nav-toggle">☰</div>
<div class="mobile-nav">
<ul>
<li><a>Item</a></li>
<li><a>Item</a></li>
<li><a>Item</a></li>
</ul>
</div>
References:
Full list of animatable properties in CSS
Transitions on the display: property
I personally use opacity combined with visibility to achieve fade effect like I would like for whole element. Remember to manipulate z-index, so you "hidden" object won't be clickable when dissapeared.
So i've recently working on some private project, and since i am a huge CSS fan i want to do most of the animations in CSS rather than in JavaScript.
Today i wanted to create something like this:
Text moving from left to right
I think this might be possible with CSS Animations. In theory, I have a div wrapper with position:relative, a fixed width and overflow:hidden. Inside, there is a div with position:absolute and left:0 and bottom:0. Now in some cases, the text is too long for the parent div, and i wanted to let text text "float" though the parent div: actually animating the div from left:0 to right:0.
I stumbled upon some CSS Animations and tried this
#keyframes floatText{
from {
left: 0;
}
to {
right: 0;
}
}
on the child div. And of course this didn't worked. Animations like from left :0 to left: -100px work, but this doesn't ensure that the whole text is visible, when it is longer than those additional 100px. Is there a nice and clean way to make this work? Surely JavaScript might rock this desired functionality. But I'd wanted to know if there is a way to do this in pure CSS.
Thanks in advance!
EDIT:
To clearify what I have in my mind, i've created a gif displaying what i want to accomplish with CSS animations:
Animated
As you see, we have three of that kind next to each other, some have a name which fits directly, some others might be too long and should be animated forth and back, so the user can read it :)!
Thanks again!
EDIT2:
Is there a way to accomplish something like this?
#keyframes floatText{
from {
left: 0px;
}
to {
left: (-this.width+parent.width)px;
}
}
This would be the ultimate solution, I know that this kind of coding is not possible in CSS, but maybe with some CSS3 tweaks like calc() or something? I'm out of ideas now :(
You can stop when your text hits the right border
This solution uses CSS translate.
The trick is that translate's percentages are corresponding to the current element and left referrs to the parent.
Make sure your text's display property is NOT inline.
Downsides of this CSS only approach:
Shorter texts also get animated. To counter that consider JavaScript or make your text min-width: 100%;. This can lead to minimal wiggling by the animation.
All texts get the same amount of animation duration, which can be awful for long texts. Again, consider JavaScript (you'll want to look at scrollWidth) or make many animation classes, which can be very hard to manage.
.animated {
overflow: hidden;
width: 11rem;
white-space: nowrap;
}
.animated > * {
display: inline-block;
position: relative;
animation: 3s linear 0s infinite alternate move;
}
.animated > *.min {
min-width: 100%;
}
#keyframes move {
0%,
25% {
transform: translateX(0%);
left: 0%;
}
75%,
100% {
transform: translateX(-100%);
left: 100%;
}
}
/* Non-solution styles */
.container {
display: flex;
flex-wrap: wrap;
}
.animated {
font-size: 2rem;
font-family: sans-serif;
border: 0.1rem solid black;
margin: 1rem;
}
.animated > * {
box-sizing: border-box;
padding: .5rem 1rem;
}
<div class="container">
<div class="animated">
<span>Short</span>
</div>
<div class="animated">
<span class="min">Short</span>
</div>
<div class="animated">
<span>Some more text</span>
</div>
<div class="animated">
<span>A really long text to scroll through</span>
</div>
</div>
change your keyframe value in %
Try This
body{
overflow: hidden;
}
p{
position: absolute;
white-space: nowrap;
animation: floatText 5s infinite alternate ease-in-out;
}
#-webkit-keyframes floatText{
from {
left: 00%;
}
to {
/* left: auto; */
left: 100%;
}
}
<p>hello text</p>
hi dude i have tried this
Note : but you will find one thing is missing and will see that animation will not reach to the purely left and right i mean you can't
see the whole text of the div.
and that is due to the value of the left and right i have set to the -100 and 100 so because i couldn't find the alternative for that so
right now trying to see that how can you make this happen.
and here is my try
div.main_div{
margin:0;
padding:0;
width: 20%;
height: 60%;
background-color:grey;
position:absolute;
overflow: hidden;
}
div.transparent_div{
width:100%;
height:50px;
bottom:0;
background:red;
position:absolute;
}
div.text_wrapper{
height:50px;
bottom:0;
z-index:10;
background:transparent;
white-space: nowrap;
font-family: Segoe UI,Frutiger,Frutiger Linotype,Dejavu Sans,Helvetica Neue,Arial,sans-serif;
color:white;
font-size:2em;
vertical-align: middle;
-webkit-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
-o-transition: all 0.3s ease-in-out;
-ms-transition: all 0.3s ease-in-out;
position:absolute;
-webkit-animation: anim 1.5s infinite;
animation: anim 1.5s infinite;
animation-direction: alternate-reverse;
-webkit-animation-timing-function: linear; /* Chrome, Safari, Opera */
animation-timing-function: linear;
}
#-webkit-keyframes anim {
from {
left: -100%;
}
to {
left:100%;
}
}
#keyframes anim {
from {
left: -100%;
}
to {
left:100%;
}
}
<body>
<div class="main_div">
<div class="text_wrapper">Hiii i am going right to left infinete times and here are the news
</div>
<div class="transparent_div"></div>
</div>
</body>
and here you can check out the demo of the above working code
DEMO CODE
Add ease-in-out to the animation for smoothness, and use % instead of px to move it left or right.
we can write jQuery code, for finding over-flow text and enable animation:
function AutoScrollText() {
var els = document.getElementsByClassName('container');
[].forEach.call(els, function myFunction(el) {
var isOverflowing = el.clientWidth < el.scrollWidth;
if (isOverflowing) {
$(el).children('span:first-child').addClass('animated');
}
var curOverf = el.style.overflow;
if (curOverf == "" || curOverf === "visible") {
$(el).css({ "overflow":"hidden"});
}
});
}
I have the following CSS:
.foo
{
height:100px;
overflow:hidden;
-webkit-transition: height 200ms;
-moz-transition: height 200ms;
-o-transition: height 200ms;
transition: height 200ms;
}
.foo.open
{
height:auto;
}
When .foo has an auto height, it will be a height of ~550px depending on the content.
I add the class open using jQuery, and I would expect to see the height change from 100px to ~550px in 200ms using CSS3 transitions.
However what exactly happens is that the height changes from 100px to 0px, then jumps to ~550px.
-- See Live Demo --
If I instead change .open to height:550px then this works fine, however the content length will vary and therefore I need to set the height to auto, and not a fixed pixel height.
Why is the div closing instead of sliding to ~550px, and how can I resolve this animation issue?
I don't think you can transition to height: auto; with css transitions. A workaround, which isn't perfect is to transition max-height instead and set it to something greater then it will ever get. Depending on what value you set it to will have a effect on the transition speed, but I've set it to max-height: 1000px; for the sake of simplicity.
Here's a demo to show you what I mean.
Code from demo:
.foo
{
max-height:100px;
overflow:hidden;
-webkit-transition: max-height 200ms;
-moz-transition: max-height 200ms;
-o-transition: max-height 200ms;
transition: max-height 200ms;
}
.foo.open
{
max-height:1000px;
}
It's not an elegant solution, but I hope it helps.
This isn't the most elegant solution, but it gets around the auto height issue.
On click of the button, calculate the height the div will be with auto height by doing:
var openHeight = $foo.addClass("heightauto").height();
Then remove this class straight afterwards, and apply a height to the div of openHeight:
$foo.removeClass("heightauto");
$foo.height(openHeight);
The heightauto class also needs to override the CSS3 transitions so that the height is changed instantly:
.foo.heightauto
{
height:auto;
-webkit-transition:0;
-moz-transition:0;
-o-transition:0;
transition:0;
}
See Live Demo: http://jsfiddle.net/AbPEx/4/
This is still hacky though, so if there is a more elegant solution then I'm open to suggestions
It is not possible to use transitions with height:auto.
The trick with max-height is a pretty good solution but has some inconvenience, especially a weird delay if max-height is much higher than the real height.
Here is the trick I use : http://jsfiddle.net/g56jwux4/2/
Basically it is two imbricated DIVs translating in opposite directions. Take a look a the code at jsfiddle because my english is not good enough to explain it clearly.
HTML part:
<body>
<p>Technicaly this dropdown menu looks like a simple height transition.</p>
<p>But this pure css code also works this a variable number of choices in menu, working around the "height:auto" not taken into account by css transitions.</p>
<input type="checkbox" id="menuOpen"></input>
<label id="bouton" for="menuOpen"><span>Click on me !</span>
<div id="menu">
<div id="masque">
<div class="choix" id="choix1">Choix 1</div>
<div class="choix" id="choix2">Choix 2</div>
<div class="choix" id="choix3">Choix 3 très très long pour voir la taille finale du menu</div>
<div class="choix" id="choix4">Choix 4</div>
<div class="choix" id="choix5">Choix 5</div>
<div class="choix" id="choix6">Choix 6</div>
</div>
</div>
</label>
</body>
CSS Part :
body {
font-family: sans-serif;
}
#menuOpen {
display: none;
}
#bouton {
position: absolute;
left: 100px;
top: 100px;
width: 200px;
height: 30px;
background-color: lightgray;
cursor: pointer;
}
#bouton > span {
color: black;
padding: 6px;
line-height: 30px;
}
#menu {
position: absolute;
top: 100%;
overflow: hidden;
min-width: 100%;
transition: transform 0.3s linear 0s, visibility 0.3s linear 0s;
transform: translateY(-100%);
visibility: hidden;
color: white;
}
#menuOpen:checked + #bouton > #menu {
transform: translateY(0%);
visibility: visible;
transition: transform 0.3s linear 0s, visibility 0s linear 0s;
}
#menuOpen:checked + #bouton > #menu > #masque {
transform: translateY(0%);
}
#masque {
position: relative;
background-color: gray;
transform: translateY(100%);
transition: transform 0.3s linear 0s;
}
.choix {
white-space: nowrap;
padding: 3px 6px;
}
.choix:hover {
background-color: darkgray;
}
There is a small bug in there, I already fix it. by adding min-height: 100px;
.foo {
min-height: 100px;
height: 100px;
...
}
There you won't see it go back to 0px.