I am using the code of this page:
https://codepen.io/shshaw/pen/gsFch
Now, my CSS looks like:
.subs {
visibility: hidden;
opacity: 0;
transform: translateY(-2em);
z-index: -1;
transition: all 0.3s ease-in-out 0s, visibility 0s linear 0.3s, z-index 0s linear 0.01s;
width: auto;
float: left;
position: absolute;
text-align: left;
border: 2px solid #66ec95;
background: #f4f7f5;
border-radius: 0 5px 5px 5px;
margin-top: -10px;
margin-left: -10px;
}
/* SELECTORS */
#nav li:hover > .subs { /* with this seletor, only the last property is working */
visibility: visible;
opacity: 1;
z-index: 1;
transform: translateY(0%);
transition-delay: 0s, 0s, 0.3s;
margin-top: 10px; /* just for test, only this is working */
}
#nav li :hover + .subs { /* this time, the animation are working but other problems occured (see above) */
visibility: visible;
opacity: 1;
z-index: 1;
transform: translateY(0%);
transition-delay: 0s, 0s, 0.3s;
}
My HTML:
<ul id="nav">
<li aria-haspopup="true">
Services
<div class="subs" id="service-subs" aria-haspopup="false">
Product List<br />
Projects<br />
</div>
</li>
... and so on
So, the second selector for .subs displays the animation but it breaks when I move my cursor into .subs and it's also interrupted many times on displaying because of cursor detects .subs while showing the menu.
Furthermore, I can't understand why does it work with sibling selector when .subs is a child of #nav li.
What am I doing wrong?
Thanks!
I am not 100% sure on the issue of why your code wasn't working. I did re-write it to try to get what you were going for using some methods I think are easier to work with.
Utilizing #keyframes is a great way to build your application with reusable chunks of code.
Utilizing translate3d will tap into the GPU of a computer/device for smoother translations.
Please note I did not take the time to add an HTML wrapper that would hide the drop down menus as they fall. This would easily be done by wrapping the entire menu in a div and setting the overflow to hidden.
I apologize I couldn't help you learn more of why you were getting the bug you had.
.sub-menu-parent {
position: relative;
}
.sub-menu {
position: absolute;
width: 100%;
display: none;
z-index:-1;
}
.sub-menu-parent:hover .sub-menu {
display: block;
animation: 1s slideDown forwards;
}
#keyframes slideDown {
0% {
transform: translate3d(0px, -200px, 0px);
opacity: 0;
z-index:-1;
}
99% {
transform: translate3d(0px, 0px, 0px);
opacity: 1;
z-index:-1;
}
100% {
z-index:0;
}
}
/* presentational */
body {
font: 18px/1.4 sans-serif;
}
nav a {
color: #E00;
display: block;
padding: 0.5em 1em;
text-decoration: none;
}
nav a:hover {
color: #F55;
}
nav ul, nav ul li {
list-style-type: none;
padding: 0;
margin: 0;
}
nav > ul {
background: #EEE;
text-align: center;
}
nav > ul > li {
display: inline-block;
border-left: solid 1px #aaa;
}
nav > ul > li:first-child {
border-left: none;
}
.sub-menu {
background: #DDD;
}
<nav>
<ul>
<li class="sub-menu-parent">
Menu Item 1
<ul class="sub-menu">
<li>Sub Item 1</li>
<li>Sub Item 2</li>
<li>Sub Item 3</li>
<li>Sub Item 4</li>
</ul>
</li>
<li class="sub-menu-parent">Menu Item 2
<ul class="sub-menu">
<li>Sub Item 1</li>
<li>Sub Item 2</li>
<li>Sub Item 3</li>
<li>Sub Item 4</li>
<li>Sub Item 5</li>
<li>Sub Item 6</li>
</ul>
</li>
<li class="sub-menu-parent">Menu Item 3
<ul class="sub-menu">
<li>Sub Item 1</li>
<li>Sub Item 2</li>
</ul></li>
</ul>
</nav>
Related
I'm working on an ebay shop. I need to make categories collapsible after I click the root item (if that is even possible) following ebay's guidelines.
Rules:
Ebay doesn't want us to use active content, that means no JavaScript, flash.
It only allows us to use CSS3.
We can't even change the output HTML for categories. So only option available is CSS.
HTML:
<div id="org-categories">
<div class="ttl">Shop home</div>
<ul class="lev1">
<li>CAT A</li>
<ul class="lev2">
<li>sub cat 1</li>
<li>sub cat 2</li>
</ul>
<li>CAT B</li>
<ul class="lev2">
<li>sub cat 1</li>
<li>sub cat 2</li>
</ul>
<li>CAT C</li>
<ul class="lev2">
<li>sub cat 1</li>
<li>sub cat 2</li>
</ul>
</ul>
</div>
Nice question! Because of this, I just discovered the magic of :focus-within.
<div id="org-categories">
<div class="ttl">Shop home</div>
<ul class="lev1">
<li>CAT A</li>
<ul class="lev2">
<li>sub cat 1</li>
<li>sub cat 2</li>
</ul>
<li>CAT B</li>
<ul class="lev2">
<li>sub cat 1</li>
<li>sub cat 2</li>
</ul>
<li>CAT C</li>
<ul class="lev2">
<li>sub cat 1</li>
<li>sub cat 2</li>
</ul>
</ul>
</div>
Then here comes the magic:
li + .lev2 {
display: none;
}
li:focus-within + .lev2 {
display: block;
}
Check it out in a fiddle
So after digging into this subject, your request seems impossible with this markup. BUT with minor adjustments to the html you provide, you can achieve it with this minimal style:
<style>
.lev1 li { display:block; }
.lev1 ul { display:none; }
.lev1 ul:target { display:block; }
</style>
<div id="org-categories">
<div class="ttl">Shop home</div>
<ul class="lev1">
<li>CAT A</li>
<ul id="lev2a">
<li>sub cat 1</li>
<li>sub cat 2</li>
</ul>
<li>CAT B</li>
<ul id="lev2b">
<li>sub cat 1</li>
<li>sub cat 2</li>
</ul>
<li>CAT C</li>
<ul id="lev2c">
<li>sub cat 1</li>
<li>sub cat 2</li>
</ul>
</ul>
</div>
*Minor adjustments = change ul's classes to an unique id's. That way the :target pseudo element can affect it.
Hope it solve it, and good luck!
Here is one example on how to do this. Whilst this shows expanding menus, it also has some visual effects. Try it out and adapt yourself. The code itself is from http://www.dynamicdrive.com/
<style>
.bgslidemenu {
font: bold 16px 'Bitter', sans-serif; /* use google font */
position: relative;
width: 100%;
}
.bgslidemenu:after { /* clear menu */
content: '';
clear: both;
display: block;
}
/* Top Level Menu */
.bgslidemenu ul {
z-index: 100;
margin: 0;
padding: 0;
position: relative;
list-style: none;
float: right; /* change to "left" to left align menu */
}
/* Top level list items */
.bgslidemenu ul li {
position: relative;
display: inline;
margin-right: 20px; /* spacing between each top level menu item */
float: left;
}
/* Top level menu items link style */
.bgslidemenu ul li a {
display: block;
position: relative;
color: white;
padding: 14px 10px;
color: black;
text-decoration: none;
}
.bgslidemenu ul li a:link, .bgslidemenu ul li a:visited {
color: black;
}
/* Top level menu items link style on hover */
.bgslidemenu ul li:hover > a {
color: purple !important;
}
/* LIs links with a sub UL style */
.bgslidemenu ul li > a {
/* add padding to accomodate arrow inside LIs */
padding-right: 25px;
}
/* LIs links with NO sub UL style */
.bgslidemenu ul li > a:only-child {
/* undo padding for non submenu LIs */
padding-right: 10px;
}
/* LIs links with a sub UL pseudo class (Add down arrow) */
.bgslidemenu ul li > a:after {
/* add arrow inside LIs */
content: "";
position: absolute;
height: 0;
width: 0;
border: 5px solid transparent;
border-top-color: black;
top: 50%;
transform: translateY(-20%);
right: 8px;
}
/* LIs links with NO sub UL pseudo class */
.bgslidemenu ul li > a:only-child:after {
/* undo arrow for non submenu LIs */
display: none;
}
/* Sub ULs style */
.bgslidemenu ul li ul {
position: absolute;
left: -5000px;
top: auto;
opacity: 0;
width: 200px; /* width of drop down menus */
visibility: hidden;
padding-top: 80px; /* Add large top padding to drop down menu */
z-index: -1;
background: #F3F3F3;
transform: translateY(100px);
-webkit-transition: opacity .3s, transform .5s, visibility 0s .3s, left 0s .3s;
transition: opacity .3s, transform .5s, visibility 0s .3s, left 0s .3s;
}
/* Sub UL style on hover */
.bgslidemenu ul li:hover > ul {
visibility: visible;
left: -30px;
transform: translateY(-80px); /* move drop down menu upwards (should be smaller than padding-top value above) */
opacity: 1;
-webkit-transition: opacity 1s, transform .5s;
transition: opacity 1s, transform .5s;
}
/* Sub level Menu list items (alters style from Top level List Items) */
.bgslidemenu ul li ul li {
display: list-item;
float: none;
overflow: hidden;
}
/* Add animated line to sub menu item on Mouseover */
.bgslidemenu ul li ul li:after {
content: '';
position: absolute;
width: 30px;
height: 5px;
background: purple;
left: 0;
top: 50%;
transform: translate3d(-100%, -50%, 0);
transition: transform .3s;
}
.bgslidemenu ul ul li:hover:after {
transform: translate3d(0, -50%, 0);
}
/* Sub Levels link style on hover and when active */
.bgslidemenu ul ul li:hover > a {
color: purple !important;
}
/* Sub level menu links style */
.bgslidemenu ul li ul li a {
font: normal 16px 'Bitter', sans-serif;
padding: 10px;
padding-left: 40px; /* Add left padding to sub menu links to accommodate animated line */
position: relative;
margin: 0;
}
/* ####### responsive layout CSS ####### */
#media (max-width: 700px) {
/*
For mobile and screen browser windows
Get Sub ULs to expand entire width of document and drop down
Changes menu reveal type from "visibility" to "display" to overcome bug. See comments below
*/
.bgslidemenu ul {
float: none;
}
.bgslidemenu ul li {
position: relative;
display: block;
width: 100%;
}
.bgslidemenu ul li ul {
width: 100%;
position: relative;
border-top: 2px solid #eee;
/* change menu reveal type from "visibility" to "display". Former seems to cause browser to jump to top of page sometimes when menu header is tapped on */
display: none;
}
.bgslidemenu ul li:hover > ul {
display: block;
padding-top: 0;
transform: none;
z-index: 10000;
left: 0 !important;
top: auto;
}
.bgslidemenu ul ul li:hover > ul {
left: 0 !important;
top: auto;
}
}
</style>
<div class="bgslidemenu">
<ul>
<li>Item 1</li>
<li>Item 2
<ul>
<li>Sub Item 1.1</li>
<li>Sub Item 1.2</li>
<li>Sub Item 1.3</li>
<li>Sub Item 1.4</li>
<li>Sub Item 1.2</li>
<li>Sub Item 1.3</li>
<li>Sub Item 1.4</li>
</ul>
</li>
<li>Item 3</li>
<li>Item 4
<ul>
<li>Sub Item 3.1</li>
<li>Sub Item 3.2</li>
</ul>
</li>
<li>Home</li>
</ul>
</div>
I am trying to make a nice transition for my site's menu: when the user hovers over the parent item, the children slide down and when the mouse leaves, they should go back up. But they don't, as seen in this fiddle. Then I asked for help here on SO and was pointed to using the overflow: hidden; approach and only transition the height. Okay. But that hid my child item's children items as seen in the snippet below:
ul {
list-style: none;
padding: 0;
}
li {
width: 180px;
}
#menu ul ul {
position: absolute;
overflow: hidden;
background: red none repeat scroll 0 0;
}
#menu ul li {
position: relative;
}
#menu ul ul li {
height: 0;
transition: height 0.2s ease 0s;
}
#menu ul ul ul {
margin-left: 100%;
top: 0;
}
#menu ul li:hover>ul>li {
height: 32px;
}
<nav id="menu">
<ul>
<li>Parent Item
<ul>
<li>Child Item</li>
<li>Child Item >
<ul>
<li>Child Child Item 1</li>
<li>Child Child Item 2</li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
So basically the "Child Child Item 1" and "Child Child Item 2" items are invisible to the user. How can I have both the slide down/up transition on mouse hover/leave and display both child items? Can it be done in pure CSS?
You can set an initial opacity on the li to 0, in addition to a height of 0.
On :hover, change the opacity to 1. Note that I haven't included opacity in the transition effect. I think it may look better for it to change immediately.
updated
Instead of using opacity, I think setting the initial font-size to 0 and scaling up will produce a smoother effect. I've added classes to the triggers and menus for clarity.
* {
cursor: pointer;
}
ul {
list-style: none;
padding: 0;
}
li {
width: 180px;
}
#menu ul ul {
position: absolute;
background: red none repeat scroll 0 0;
}
#menu ul li {
position: relative;
}
.dropdown-one li,
.dropdown-two li {
height: 0;
font-size: 0;
transition: height 0.2s ease 0s;
}
#menu ul ul ul {
margin-left: 100%;
top: 0;
}
.dropdown-trigger-one:hover .dropdown-one>li,
.dropdown-trigger-two:hover .dropdown-two>li {
height: 32px;
font-size: 1em;
}
<nav id="menu">
<ul>
<li class="dropdown-trigger-one">Parent Item
<ul class="dropdown-one">
<li>Child Item</li>
<li class="dropdown-trigger-two">Child Item >
<ul class="dropdown-two">
<li>Child Child Item 1</li>
<li>Child Child Item 2</li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
I'm trying to have the sub menu items disappear after a certain amount of time using CSS only. Sadly if I have more than one sub menu and hover over the next sub menu the other one has not yet disappeared. Any way to make the previous sub menu disappear when the next sub menu is show with CSS only?
It wouldn't be hard for me to write a JQuery script to achieve this but would nice if I could do it using css. Would there be any JS/JQuery plugins to recommend if this is not possible with CSS?
http://codepen.io/anon/pen/aBPBbj
nav > ul > li {
display: inline-block
}
nav > ul > li ul {
visibility: hidden;
position: absolute;
top: 105%;
left: 0;
transition: 0.2s 1s;
}
nav > ul > li:hover ul {
visibility: visible;
transition-delay: 0s;
}
nav ul {
list-style: none;
padding: 0;
margin: 0;
}
nav li {
width: 100px;
background: #eee;
margin: 2px;
position: relative;
padding: 10px;
}
nav a {
display: block;
}
body {
padding: 10px;
}
<nav>
<ul>
<li>
Dropdown
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
</li>
<li>
Dropdown
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
</li>
</ul>
</nav>
Try to remove transition: 0.2s 1s;
Just change the tarnsition time as shown below code.
nav > ul > li ul {
visibility: hidden;
position: absolute;
top: 105%;
left: 0;
transition: 0.2s;
}
Try this example of code:
<ul id="mainNav">
<li>item 1
<ul>
<li>sub item 1</li>
<li>sub item 2</li>
<li>sub item 3</li>
</ul>
</li>
<li>item 2
<ul>
<li>sub item 1</li>
<li>sub item 2</li>
<li>sub item 3</li>
<li>sub item 4</li>
</ul>
</li>
<li>item 3
<ul>
<li>sub item 1</li>
<li>sub item 2</li>
</ul>
</li>
ul#mainNav {
float:left;
width:auto;
margin:0; padding:0;
color:white;
list-style-type:none;
}
ul#mainNav > li {
float:left;
display:inline;
position:relative;
padding:5px;
border:1px white solid;
background-color:black;
}
ul#mainNav > li:hover {
background:white;
color:black;
border:1px black solid;
}
ul#mainNav > li:hover ul {
visibility: visible;
opacity: 1;
transition-delay: 0s, 0s;
}
ul#mainNav li ul {
position:absolute;
float:left;
width:100px;
height:0;
padding:10px;
margin:0;
visibility: hidden;
opacity: 0;
transition-property: opacity, visibility;
transition-duration: 1.4s, 0s;
transition-delay: 0s, 0s;
}
ul#mainNav ul li {
background-color:white;
border:1px black solid;
}
ul#mainNav ul li:hover {
background-color:black;
border:1px white solid;
color:white;
visibility: hidden;
opacity: 0;
transition-property: opacity, visibility;
transition-duration: 0s, 0s;
transition-delay: 0s, 0s;
}
Seeing as no one proposed a working CSS only solution apparently the only way to achieve this is through javascript/JQuery.
https://jsfiddle.net/jkanckr3/
<nav>
<ul>
<li>
Dropdown
<ul>
<li>One</li>
<li>Two</li>
<li>Three</a></li>
</ul>
</li>
<li>
Dropdown
<ul>
<li>One</li>
<li>Two</li>
<li>Three</a></li>
</ul>
</li>
</ul>
</nav>
var timeout;
$('nav > ul > li').on({
mouseenter: function () {
clearTimeout(timeout);
$('nav > ul > li > ul').hide();
$('ul', this).show();
},
mouseleave: function () {
var self = this;
timeout = setTimeout(function() {
$('ul', self).hide();
}, 500);
}
});
nav > ul > li {
display: inline-block
}
nav > ul > li ul {
display: none;
position: absolute;
top: 105%;
left: 0;
}
nav > ul > li:hover ul {
//visibility: visible;
}
nav ul {
list-style: none;
padding: 0;
margin: 0;
}
nav li {
width: 100px;
background: #eee;
margin: 2px;
position: relative;
padding: 10px;
}
nav a {
display: block;
}
body {
padding: 10px;
}
I'm trying to add a "sub menu" to a drop down menu. Say I wanted to add a sub menu to Item 3 (see html), how would I go about doing that?
Thanks,
Here's my CSS:
.nav_menu {
width:100%;
background-color:#EFEFEF;
z-index:2000;
border:1px solid #ccc;
}
.selected {
background-color:#ccc;
color:#333;
}
.nav_menu a:link {
color:#007dc1;
}
.nav_menu a:visited {
color:#007dc1;
}
.nav_menu a:hover {
color:#007dc1;
}
.nav_menu ul {
text-align: left;
display: inline;
margin: 0;
padding: 15px 4px 17px 0;
list-style: none;
}
.nav_menu ul li {
font-size:16px;
display: inline-block;
margin-right: -4px;
position: relative;
padding: 8px 22px;
font-weight:600;
transition: all 50ms linear;
transition-delay: 0s;
}
.nav_menu ul li ul {
padding: 0;
position: absolute;
top: 37px;
left: 0;
width: 230px;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
display: none;
opacity: 0;
visibility: hidden;
display: block;
opacity: 0;
-webkit-transition: opacity .2s;
z-index:50000;
}
.nav_menu ul li ul li {
background-color:#535353;
border-top:1px solid #fff;
display: block;
font-size:12px;
color:#fff;
}
.nav_menu ul li ul li:hover {
background: #B2B2B2;
}
.nav_menu ul li:hover ul {
display: block;
opacity: 1;
visibility: visible;
}
Here's my HTML:
<ul>
<li>All Items
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3 with Sub Menu</li>
</ul>
</li>
</ul>
Firstly, since your menu is based simply on the CSS :hover pseudo-class, make sure that your ul and li elements do not have any space between them, because this will lead to the entire menu dissapearing.
The HTML code
<div class='nav_menu'>
<ul>
<li>All Items
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li class='nav_menu_sub'>Item 3 with Sub Menu
<ul>
<li>SubItem 3.1</li>
<li>SubItem 3.2</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
Just like the drop down that you already provided, simply adding a ul element within the li element should suffice to create the sub menu. I added a nav_menu_sub class to the li that opens the sub menu making it easier to select via CSS (avoiding .nav_menu ul li ul li).
The CSS code
.nav_menu_sub {
padding:0;
margin:0;
}
.nav_menu_sub ul {
margin-top:-7px;
display: none !important;
}
.nav_menu_sub:hover ul {
display: block !important;
opacity: 1;
visibility: visible;
}
The margin-top:-7px on the ul element was added to ensure that it fits nicely up against the li.
Add the !important to the display attribute to get it overwrite the previously declared styling.
Working jsFiddle: http://jsfiddle.net/akhrbkug/
Judging from the css you posted:
.nav_menu ul li:hover ul {
display: block;
opacity: 1;
visibility: visible;
}
It looks like you have to add another ul in the submenu li:
<ul>
<li class='nav-menu'>All Items
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3 with Sub Menu
<ul>
<li>SubItem 3.1</li>
<li>SubItem 3.2</li>
</ul>
</li>
</ul>
</li>
</ul>
Fiddle for the demo
http://jsfiddle.net/ee9ebv2s/
JSFiddle: http://jsfiddle.net/oj1vrjzh/12/
I'm trying to create a dropdown navbar that will first show sections, then display subsections once hovered on, all controlled by jquery. In the JSFiddle currently shown, the submenu covers the super sections:
<ul class="dropdown">
<li id="menu1" class="nav_menu">
Menu1
</li>
<ul class="submenu">
<li>ASDF</li> <!-- These cover up 'Menu2' -->
<li>ASDF</li>
<li>ASDF</li>
</ul>
<li id="menu2" class="nav_menu">
Menu2
</li>
</ul>
How do I change is so that when the submenu class is displayed, that it will bump the "nav_menu" classes down to the bottom of the submenu class?
I would suggest to try this one i adjusted for you:
Just simple and awesome!
Check this out live at codepen here!
Implementation:
HTML
<nav class="nav">
<ul>
<li>
Home
<ul>
<li>Sub Menu 1
<ul>
<li>Level 3 Menu 1
<ul>
<li>Level 4 Item 1</li>
<li>Level 4 Item 2</li>
</ul>
</li>
<li>Level 3 Menu 2</li>
</ul>
</li>
<li>Sub Menu 2</li>
<li>Sub Menu 3</li>
</ul>
</li>
</ul>
</nav>
CSS
$brand-primary: #fff;;
$text-color: grey;
nav {
font-family: Arial, sans-serif;
font-size: 18px;
line-height: 24px;
background: $brand-primary;
color: $text-color;
> ul {
list-style: none;
> li {
display: inline-block;
}
}
li {
position: relative;
&:hover {
background: mix(#000000, $brand-primary, 20%);
}
li:hover > a {
background: mix(#000000, $brand-primary, 30%);
}
}
a {
display: block;
padding: 10px 20px;
color: inherit;
text-decoration: none;
#include transition(all 0.3s);
}
// Submenu
.has-subnav {
> a {
padding-right: 30px;
position: relative;
&:after {
content: "ยท";
display: block;
font-family: sans;
font-size: 36px;
line-height: 0;
position: absolute;
right: 5px;
margin-right: 2px;
top: 22px;
}
}
}
ul ul {
width: 240px;
background: mix(#000000, $brand-primary, 20%);
position: absolute;
left: 0;
top: 100%;
ul {
left: 100%;
top: 0;
#include box-shadow(-1px 0 4px rgba(0,0,0,0.2));
}
}
// fade effect with css3
li {
& > ul {
visibility:hidden;
opacity:0;
#include transition(visibility 0s linear 0.1s, opacity 0.1s linear);
}
&.active {
> a {
}
& > ul{
visibility:visible;
opacity:1;
#include transition-delay(0s);
#include transition-duration(0.3s);
}
}
}
}
JAVASCRIPT
// navigation
$('.nav li:has(ul)')
.addClass('has-subnav')
.each(function(){
var $li = $(this)
, $a = $('> a', $li);
$a.on('mouseenter', function(){
$li.addClass('active');
});
$li.on('mouseleave', function(){
$li.removeClass('active');
});
});