Possible to animate dynamic height using CSS? JS alternatives accepted - javascript

I'm using AngularJS which allows me to use ng-show and ng-hide to show and hide elements based on a logical condition. What I'm trying to accomplish is to animate the size changes of the container when the children objects are shown-hidden so it's less jumpy.
For those not familiar with AngularJS, ng-show and ng-hide basically just applied the display: none and display: block properties. So when a container is set to show the display is set to block.
With that out of the way, I've been reading on animating height changes through a few pages of google searches and all I can find are examples using max-height to animate it from one height to another, which are statically defined by CSS rules, for example:
#animated-div {
max-height: 100px;
transition: max-height 1s ease;
}
#animated-div.hidden {
max-height: 0px;
}
and they would remove the .hidden class to cause the transition to animate the change in height.
The issue is that I'm not opening/closing a container and there's no pre-determined height that the container will be, as the container can be modified dynamically based on a variety of variables. On-top of that the application is responsive, so the height will vary across devices.
Here is an example scenario:
- Container
- Div A (Height: 200px); Shown
- Div B (Height: 100px); Shown
- Div C (Height: 300px); Hidden
- Div Slider (Height: Dynamic) Hidden.
Currently the height of the container (which is auto) is 300px based on the children, now the user toggles Div C active, which increases the height to 600px The div should animate the expansion from 300px -> 600px now the user clicked the clear button, the children of the container are all hidden, the container should animate from 600px -> 0px.
The user then starts messing with a slider, which value ranges from 0 to 100. This height is applied to the Div Slider. Say the user slides to 57. This should cause an animation from 0px -> 57px as none of the divs are shown.
Sorry for the in-depth example of what I want, but it's the only way I can think to explain it. For reference, children in the container are scaled dynamically, using % values and vw/vh values. The size of the container when a certain combination of children are active is never the same across different resolutions, so this must be able to animate dynamic changes in height.
Javascript examples are welcome, however for this project I do not wish to involve any additional libraries, Javascript examples must work on modern mobile browsers.

Your question got me thining for a while and in the end I came up with an interesting solution.
Instead of trying to animate the parent element - animate the new children instead.
I've created a codepen here that does exactly that.
I'm using a CSS animation for both 'show' and 'hide' effects.
Here's a little LESS code for the main animations:
.parent{
width:33%;
overflow:hidden;
.child{
padding:.5rem;
border:1px solid #78909C;
border-bottom:0;
color:#fff;
animation:slideDown .2s ease-in forwards; //set basic "show" animation
transform-origin:top center; // set proper transform origin
&.removed{
animation:slideUp .2s ease-in forwards; // add different animation for "hide"
}
&:nth-child(even){background:#78909C;}
&:nth-child(odd){background:#546E7A;}
&:last-child{border-bottom:1px solid #78909C;}
}
}
I'm not sure if this solves your issue perfectly, but it's definitely something that will help you out here.

Related

CSS Marquee Slider Compensate Outer Width Minus Inner Width

So I have a marquee slider that takes a bunch of images, scrolls them to the left, and when the first image hits the left of the page, it comes back from the right side again infinitely.
My issue is that there is a gap between the last image, and the first image that comes again. I believe the theory to fix this is by using jQuery to calculate the sum of all of the images in the first <span>, subtract that from what the width of the container is, and then adding a negative margin-left with that differential number. I have tried the following code, but the issue is that I am not familiar enough with jQuery to pull the widths. Also, I need a solution that will calculate the new container width on window resize (since the container is set to 100% and will certainly change).
NOTE: The two spans contain THE SAME EXACT IMAGES. The reason for this is for the second span to scroll into view as soon as the first one hits the far left. This loops infinitely.
<script>
var marqueeWidth = $('.marquee div span').innerWidth();
var marqueeWidth2 = 0;
$('.marquee div span img').each(function(){
marqueeWidth2 += $(this).innerWidth();
});
console.log(marqueeWidth / 2);
console.log(marqueeWidth2);
</script>
Full Code on JSFiddle: http://jsfiddle.net/Hybridx24/5nuxfed5/2/
Would this work for you? http://jsfiddle.net/5nuxfed5/11/
I've made some changes to the html, the 2 span are now div.flex_container, which are inline-flex elements with 100% width.
.flex_container {
display: inline-flex;
width: 100%;
}
Also I prevented the images to wrap to the next line with white-space: nowrap
.marquee {
white-space: nowrap;
position: relative;
font-size: 0; /* Inline-block spacing issue hack */
animation: marquee 5s infinite linear;
}
Inside each flex box the images are rescaled within its own container, fitting the entire screen width while keeping its ratio:
.marquee img {
display: block;
width: 100%;
height: auto;
}
Edit: added an outer wrapper to remove scroll bar, and added a flex-grow to grow the img if there's free space.
I have made a slider using jquery, which is little bit different from your query. But I hope it may fulfill your reqirement.
URL: http://demos4clients.com/mygallery/
You need to include jquery library file and image into the slider. Also you can change time duration in jquery code.

How to change height of parent div when using css trasition?

I have a problem with a CSS transition. I need to change the height of the parent div relative to the child divs in the transition.
I am using CSS which has a number of steps which slide from right to left as the user clicks continue (Magento onepage checkout with progress bar).
The problem is that the parent container .opc has a height of 970px but the heights of the additional steps vary so I need to find a way to make the parent DIV .opc change height to accommodate the sizes of the remaining steps.
.opc { position:relative; overflow:hidden; height:970px; padding-top:20px; text-align:center; }
I've tried adding height: auto; or height: 100%; but the remaining pages still don't fill the page and I am not sure how to solve it!
Is there a way to affect the height using jQuery or Javascript, maybe pure CSS?
I'm thinking jQuery to detect which step the user is on the adjust the height of the container to fit the content?
<script>
jQuery(document).ready(function(){
if('#opc-billing'){
jQuery('.opc').height(1200);
}
if('#opc-shipping'){
jQuery('.opc').height(500);
}
})
</script>
Although the above solution doesn't work :(
Any help would be appreciated guys!
Here is a quick demo that might help:
I am simply adding a CSS transition property to the parent as well, and adjusting the height at the same time as the position of the child.
http://jsfiddle.net/qF3u7/
.parent {
background-color: lightyellow;
-webkit-transition: height 2s;
height: 50px;
}
.transit {
position: relative;
top: 0;
width: 50px;
height: 50px;
border: 1px solid red;
-webkit-transition: top 2s;
}
PS: Run this in chrome as I didn't bother with the other browser prefixes for the CSS.
Although it is not a very dynamic function what you have is getting there. Try this:
$(document).ready(function{
var x = $("#opc-billing").height();
var y = $("#opc-shipping").height();
var opc = $(".opc");
if (x === 600){ // - The number values are just examples of course.
opc.height(1200);
}
if (y === 200){
opc.height(400);
} else {opc.height(300);} // - default height, could be left blank if set by CSS(example - else{})
})
DEMO
Keep in mind that when using the height() method results may be unexpected because height() returns the computed value of an element which does not include padding, border or margin and does not take into account something like when a page is zoomed in. Learn more about height() here. To get total height including padding, border and margins use outerHeight().
UPDATE: I added some extra bells and whistles to the JSFiddle. Check it out!

CSS3 translate out of screen

For a number of projects now I have had elements on the page which I want to translate out of the screen area (have them fly out of the document). In proper code this should be possible just by adding a class to the relevant element after which the css would handle the rest. The problem lies in the fact that if for example
.block.hide{
-webkit-transform:translateY(-10000px);
}
is used the element will first of all fly out of the screen unnecessarily far and with an unnecessarily high speed. And purely from an aesthetic point of view there's a lot left to be desired (Theoretically speaking for example a screen with a height of 10000px could be introduced one day in the future).
(Update) The problem why percentages can't be used is that 100% is relative to the element itself, rather than to the parent element/screen size. And containing the element in a full-sized parent would be possible, but would create a mess with click events. And after a few answers, allow me to point out that I am talking about translations, not about position:absolute css3 transitions (which are all fine, but once you get enough of them they stop being fun).
What aesthetically pleasing solutions to allow an element to translate out of a screen in a fixed amount of time can you guys think of?
Example code can be found in this jsfiddle demonstrating the basic concept.
http://jsfiddle.net/ATcpw/
(see my own answer below for a bit more information)
If you wrap the .block div with a container:
<div class="container">
<div class="block"></div>
</div>
<button>Click</button>
you could expand and then, translate the container itself after the click event
document.querySelector("button").addEventListener("click", function () {
document.querySelector(".container").classList.add("hide");
});
with this style
.block {
position:absolute;
bottom:10px;
right:10px;
left:10px;
height:100px;
background:gray;
}
.container {
-webkit-transition: -webkit-transform ease-in-out 1s;
-webkit-transform-origin: top;
-webkit-transition-delay: 0.1s; /* Needed to calculate the vertical area to shift with translateY */
}
.container.hide {
position:absolute;
top:0;
left:0;
bottom:0;
right:0;
/* background:#f00; /* Uncomment to see the affected area */
-webkit-transform: translateY(-110%);
}
In this way, it is possible to apply a correct translationY percentage ( a little more than 100%, just to have it out of the way ) and mantaining the button clickable.
You could see a working example here : http://jsfiddle.net/MG7bK/
P.S: I noticed that the transition delay is needed only for the transitionY property, otherwise the animation would fail, probably because it tries to start before having an actual value for the height. It could be omitted if you use the horizontal disappearing, with translateX.
What I did is use the vh (view height) unit. It's always relative to the screen size, not the element itself:
/* moves the element one screen height down */
translateY(calc(100vh))
So if you know the position of the element in the screen (say top:320px), you can move it exactly off the screen:
/* moves the element down exactly off the bottom of the screen */
translateY(calc(100vh - 320px))
I know this is not exactly what you were asking but...
Would you consider using CSS animations with Greensock's Animation Platform? It is terribly fast (it claims it's 20 times faster than jQuery), you can see the speed test here: http://www.greensock.com/js/speed.html
It would make your code nicer I believe, and instead of trying to hack CSS animations you could focus on more important stuff.
I have created a JSFiddle here: http://jsfiddle.net/ATcpw/4/
Both CSS and possible JS look simpler:
document.querySelector("button").addEventListener("click",function(){
var toAnimate = document.querySelector(".block");
TweenMax.to(toAnimate, 2, {y: -window.innerHeight});
});
CSS:
.block{
position:absolute;
bottom:10px;
right:10px;
left:10px;
height:100px;
background-image: url(http://lorempixel.com/800/100);
}
I recently built an app which used precisely this technique for sliding 'panels' (or pages) and tabs of the application in and out of view. A basic implementation of the tabs mechanism can be seen here.
Basically (pesudo-code to illustrate the concept, minus prefixes etc):
.page {
transform: translateY(100%);
}
.page.active {
transform: translateY(0%);
}
The problem I had was that Android Webkit in particular wouldn't calculate percentage values correctly. In the end I had to use script to grab the viewport width and specify the value in pixels, then write the rules using a library for dynamic stylesheet parsing.
But eventually, and in spite of only these minor platform-specific problems, this worked perfectly for me.
Use calc method (http://jsfiddle.net/ATcpw/2/):
.block{
position:absolute;
top: -webkit-calc(100% - 110px);
right:10px;
left:10px;
height:100px;
background:gray;
-webkit-transition: all 2s;
/*this adds GPU acceleration*/
transform: translate3d(0,0,0);
-webkit-transform: translate3d(0,0,0);
}
.block.hide{
top: -100px;
}
Since you are using -webkit prefix I used it as well.
calc is supported by majority of browsers: http://caniuse.com/#search=calc
One very simple, but not aesthetically pleasing solution is to define the class dynamically:
var stylesheet = document.styleSheets[0];
var ruleBlockHide;
and
//onresize
if(ruleBlockHide) stylesheet.deleteRule(ruleBlockHide);
ruleBlockHide = stylesheet.insertRule('.block.hide{ -webkit-transform:translateY(-'+window.innerHeight+'px); }',stylesheet.cssRules.length);
see: http://jsfiddle.net/PDU7T/
The reason a reference to the rule needs to be kept is that after each screen resize the rule has to be deleted and re-added.
Although this solution gets the job done, there has to be some DOM/CSS combination which would allow this to be done without javascript (something along the lines of a 100%x100% element containing such a block, but I haven't been able to figure out any transform based way).
get the document width. then use a java script trigger to trigger the css3 translation.
function translate(){
var width = document.body.Width;
document.getElementById('whateverdiv').style='translateX(' + width + 'px)';
}
This is simple
add the following to your div
.myDiv {
-webkit-transition-property: left;
-webkit-transition-duration: 0.5s;
-webkit-transition-timing-function: ease-in-out;
-webkit-transition-delay: initial
}
then change the "left" property of it either by adding an additional class or by jQuery
This will animate it along the x-axis
Note: you can change the -webkit-transition-property to any property you want and this will animate it

Slide + fade effect using CSS transitions

I'm trying to replicate this effect using CSS effects or transitions.
Using animations I can animate the opacity, but only fadeIn, and the height (which should control the slide) doesn't seem to work at all :(
The closest I've got is by using javascript to set a temporary class on the element I want to animate, and on which I apply the initial opacity. But height doesn't work either. And there seems to be a slight delay on animation start.
Any other ideas?
So I ended up using the solution posted in the question Simon mentioned: With javascript I wrap the element I want to animate within a "wrapper" DIV on which I apply the animation. The wrapper will get its height changed from 0 to the height of the content DIV every time the label is clicked:
fiddle here
I know it requires some javascript, but the idea is to make the animation in CSS, and this is what it does. And if JS is disabled, the toggle will still work...
You can't currently animate on height when one of the heights involved is auto, you have to set two explicit heights. There's an extensive workaround posted as an answer to this similar question.
I made an alteration to your JS Fiddle, I beleive this is what you want; please see it here.
You need to specify a height on the div originally (0) and don't forget overflow:hidden; so that the content doesn't 'spil out' of the div. You will still need jQuery / Javascript however, to toggle a class but it means much less Javascript is required. (I toggled the class "change" which you will see on that fiddle)
input {
display:none;
}
label {
display:inline-block;
}
div {
white-space: pre;
background: #eee;
color: #333;
overflow:hidden;
height:0;
opacity:0;
-moz-transition:height 1s opacity 1s;
-webkit-transition:height 1s opacity 1s;
-o-transition:height 1s opacity 1s;
-ms-transition:height 1s opacity 1s;
transition:height 1s, opacity 1s;
}
.changed {
height:200px;
opacity: 1;
}
I added a few vendor prefixes to the transition CSS propery as I'm not sure what browser you'll be using and I'm on firefox so I need the -moz- prefix lol :)
The only problem I can see with this is that height:auto or height:100% doesn't animate, so you'll need to specify ems or px... If this is going to be a problem (like if the content will be dynamic), I would advise using jQuery for the height animation.

css margin issue with jquery slider

I've having an issue with the background images i have embedded into my carousel. click here I've noticed when i click from one slide to another the background image on my site moves out of place. The margin-top for my carousel is current set to margin-top:-275px; and the background image is set to margin-top:-64px; I am slight concerned about these settings.
Does anyone have a solution to this problem?
In order to activate the slides click the thin red tab under the nav bar
I guess that's because you have
.rslides li {
top:0;
}
It does nothing with position:relative (and the current slide has it), but it moves down the slide with position:absolute (hidden slides).
When you click a tab, there's a moment in which the new one is fading in, but it doesn't have position:relative yet. Then, in that moment, the new slide isn't where you want.
So remove that line.
The jumping is occurring because you are switching the LI items from position: absolute; to position: relative; at the end of the animation toggle. This can be avoided by removing your CSS rule:
.rslides li { left: 0; top: 0; }
Specifying width and height is fine, but as soon as you specify left and top - then switch from relative to absolute positioning, you get that jump you're seeing.
As for the positioning of each panel - it has to do with the way you are laying out your boxes. The sizes you are specifying are not large enough for the content you are providing. For instance: <div id="header"> is 37px tall, which is the appropriate size for the social media buttons, but you also have it as the container for the #nav-menu UL - which is another 102px tall.
It appears that in order to correct this and make things overlap, you are using negative margins - which is getting you all thrown off.
My suggestion would be to use a standardized layout system, such as any of the following:
http://cssgrid.net/
http://960.gs/
http://www.1kbgrid.com/
http://foundation.zurb.com/docs/grid.php
And use it to perform your layout tasks, rather than trying to self-craft overlapping layers with mixed absolute/relative positioning.
Alternatively, if you're going to go the overlapping layers route (again, not suggested), really commit to it. Position things absolutely throughout the layout.
In order to accomplish this, you might consider CSS rules like:
#header {
display: block;
position: absolute;
left: 50%; top: 0px;
height: 139px; /* Your Social media links height + nav buttons height */
width: 1018px; /* Your current width */
margin-left: -509px; /* Half the width - centers on page */
}
Again - this is MUCH more work, MUCH harder to maintain and MUCH less elegant - but will yield you at least a consistent spacing / sizing.

Categories