Expandable menu CSS transitions

Asked

Viewed 2,572 times

5

Having an expandable menu like using the CSS transition to open/close at the same time the part that is open and the part that is closing?

The problem does not arise if the menus are the same size (example), but when the size is different it gives idea that the CSS reads the max-height as the actual value and not as a maximum...

Example of the problem here: Fiddle


HTML

<div class="max">
    <ul class="menu">Pequena
        <li>One</li>
        <li>Two</li>
        <li>Three</li>
    </ul>
    <ul class="menu">Pequena
        <li>One</li>
        <li>Two</li>
        <li>Three</li>
    </ul>
    <ul class="menu">Grande
        <li>One</li>
        <li>Two</li>
        <li>Three</li>
        <li>Four</li>
        <li>Five</li>
        <li>Six</li>
        <li>Seven</li>
        <li>Eight</li>
        <li>Nine</li>
        <li>Ten!</li>
    </ul>
</div>

CSS

.max ul {
    border:2px solid #a5f;
    overflow:hidden;
    max-height:20px;
    transition: all 1s ease-in-out;
}

.max ul.opened {
   max-height: 250px;
}

4 answers

4


Defining the height of each <li> as zero by default(default), you can set the height as 20px when you are .opened, even though it doesn’t have exactly the same visual effect

Example

1

Since you are using Javascript to add the class, why not use a jQuery to do this? You wouldn’t work the fixed size...and then behave like an accordion..

HTML:

<ul>
    <li>
        Pequeno
        <ul>
            <li>One</li>
            <li>Two</li>
            <li>Three</li>
        </ul>
    </li>
     <li>
        Grande
        <ul>
             <li>One</li>
            <li>Two</li>
            <li>Three</li>
            <li>Four</li>
            <li>Five</li>
            <li>Six</li>
            <li>Seven</li>
            <li>Eight</li>
            <li>Nine</li>
            <li>Ten!</li>
        </ul>
    </li>

</ul>

jQuery

$("ul li").click(function(){
    //Quando clica esconde QUALQUER que estiver aberta
    $("ul li ul:visible").slideUp();
    //Abre a que possui hierarquia com a que você clicou:
    $(this).children("ul").slideToggle(); 
});

Fiddle

  • Vinicius, thanks, I know how to do using Javascript (Mootools in my case), but I wanted to use only CSS3.

1

You are encountering this delay problem in animation because of property max-height.

Note that in your Fiddle, if you replace the max-height for height the problem does not happen. (Although the layout is different from what you want, probably.)

Delay is caused by the Browser interpolating the property max-height of value 250px at value 20px in the interval of a second. How 250px is greater than the "effective" height of the element, there is a delay until the value of the property max-height is less than the height of the element so that it starts to be "cut".

As far as I know, no browser is currently able to interpolate correctly between a specific value of max-height, as 20px and the automatic value, default. (Google Chrome interpola 20px with 0px, and then displays the height generated by the value default, while Firefox disables the CSS transition completely.)

Unfortunately it will probably be necessary to specify the exact height per element, or use another effect if you want to do this only with CSS.

  • Marco, thank you for taking a look at the problem. I am aware of the problem being related to max-height, what I strange ( and look for a solution ) is, why is that the CSS starts the animation of the maximum value and not the real value where the ul stopped the opening. Since it doesn’t open until 250px why start the animation by 250px?

  • If you use the Web Inspector to observe the computed style of the <div> with it opened, the value of max-height will be in 250px. (What is being excited is the max-height and not the height directly. ) I agree that it is confusing, because it is difficult to visualize the value of max-height directly...

  • Correct, but if I don’t define the heigth ul does not open until 250px, it would wait for the transition to start around 80px (the real value). If I use document.querySelectorAll('.menu')[1].clientHeight; to get the value of heigth I get 80px, which I did not defeni but still the transition stopped there.

1

Hello, I made an example with the Hover event for being more practical!

I don’t know if the inclusion of a new class is ideal, gets less dynamic.

HTML:

<ul class="max">
<li class="menu">Pequena
    <ul>
        <li>One</li>
        <li>Two</li>
        <li>Three</li>
    </ul>
</li>
<li class="menu">Pequena
    <ul>
        <li>One</li>
        <li>Two</li>
        <li>Three</li>
    </ul>
</li>
<li class="menu gr">Grande
    <ul>
        <li>One</li>
        <li>Two</li>
        <li>Three</li>
        <li>Four</li>
        <li>Five</li>
        <li>Six</li>
        <li>Seven</li>
        <li>Eight</li>
        <li>Nine</li>
        <li>Ten!</li>
    </ul>
</li>

CSS:

.max{
    width: 250px;
    height: 400px;
    overflow:hidden;
}

.max > li{
    height: 18px;
    width: 200px;
    margin-bottom:10px;
    padding: 4px;
    padding-left: 20px;
    border:2px solid #a5f;
    float:left;
    overflow:hidden;    
    -moz-transition:all 0.2s ease-out;
    -webkit-transition:all 0.2s ease-out;
    -o-transition:all 0.2s ease-out;
    transition:all 0.2s ease-out;
    -moz-transition-delay:0.15s;
    -webkit-transition-delay:0.15s;
    -o-transition-delay:0.15s;
    transition-delay:0.15s;
}

.max > li:hover{
    height: 80px;
}

.max > li.gr:hover{
    height: 215px;
}

.max > li ul li{
    width: 100px;
    text-align: left;
}

See the Fiddle

  • Hi Luiz, thanks for taking a look at the problem. Your solution does not solve the problem, simply disguises it using a faster transition speed and a lower max-height.

  • Hello Sergio, really not the ideal solution. I tried to work using your approach but I did not succeed! It is an alternative. But I hope you can solve it. I’ll keep up with the news! abs

Browser other questions tagged

You are not signed in. Login or sign up in order to post.