Trouble understanding CSS animations - css

I am trying to wrap my head around the CSS animation property. In my current code, I have basically this structure:
<div>
<div>
<ul>
<li></li>
<li></li>
<li></li>
</ul>
</div>
</div>
The li's inside are generated via JS, and what I'd like to do is animate the expansion so it's not as abrupt. I attached
animation: 1s linear;
to the outermost div, but it doesn't animate. What I'm trying to do is as the li's are added/removed, the height of the wrapper should animate instead of simply change. I've been looking through various docs and sites, but I can't figure out if I don't understand the property or if I'm using it wrong.

First of all, it's good to know the difference between transition and animation in CSS, and when to use each.
transition is used when you want to animate changes to either specific properties (transition: opacity .5s, color .5s), or all properties (transition: all .5s) as they are altered. This way, if you change a property like opacity via - for example - a CSS hover state, or JavaScript, that change will animate.
animation is used to set a keyframe animation to an element, where you predefine a sequence of steps that can affect one or more properties of that element.
The type of animation you're requesting - simply animating an element in/out as it is added or removed from the DOM - does not exist in CSS alone. However, many JavaScript libraries can intelligently add/remove CSS classes while an element is added/removed, allowing CSS animations to carry out.
With that said, there is a way we could decently animate in <li> elements with CSS alone, by having them start with a keyframe animation.
Here's a live demo where I'm doing just that by animating each new <li>'s height from 0 to 2em (which I've specified as the line-height). Note that width and height can only transition to a specified value - not auto.
$('button').on('click', function() {
$('ul').append('<li>List Item</li>');
});
div {
border: 1px solid teal;
border-radius: 4px;
padding: 1em;
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
li {
animation: grow 1s;
line-height: 2em;
overflow-y: hidden;
}
#keyframes grow {
0% {
height: 0;
}
100% {
height: 2em;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<ul>
<li>List Item</li>
</ul>
<button>Add to List</button>
</div>

Related

Css alternative to slide down using transform: scale

SlideDown type of animations are very useful to show the user what is changing in the layout. I used to do this with JQuery, but I rather have a CSS only solution.
If the element is positioned absolute, everything is perfect with using transform: scale. But it is possible to do the same when the element is taking space and should move things around?
I don't mind that it grabs it's space in one big step - as long as the animation shows some kind of direction for the eye to follow.
There is the work around with max-height - like here: https://stackoverflow.com/a/8331169/647845
, but what I don't like is that I have to estimate the height, otherwise the animation looks clunky or you're missing content.
I'm perfectly fine for using transform: scale and having a jump in the other elements. In combination with display: block it does not work though. I'm looking for animating both up and down.
Is there a (simple) alternative?
In conclusion I'm looking for an alternative to animating the delay of display: none/block.
.lolcat
{
transition: transform 200ms ease-in-out;
transform: scale(1,0);
transform-origin: 0 0;
display: none;
}
.lolcat.expanded
{
transform: scale(1,1);
display: block; /* I wish you'd be delayable */
}
You can use margin-top property and animate menu.
See the Snippet below:
#lolcat-container{
overflow:hidden;
}
.lolcat
{
border:1px solid black;
background:red;
color:white;
margin-top:-100%;
animation-direction: reverse;
animation:1s 1 alternate forwards close;
}
#menu:hover .lolcat
{
animation:1s 1 alternate forwards open;
}
#keyframes open {
0% {
margin-top:-100%;
}
100% {
margin-top:0%;
}
}
#keyframes close {
0% {
margin-top:0%;
}
100% {
margin-top:-100%;
}
}
<div id="menu">
<a>hover me</a>
<div id="lolcat-container">
<ul class="lolcat">
<!-- Create a bunch, or not a bunch, of li's to see the timing. -->
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
</ul>
</div>
<div>
Content
</div>
</div>
You can also test it here

CSS width transition and hover

I'm trying to implement a slide show like menu with CSS. It's working fine except for transition. If transition is used the elements are not in sync anymore. Whole menu losing width if multiple elements are hovered in short time. Everything works fine if transition is removed.
Is there anything I have to be aware of when using CSS transitions and hover together? I thought a transition-timing-function: linear; would be enough to get width in sync. It seems like the transition is started early on the fading out element than fading in element.
Some technical notes about implementation:
It's a ul list. Menu items are represented as li. Selected menu item has a selected. This one is shown if there isn't any user interaction. The other ones are collapsed. If an element is hovered it's opened and all other ones are collapsed. There should be a transition effect when changing from collapsed to shown.
ul {
list-style: none;
display: inline-block;
padding: 0;
/*
* remove gaps between inline elements
* https://css-tricks.com/fighting-the-space-between-inline-block-elements/
*/
font-size: 0;
}
ul li {
display: inline-block;
overflow: hidden;
/*
* Transition
*/
transition: width 0.5s;
transition-timing-function: linear;
width: 50px;
}
ul li:hover,
ul li.selected,
ul:hover li.selected:hover {
width: 564px;
}
ul:hover li.selected {
width: 50px;
}
<ul>
<li>
<a href="http://www.3ker-ras-group.com/profil.html">
<img src="http://www.3ker-ras-group.com/images/m_profil.jpg" alt="Unser Profil">
</a>
</li>
<li class="selected">
<a href="http://www.3ker-ras-group.com/referenzen.html">
<img src="http://www.3ker-ras-group.com/images/m_referenzen_der_3ker_ras_group.jpg" alt="Referenzen der 3KER RAS GROUP">
</a>
</li>
<li>
<a href="http://www.3ker-ras-group.com/jobs.html">
<img src="http://www.3ker-ras-group.com/images/m_hoehenarbeiter_jobs.jpg" alt="Jobs für Höhenarbeiter">
</a>
</li>
<li>
<a href="http://www.3ker-ras-group.com/shop-kletterbedarf.html">
<img src="http://www.3ker-ras-group.com/images/m_kletterbedarf_shop.jpg" alt="Unser Shop für Kletterbedarf">
</a>
</li>
<li>
<a href="http://www.3ker-ras-group.com/kontakt.html">
<img src="http://www.3ker-ras-group.com/images/m_kontakt_zum_unternehmen.jpg" alt="Kontakt aufnehmen">
</a>
</li>
</ul>
Trigger the issue by moving cursor fast from left to right. It occurs at least in Firefox and Chrome. Didn't tested safari, IE and edge.
Here is a JSFiddle: https://jsfiddle.net/vj12qswz/3/
All elements should fit in one line. Adjust preview window width if necessary.
Works fine if you use javascript to add a specific class on hover.
Probably best to add "onclick" event as well because hover not gonna work on touch devices.

Why does my list's background-color disappear when I float its list elements?

The moment I float my unordered-list element...the background color fails. Why?
<style type="text/css">
.bkgrd-blue { background-color: #094AB2; }
.application-bar { color: #FFFFFF; }
.application-bar ul { }
.application-bar ul.control-bar { list-style: none outside none; margin: 0; overflow: visible; padding: 0; }
.application-bar ul.control-bar.branding { float: left;}
</style>
<div class="application-bar bkgrd-blue">
<ul class="control-bar">
<li>
This is working!
</li>
</ul>
</div>
<div class="application-bar bkgrd-blue">
<ul class="control-bar branding">
<li>
The moment I float this...it fails! Why?
</li>
</ul>
</div>
Floating an element removes it from the normal document flow so containers don't expand - that is, the containing div has 0 height.
To fix this you need to clear the float. You can either:
set overflow: hidden on the div
float the div
add an element after the floated list with clear:both - this could be done using the :after pseudo-element
Here's a demo using the first solution: http://jsfiddle.net/FSH4Y/
I added:
.application-bar {
color: #FFFFFF;
overflow: hidden;
}
Here's some more info on this issue: CSS Tricks: All About Floats - have a look at the section called The Great Collapse
You need to clear under the list, usually I add a div like
<div style='clear:both;'></div>
This will allow the floated element's parent to properly calculate it's height.
You need to float the containing div with the background in it as well. As soon as you float the inner ul, the containing div effectively has no content so ends up with a height of 0.

Parent div float interferes the child div's width

What I am trying to do is to have a very simple tooltip that hides/shows on hover using jQuery.
(jsFiddle demo of the problem)
To do this, what I did was to put a div on li's that will have a tooltip. This div is absolutely positioned on top of each li. The tooltip div will contain varying lengths of text so I cannot just pre-define its width. I just want the width to extend all the way depending on the text length.
My problem is that when I float the li, the div also gets floated (or so it seems) hence taking the width of the floated li. The tooltip now becomes as narrow as the width of the li, which I don't like to happen.
This is the HTML:
<ul id="images">
<li><img src="[some image]" /><div class="tooltip">Some text that is quite long.</div></li>
<li><div class="tooltip">Some text that is quite small.</div><img src="[some image]" /></li>
<li><img src="[some image]" /></li>
<li><img src="[some image]" /></li>
</ul>
This is the CSS:
#images li {
list-style: none;
margin-left: 10px;
position: relative;
}
.tooltip {
color: #FFF;
clear: both;
background: #000;
padding: 10px;
font: 11px Arial, Helvetica, sans-serif;
-moz-border-radius: 5px;
position: absolute;
top: -50px;
display: none;
border: 2px solid #999;
}
I hope someone would help me with this problem.
You can always calculate the exact width before.
For example, you create a tooltip div outside of your page like
<div class="tooltip" id="calc"></div>
and
#calc{
top:-100px;
left:-100px;
}
If you add the following js, it will show nicely
$(".tooltip","#images").each(function(){
$("#calc").text($(this).text());
$(this).width($("#calc").width());
});
updated fiddle here
Block elements expand to the width of their containers. Float doesn't change this.
If you want a different width on the tool-top use width and specify the width in pixels.
If you want to go a fancier route, you can define a width and height, check for overflow and make it wider using JavaScript.
I think you need to change your approach a bit! Instead of using the same div as the actual tooltip, you can use its HTML content inside a div that has an absolute position and you set its position based on the position of the object being hovered.
$('#images li').hover(function() {
$('#myTooltip').html($(this).find('.tooltip').html());
/* Here you need to set #myTooltip absolute position.
based on the position of $('this') or the mouse position
with an offset */
}, function() {
$('#myTooltip').hide();
});
where #myTooltip is a div defined outside your list that has an absolute position.

Trying to center a dynamic width jquery menu

I have a menu built with jquery from apycom.com that I am trying to center.
The menu items are from a cms and dynamically created when the page loads. So this means that the menu isn't a fixed width.
I have tried several methods using just css, but without having a width set for the menu, they don't want to work.
I have found some information that leads me to believe that there may be a way to do it with javascript.
Is there is a way to dynamically set the width of the div element around the menu and then set the left and right margins to auto to center the menu?
If there is a better way to accomplish this, I am open to ideas.
Thanks in advance
Bjorn
Here is a sample of what I have thus far.
I have already tried using 'margin: 0 auto;' but without a width setting that doesn't work. Because the menu is created by looping over the menu items available from the cms, I don't know the width of the menu.
I've tried using 'display: inline-block;' as well, and that get's me to a point that the block space the menu takes up is only the width of the menu. Now I just need to be able to center that block. I thought that there might be a way that once the menu has been created and the width is then known that you could then apply the margin settings.
Maybe similar to the way jquery is able to apply and change style settings on the fly.
<div class="top_navigation_bar">
<div id="menu">
<ul class="menu">
<li><a class="parent" href="/en/"><span>Home</span></a></li>
<li><a class="parent" href="/en/web-design"><span>Web Design</span></a>
<div>
<ul>
<li><span>Design Packages</span></li>
<li><span>Website Maintenance</span></li>
<li><span>Redesign Website</span></li>
<li><span>Design Fundamentals</span></li>
<li><span>Design Key Elements</span></li>
</ul>
</div>
</li>
<li><a class="parent" href="/en/website-business-solutions"><span>Business Solutions</span></a></li>
<li><a class="parent" href="/en/internet-marketing"><span>Internet Marketing</span></a>
<div>
<ul>
<li><span>Small Business Marketing</span></li>
<li><span>Leveraging the Internet</span></li>
</ul>
</div>
</li>
<li><a class="parent" href="/en/doing-business"><span>About Us</span></a>
<div>
<ul>
<li><span>Design Team</span></li>
</ul>
</div>
</li>
<li><a class="parent" href="/en/blog"><span>Blog</span></a></li>
<li><a class="parent" href="/en/contact-us"><span>Contact</span></a></li>
<li class="last"><span>FAQ</span></li>
</ul>
</div>
.top_navigation_bar {
height: 46px;
padding-top: 4px;
background-color: #3a8658;
}
div#menu {
height: 46px;
padding-left: 24px;
background: url(/site_media/template_images/images/left.png) no-repeat;
_background: url(/site_media/template_images/images/left.gif) no-repeat;
width:auto;
}
div#menu ul {
margin: 0;
padding: 0;
list-style: none;
float: left;
}
Without a sample makes harder to see what exactly is happening. It would be nice if you post a sample for HTML and CSS you are using. But going blind...
For horizontal centering an element with CSS, you can do:
element {margin: 0px auto;}
This is enough to correctly center an element.
Note that block elements (like div, ul, li and p) tends to fill 100% horizontally. Floating elements or absolute positioning them makes they loose this fullfillment characterist. If this is the case, the elements will wrap to minimum comfortable size that allows the content to be displayed, unless you set width and/or overflow properties.
If you set width, and content is larger than the declared width, it will or overflow, or wrap. You have CSS properties to handle those cases too.
I recommend doind this with CSS, because makes layout more accessible. But if you prefer, you can code width with javascript or jquery, making your life a bit easier.
To process that with javascript, you'll need something like:
myMenuElement.style.width = "200px";
with Jquery (width method):
$('#myMenuElement').width(200);
Cheers.
EDIT
Not sure what is exactly the desired effect, but I made a few changes in your css. Check.
.top_navigation_bar {
height: 46px;
padding-top: 4px;
background-color: #3a8658;
}
div#menu {
height: 46px;
padding-left: 24px;
}
div#menu ul {
margin: 0;
padding: 0;
list-style: none;
}
ul.menu>li {
display: inline;
position: relative;
}
ul.menu>li>div {
display: block;
position: absolute;
left: 0%;
}
ul.menu span {
white-space: nowrap;
}
Follow a good reference from both, vertical and horizontal menus (I've learned from those).
If you are trying to center the #menu inside the .top_navigation_bar then you could use the margin:0 auto and additionally use jQuery like this
$(function(){
$menu = $('#menu');
$menu.width(
$('.menu').outerWidth() +
$menu.outerWidth() - $menu.width()
);
// added the following line, because the lavalamp plugin
// corrects itself when the window resizes..
// so we trigger a resize event, and the plugin fixes everything ;)
$(window).trigger('resize');
});
this will resize the #menu according to its contents, and will become centered because of the auto margin we set in css.
example at http://www.jsfiddle.net/MCnbr/

Resources