30px is a magic number and should be avoided. A drop down menu usually needs to be at top:100% to clear the main item. Then it doesn’t matter if the menu height is changed.
You don’t need to find the nested ul as you already have found the list parent on mouseover so just add the class straight to the list parent and let css find it. e.g. .active ul {top:100%;}
Rough demo:
Of course no Javascript at all is needed to do the above but I guess you are doing it as a learning exercise :);
But I think that the current one is dependent on JavaScript, Right? Would it be possible to modify my original code so that I can understand what changes you have implemented?
That provides the arrow automatically to any list that contains a drop-down.
It styles any anchor that is the first child of a list item but not a last child (I could have used not only child instead).
The reason is that all the anchors inside a list are only child items except when there is a drop-down and then the anchor is a first child only and so you can attach an arrow to it.
This saves having to add a class to the anchor in order to draw the arrow.
If you look at my menu you will see that when you move the cursor down the drop-down menu the top level item stays highlighted even though you are not over the menu item.
The line of code above says that when you hover a list element the direct child anchor should be aquamarine. The child selector is needed otherwise all the anchors in the drop down would be aquamarine.
The a:hover rule is the rule that changes the background of the anchors in the drop-down (it also works on the top level but is superfluous as the li:hover > a rule will effect a change first).
If you don’t use the li:hover > a rule then the top menu item reverts back to its original color as you traverse the drop-down which will look odd.
But I could not grasp if this is targeting anything. The same can be verified by eliminating that part. Please correct me in case I have difficulty understanding the objective.
CSS can be used to create basic drop-down menus, and in may cases, it may be sufficient for the needs.
I commented on the arrow and JS part, and understand your code:
/* arrows */
/* .nav li a:first-child:not(:last-child) { */
/* make space for arrows*/
/* padding-right: 20px; */
/* } */
/* .nav li a:first-child:not(:last-child):after {
content: "";
position: absolute;
right: 3px;
top: 50%;
margin-top: -6px;
width: 0;
height: 0;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-top: 6px solid red;
transition: 0.5s ease;
}
.nav li:hover a:first-child:not(:last-child):after {
transform: rotate(180deg);
} */
/* js adds active class so testing here */
/* .first > li.active > ul {
box-shadow: 0 0 40px 40px rgba(0, 0, 0, 0.5);
} */
Focus can be moved away from the li element by clicking anywhere else on the page. When the focus is moved away from the li element, the styles defined in the CSS rule .first > li:focus-within > ul will no longer be applied to its child ul element. and a drop-down will disappear.
top: 100%
which means the ul element will be positioned below its parent li element, with 100% of the parent’s height being used as the distance from the top of the parent.
But as soon as increase this 200% or increase
margin-top: 10px;
The anticipated results fail to deliver, I think we cant achieve that. The same was an issue in my JS version else it was working.
The point you are missing is that if you move the absolute dropdown to anything greater than 100% then you will no longer be hovering (or mouseover) on the parent list element (which is the trigger) so the hover is lost and the menu disappears (or with js the class is removed and the element disappears).
Moving the dropdown to 200% makes no sense anyway as it will be too far away from the trigger element and would be a nightmare for users to navigate.
There are ways to move the dropdown further away from the trigger element but I think it is a UI mistake. You can add some padding top to the ul so that although it remains attached to the parent list it looks like its moved away.
I gave the dropdown a negative z-index so that it slides down behind the nav menu item. If it was a positive number it would slide down in front which looks bad.
e.g. It would look like this at half way.
I used a negative z-index to pull the dropdown behind the top level anchors so it drops from behind like this:
The negative z-index will not affect the stacking of the dropdown menu in relation to other items outside the menu because I put a high z-index on the main ul.
That means the z-index value will be auto by default.
This allows the nested ul dropdown to fall behind that item. If the code above had a z-index value (any z-index value other than auto) then you could not place any children behind it because once an element has a z-index other than auto then no child can be hidden behind that item (in css terms it is said to become atomic).
The pointer-events:none is required because although you can’t see the menu it is still there on the screen and would block any interaction with elements that happened to be in the way. In your codepen example you can see this in effect if you add some anchors underneath the menu and then try to hover them each in turn. You will see that where a dropdown menu item would be shown you cannot click the anchor.
For example I added these anchors to your code.
If you do the same in your demo and then run the cursor along the words 'hello" you will see that some words can’t be clicked.
In the given CSS code, the .menuholder class has a border-bottom with a z-index value of 0 by default. The .hmenu > li > ul class, which is the dropdown menu, has a z-index value of -1. This means the dropdown menu will be below the border of the .menuholder element in the stacking order.
The h1 tag is likely being displayed above the dropdown menu because it also has a higher z-index value than -1.
.hmenu > li:hover > ul,
.hmenu > li:focus-within > u
↑ it is low in the food chain of the z-index( Since it is demoted by putting z-index: -1; in .hmenu > li > ul ) as compared to h1 tag and the said border.
A child element cannot be under the borders and background of a parent element that has a z-index other than auto. The parent element becomes atomic and its child can’t escape the parents stacking level.
As you can see from this demo the drop-down lies on top of the red border.
No, you still haven’t grasped the concept of z index properly. :). The drop-down menu could have a z index of a million but it’s the parent of that element that controls the stacking order of elements outside that context. If the parent is z index:1 then the drop down menu will not overlap any other elements outside that context that have a z-index of 2 (or 1 if later in the cascade).
For stacking logic you need to go back to the furthest ancestor that has a position and z index defined.
You don’t show all the css for the elements in your screenshot but you would need to check the whole structure of each separate block to determine what goes where.