简体   繁体   中英

Animating horizontal menu (overlapping menu items without positioning them absolutely)

So a client requires me to realize a menu animation. It was originally created with InvisionApp by the designer. And that App just taked the menu items and positions them absolutely, which should be no good idea to do on a website (responsiveness, etc.).

I have replicated the design in html/css with jsfiddle with absolute positioning:

 ul { list-style: none; display: flex; position: relative; } li { padding: 5px 15px; position: absolute; animation-name: menu-fold; animation-duration: 3s; animation-iteration-count: infinite; } li:nth-child(1) { right: 0; } li:nth-child(2) { right: 119px; } li:nth-child(3) { right: 238px; } li:nth-child(4) { right: 357px; } li:nth-child(5) { right: 476px; } @keyframes menu-fold { from { opacity: 1; } to { opacity: 0; right: 0 } }
 <ul> <li>Menu Item 1</li> <li>Menu Item 1</li> <li>Menu Item 1</li> <li>Menu Item 1</li> <li>Menu Item 1</li> </ul>

How would you do that kind of animation while preserving responsiveness?

(I know there will be ways with JavaScript - although I didn't try them yet - but I'd like to avoid using JavaScript for this, if possible. If you say it's only possible with JS, I'd still like to hear your suggestions:P)

// Edit 1: I came up with a quick jQuery solution, but, I don't know, I still want to avoid it. At least it doesn't feel like it's a good solution:

 var lastItemX = $('ul li').last().position().left; $('ul li').each(function() { var currentItemX = $(this).position().left; $(this).css('transform', `translateX(${lastItemX - currentItemX}px)`) })
 html, body { margin: 0; padding: 0; } ul { padding: 0; list-style: none; display: flex; position: relative; } li { padding: 5px 15px; transition: transform 3s; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <ul> <li>Menu Item 1</li> <li>Menu Item 1</li> <li>Menu Item 1</li> <li>Menu Item 1</li> <li>Menu Item 1</li> </ul>

This is one way, with flex, a transitioning width , and using :hover where only the first element is visible until you hover over it:

 .my-list { list-style: none; padding: 0; display: flex; margin-left: auto; background: yellow; width: 20%; transition: width 0.5s ease; overflow: hidden }.my-list:hover { width: 100%; }.my-list li { display: none; flex: auto; background: orange }.my-list li:first-child, .my-list:hover li { display: block; width: 20%; margin: 5px; padding: 5px; }
 <div> <ul class="my-list"> <li>Menu Item 1</li> <li>Menu Item 1</li> <li>Menu Item 1</li> <li>Menu Item 1</li> <li>Menu Item 1</li> </ul> </div>

The design itself isn't the best for responsiveness, any menu item above ~15 characters won't look great on smaller displays because there isn't enough available width.

A common use for JavaScript is to prevent the animation from jittering, with some debounce/throttle mechanism, and the animation itself can be left to CSS by toggling CSS class names.

Here's an alternate way where each item takes up the full width and has a fixed height: (And where JS only toggles CSS classes)

 function myListOpen() { document.querySelector(".my-list").classList.add("open") } function myListClose() { document.querySelector(".my-list").classList.remove("open") }
 .my-list { list-style: none; margin-left: auto; background: yellow; padding: 5px; width: 20%; overflow: hidden; transition: width 0.5s ease; }.my-list.open { width: 100%; }.my-list li { background: orange; margin: 0; padding: 0; padding-left: 1em; height: 0; line-height: 2em; transition: height 0.5s ease; }.my-list li:first-child, .my-list.open li { height: 2em; visibility: visible; }
 <button type="button" onclick="myListOpen()">open</button> <button type="button" onclick="myListClose()">close</button> <hr /> <div> <ul class="my-list"> <li>Menu Item 1</li> <li>Menu Item 1</li> <li>Menu Item 1</li> <li>Menu Item 1</li> <li>Menu Item 1</li> </ul> </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM