CSS Dropdown menu with animation (no js) - css

Trying to create an animated dropdown menu using CSS animation, without any JS. Thought I've been barking up the right tree but can't see where I'm going wrong, for this simplified menu item...
<div class="menu">Menu Item
<ul>
<li>Dropdown 1</li>
<li>Dropdown 2</li>
<li>Dropdown 3</li>
<li>Dropdown 4</li>
<li>Dropdown 5</li>
</ul>
</div>
And the following CSS;
.menu ul {
height: 0px;
overflow: hidden;
-webkit-transition: all 0.5s ease-in-out;
-moz-transition: all 0.5s ease-in-out;
-o-transition: all 0.5s ease-in-out;
transition: all 0.5s ease-in-out;
}
.menu:hover ul {
height: auto;
}
Thought that should successfully result in a scroll down of the div, but it just keeps appearing. Any thoughts? Cheers

See this topic for reference: How can I transition height: 0; to height: auto; using CSS?
To put it simply, you can not animate to height: auto;. It is not supported. If you have a pre-determined, fixed height, you can do it by animating to that specific value. 0px to 100px for instance. Auto however is not supported.
The first answer in the link above links to another article in which a sort of work-around is given. You may explore that for implementation on your site.
Can you use CSS3 to transition from height:0 to the variable height of content?

You can't use CSS transitions with height:auto, only with specific values.
.menu:hover ul {
height: 100px;
}
http://jsfiddle.net/mblase75/cWZMu/

The animation for a dropdown can be implemented with pure CSS:
ul {
overflow: hidden;
transition: all .3s ease;
}
ul.folded {
max-height: 0;
}
ul.unfolded {
max-height: 300px; //value of max-height should always bigger than actual sum of all li's height
}

I was able to build a solution similar to #artcher, but instead I used max-height: 100%; and that worked perfectly:
ul.submenu {
overflow: hidden;
transition: all .3s ease;
max-height: 0;
}
.top-level-item:hover {
.submenu {
max-height: 100%;
}
}

Related

Transitioning opacity from 0 to .9 works with toggling visibility from hidden to visible, but not the other way around

I have a sub-menu that appears when I hover over an item in the main menu:
I have a transition effect whereby the sub-menu transitions from 0 opacity to .9 opacity in .5 seconds. However, I also have to toggle the visibility from hidden to visible in order for this to work.
Here's the html:
<li style="position: relative;" onmouseover="showLegalMenu()" onmouseout="hideLegalMenu()">
<a>Legal</a>
<div id="legal-menu" class="legal">
<ul>
#if (termsOfUse != null)
{
<li>#termsOfUse.Name</li>
}
#if (privacyAndSecurity != null)
{
<li>#privacyAndSecurity.Name</li>
}
#if (refundPolicy != null)
{
<li>#refundPolicy.Name</li>
}
</ul>
</div>
</li>
Here's the Javascript:
function showLegalMenu() {
$("#legal-menu").addClass("legal-show");
}
function hideLegalMenu() {
$("#legal-menu").removeClass("legal-show");
}
Here's the CSS:
.legal {
visibility: hidden;
background-color: #383838;
opacity: 0;
padding: 5px 0;
z-index: 10;
position: absolute;
top: 15px;
left: 10px;
width: 150px;
transition: opacity .5s linear;
}
.legal-show {
visibility: visible;
opacity: .9;
}
Transitioning in works fine. The legal-show class is added, it is set to visible, and it transitions from 0 opacity to .9 opacity.
It's transitioning out that's the problem. The legal-show class is removed, causing the sub-menu to become invisible immediately (no transition). The sub-menu items still transition from .9 opacity to 0 opacity somehow (even though the div they are contained in is supposedly invisible at this time), but I would like for the sub-menu div to also transition to 0 opacity like this as well.
If I could just set the visibility to hidden at the end of the transition rather than right away, I believe this would work. How does one does this? Thanks.
No need to complicate it using JavaScript. This can be easily achieved by CSS only.
.legal {
visibility: hidden;
background-color: #383838;
opacity: 0;
padding: 5px 0;
z-index: 10;
position: absolute;
top: 15px;
left: 10px;
width: 150px;
transition: all 0.5s ease-in-out;
}
.parent-li:hover .legal {
visibility: visible;
opacity: .9;
}
<li class="parent-li">
<a>Legal</a>
<div id="legal-menu" class="legal">
<ul>
<li>#termsOfUse.Name</li>
<li>#privacyAndSecurity.Name</li>
<li>#refundPolicy.Name</li>
</ul>
</div>
</li>
.to-toggle {
max-height: 0;
overflow: hidden;
opacity: 0.9;
background: red;
transition: max-height .5s ease-out;
}
.to-toggle.active {
height: auto;
max-height: 500px;
transition: max-height .5s ease-in;
}
<div class="legal">
<label id="hoverable">Hover me</label>
<div class="to-toggle">
<ul>
<li>show1</li>
<li>show2</li>
<li>show3</li>
</ul>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(() => {
$('#hoverable').hover(function() {
$('.to-toggle').addClass('active')
console.log('asdasd')
}, function() {
$('.to-toggle').css({'transition': 'opacity height 5s ease-out'}).removeClass('active')
})
})
</script>
Instead of only transitionning opacity, do it also for visibility :
transition: opacity .5s linear, visibility .5s;
visibility is a "0" or "1" state (no intermediate values) so it will change its value after .5s, giving time for your opacity transition to take effect for the fade out.
Edit : for now I don't understand why it also work for the fade in.
.legal {
visibility: hidden;
background-color: #383838;
opacity: 0;
padding: 5px 0;
z-index: 10;
position: relative;
top: 15px;
left: 10px;
width: 150px;
transition: opacity .5s linear, visibility .5s;
}
.legal-show {
visibility: visible;
opacity: .9;
}
li.legal-container:hover #legal-menu,
#legal:hover {
visibility: visible;
opacity: .9;
}
<ul>
<li style="position: relative;" class="legal-container">
<a>Legal</a>
<ul id="legal-menu" class="legal">
<li>test3</li>
<li>test</li>
<li>test2</li>
</ul>
</li>
</ul>

Max-height transition from 0 to auto or none?

I have an element with a max-height of 0. I want to transition it to no max-height auto or none; whatever makes it expand based on the number of elements present. I don't want to use JS nor flex, yet.
Here's the jsfiddle: https://jsfiddle.net/m9pd8bjh/19/
HTML:
<nav>
<input type="checkbox" id="menu-main-checkbox" hidden>
<label class="toggler" for="menu-main-checkbox">Menu</label>
<div class="hide toggleable">
<ul>
<li>Home</li>
<li>Sample Page</li>
</ul>
</div>
</nav>
CSS:
.hide {
visibility: hidden;
overflow: hidden;
max-height: 0;
}
input[type=checkbox]:checked~.toggleable {
visibility: visible;
max-height: 68px;
}
.toggleable {
transition: visibility 1.5s ease-in-out, max-height .75s ease-in-out;
}
.toggler {
cursor: pointer
}
nav {
background: #e74c3c;
}
When I set the max-height to 68px (the height fitting two list items) it works perfectly, but when I set the max-height to 500px, for example, leaving room for future list items, it takes time to transition from 500 to 0, making it give a delay before the list items disappear again.
I do not wish to use scaling as it complicates it and I have to come up with a solution to solve the spacing under it. It keeps the spacing under the element and reserves it for when it opens out.
One workaround what I found was to use animation with #keyframes.
Remember to add vendor-prefixes.
Browser support for this is the following:
Firefox 5+, IE 10+, Chrome, Safari 4+, Opera 12+
I modified your CSS to this:
.hide {
visibility: hidden;
overflow: hidden;
max-height: 0;
}
input[type=checkbox]:checked~.toggleable {
visibility: visible;
animation: height1 .75s forwards;
}
input[type=checkbox]:not(:checked)~.toggleable {
visibility: visible;
animation: height2 .50s forwards;
}
.toggleable {
transition: visibility 1.5s ease-in-out;
}
.toggler {
cursor: pointer
}
nav {
background: #e74c3c;
}
#keyframes height1 {
0% { max-height: 0; }
100% { max-height: 500px; }
}
#keyframes height2 {
0% { max-height: 500px; }
100% { max-height: 0; }
}
If used like this there will be smaller delay when clicking again.
Here is the updated jsfiddle: https://jsfiddle.net/m9pd8bjh/25/

How to make background image on hover have a transition effect without default background image?

So i'm doing a transition effect on an <a> that has no default background image so when I try to hover over it the transition effect doesn't work. I doubt that without having a default background image it'll not work. So how can I achieve my goal or any alternative on doing that without using javascript? Here is my code:
<nav>
<li>Products</li>
</na>
Here is my css:
.nav>li>a { font-size:17px; color:#929799; padding:45px 25px 35px 25px;
-webkit-transition: background-image 1s ease-in-out;
-moz-transition: background-image 1s ease-in-out;
-o-transition: background-image 1s ease-in-out;
transition: background-image 1s ease-in-out;
}
.nav>li>a:hover, .nav>li>a:focus{
background:url(http://cdn.myld.com.au/2/1198/web_total-gardens_9a0e4cf244.png) no-repeat top center; color:#38c867; }
background-image is a non-animatable property. You can not apply transitions.
I'm assuming you want to fade in the image on hover (?). A way to fake it is to apply your background image to a pseudo element and transition the opacity:
body {
padding-top: 50px;
}
nav>ul>li>a {
font-size: 17px;
color: #929799;
padding: 45px 25px 35px 25px;
position: relative;
}
nav>ul>li>a>span {
position: relative;
}
nav>ul>li>a:before {
content: "";
background: url(http://placehold.it/200x100) no-repeat top center;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
opacity: 0;
transition: opacity 1s ease-in-out;
}
nav>ul>li>a:hover:before,
nav>ul>li>a:focus:before {
opacity: 1;
}
<nav>
<ul>
<li><span>Products</span></li>
</ul>
</nav>
As #GabyakaG.Petrioli mentioned in the comments, your selectors are wrong and you have invalid HTML. Both are fixed in the above example
css transition opacity allow image to change values over a specified duration, animating the property changes
http://css3.bradshawenterprises.com/cfimg/
or try
transition: all 1s ease-in-out;

CSS3 transition

I have this page here (work in progress) http://kimwilddesigns.com/index_new.htm
In this section, I want to be able to hover on the li, have the background image fade out and the h2 to fade in. Is this possible with transitions? I might not be setting it up correctly but I wanted to see if this kind of effect is even possible.
<div id="categories-wrapper">
<ul>
<li class="fine-art"><img src="pics/hp_icon_fine-art.jpg" alt="fine art" width="290" height="240" border="0">
<h2>fine art work</h2>
</li>
<li class="gd">graphic design work</li>
<li class="students">my students' work</li>
</ul>
</div>
Yes, this works nicely with CSS transitions, something like that:
#categories-wrapper li a {
position:relative;
display: block
}
#categories-wrapper li h2 {
position: absolute;
left: 20px;
top: 20px;
opacity: 0;
}
#categories-wrapper li h2,
#categories-wrapper li img {
-webkit-transition: opacity .3s ease-in-out;
-moz-transition: opacity .3s ease-in-out;
-o-transition: opacity .3s ease-in-out;
transition: opacity .3s ease-in-out;
}
#categories-wrapper li:hover h2 {
opacity: 1
}
#categories-wrapper li:hover img {
opacity: 0
}
See the Fiddle for this, slightly changed your markup by putting the h2 inside of the a tag.

Selecting parent menu should show child menu

I am developing a Wordpress site and trying to display my menu as shown in image. How can I display the sub menu when the parent menu is selected?
You can create your main top links with secondary nested like so
<ul class="primary">
<li>Tutorial</li>
<ul class="secondary">
<li>Photoshop</li>
<li>Illustrator</li>
<li>Flash</li>
<li>HTML</li>
<li>PHP</li>
<li>Wordpress</li>
<li>jQuery</li>
<li>more...</li>
</ul>
<li>Wallpaper</li>
<li>Get A Quote</li>
<li>Photography</li>
<li>Freelance</li>
</ul>
then your styling would be like so ( this is using just CSS3, not JS )
<style>
ul.primary {
width: -- ;
height: -- ;
margin: -- ;
overflow: hidden;
}
ul.primary > li {
width: -- ;
height: -- ;
margin: -- ;
float: left;
list-style: none;
}
ul.seconday {
opacity: 0;
width: -- ;
height: -- ;
margin: -- ; /* when this is used with position: relative you can adjust where the drop down is placed. */
position: relative; /* need to set this to relative to position properly */
/* css3 transition */
transition: all .5s ease-in;
-webkit-transition: all .5s ease-in;
-moz-transition: all .5s ease-in;
-ms-transition: all .5s ease-in;
-o-transition: all .5s ease-in;
}
ul.primary > li:hover ul.secondary {
opacity: 1;
}
</style>

Resources