CSS Drop Down Menu hidden behind horizontal scrollbar

I am almost finished with my project - except for one thing = my CSS Drop Down Menu is hidden behind my horizontal scrollbar. Note that if there is no scrollbar, there is no hiding behind text and/or graphics that follow immediately in the DOM; hiding only occurs when I implement a scrollbar via:

#menubar {
	white-space: nowrap;
	overflow-y:  none;
	overflow-x:  auto;
	-webkit-overflow-scrolling: touch;   /* for iOS */
}

It’s logical to conclude that a simple use of position: relative; z-index: 1000; should correct this problem, except it does not. Note that I don’t wish to add !important which I consider hiding the true problem.

HTML:

<ul id="menubar">
	<li>
		<a href="DOI.html">
		Declaration of<br>Independence
		</a>
	</li>

	<li>
		<a href="#">Drop Down<br>Menu</a>     <!-- #menubar > li            -->
		<ul class="aMenu">                    <!-- drop menu = .aMenu       -->
			<li><a href="#">text21</a></li>   <!-- drop-menu item =         -->
			                                  <!--   #menubar > li          -->
			<li><a href="#">text22</a></li>   <!-- another drop-menu item   -->
		</ul>
	</li>

	<li>
		<a href="Pledge_of_Allegiance.html">
		Pledge of<br>Allegiance
		</a>
	</li>
</ul>

CSS:

#menubar {
	margin:  0em;
	padding: 0em;
}

#menubar {
	list-style: none;
}

#menubar {
	white-space: nowrap;
	overflow-y:  none;
	overflow-x:  auto;
	-webkit-overflow-scrolling: touch;   /* for iOS */
}

#menubar > li {
	display: inline-block;
}

/* All items in main #menubar + in drop + (sub-)sub-menus. */
#menubar li {
	list-style: none;   /* supposed to be inherited ? */

	/* this width takes care of any needed horizontal padding */
	width:      8.1em;     /* Wish I could dump this fixed width here. */
 
	color:      #00008b;
}

image

Your menu isn’t hiding its contained within your scroll box. You would need to scroll down inside your scroll box to see it.

You can’t have a dropdown menu show outside of a box that is not overflow:visible. Overflow other than visible will contain all the overflow inside the scroll box. :slight_smile:

Boy, you’re quick …

Given your response, I will look into using:

.hide-scroll::-webkit-scrollbar {
	display:            none;
}

to temporarily hiding the scrollbar just before :hover which displays the drop-down.

Don’t have a clue yet if that’s possible … but it’s worth a shot

That won’t work I’m afraid as the scrollbar is only the mechanism that allows you to scroll. It’s the overflow:auto that stops the menu showing outside of that context. (BTW There is no property called overflow-y:none).

The only way you can see the hover menu is if #menubar had enough height for it to show. Of course that affects the layout of the page so you can’t just have blank space waiting for a menu to show. (It could be that you could absolutely place the whole menu bar as it looks like a fixed height and then you could increase the height so that the dropdown can show over other elements. I’d need to see the full context of code to see if that’s possible.)

Do you have a working demo of the menu so that we can see if there’s a workaround? Or a codepen example?

There is one other way that might work and that is not to have a position:relative context on the absolute menu. If three is no position:relative parent inside the scrollbox then the absolute element should appear outside of the scrollbox. Again I’d need to see full code to work out if that was possible :slight_smile:

Actually while that will appear to work initially it will misplace the dropdowns that you have to scroll to see.

Here’s an example showing the fail.

I think the only solution if you want to scroll menu items sideways is to resort to JS to achieve this as I don’t believe there is a css only solution that can handle this nicely.

Here we go … its almost done.

https://jsfiddle.net/johnlove/2gmqhrs3/65/

That’s not working I’m afraid and indeed you could have ‘mostly’ done that effect with css anyway :slight_smile:

It looks ok unless there is a need to scroll the menu sideways. You can’t scroll the menu sideways because you remove the overflow on hover. There is a small area between the list items where you don’t trigger the hover and if you are careful you can scroll the menu but once again when you hover over an item the overflow is removed and the menu stretches to full width.

Here’s a screenshot of what is happening at smaller widths.

As you can see that is not a usable menu.

I assume you want to scroll the menu because you have a lot of items otherwise you could do away with the scrolling effect and just let the items wrap or switch to a hamburger menu once the items are squeezed together.

There is also a the question of keyboard accessibility and touch accessibility as hover and touch are not the same things.

If you must have a sideways scrolling menu then you would have to have a lot more JS and clone the submenus and then re-insert them after the menu html at the correct position to match the menu (and of course constantly monitor and update the position should the parent menu scroll while the submenu is open).

That is quite a task even for a competent JS programmer and if that’s the way you want to go I would suggest you reformat your question and post in the JS forum if you want help in building it.

Are you sure this is worth all the effort and maybe the usual hamburger approach for smaller screen sizes would be better where you create a vertical list only?

I’ll have another think and see if there’s anything simpler that could be done but I think this is a step too far for css alone.

1 Like

This is the only CSS method I can see that would work but its not very nice or user friendly.:slight_smile:

Even if you did script this with JS you can see how difficult this is to navigate to the lower levels as you have to scroll sideways while still holding the menu open but as soon as you scroll the menu moves away from the pointer and the hover effect is gone.

Either way this will show whether you need to reconsider your approach :wink:

Like so many menus these days, it’s not accessible for keyboard users. frown

3 Likes

lovesongforever.com/testmenubar

I have uploaded my code. The above web page is, IMO, more usable than a jsFiddle.

Yes, I see the overflow - but just with iOS - will definitely work on that OUCH.

That aside, I am rethinking my approach. And in my rethinking, I have returned to some basic questions

  1. what does a Browser do when it encounters my .html, .css and .js? (talk about a semester long course just on this question)

  2. who/what causes the menu to collapse?

I have various:
#menubar li
#menubar li:hover

splattered throughout my css.

I presume the Browser knows that #menubar li is the non-hover case. If true, then I suppose that if I alter this non-hover case to prevent collapsing then the difficulty with horizontal sub-menus goes away?

I know Apple’s and MS’s main OS menubar doesn’t collapse if I go outside their sub-menus … ASAMOF, collapsing occurs only if I move up to a non-parent item.

This is called “getting back to basics”

Hi,

I’m not quite sure I understand the questions as intended but here goes :slight_smile:

Re question 1 then a browser will do whatever you have told it to do if it understands your html, CSS and JavaScript.

If the code is valid and logical then it does what it’s told. However if you have logic errors or badly formed code you probably won’t get your desired result.

I’m not sure that’s what you were asking though :slight_smile:

Re question 2 then the drop menus open when you hover over the parent list item and the css changes the drop menu so that it’s visible. Once you stop hovering the menu item or it’s nested drop down the menu will collapse.

It’s the action of hovering that holds the menu open. Once you no longer hover the current menu item the menu closes.

Your demo does not work in any shape or form and is unusable so I think you need to rethink your approach. It’s unclear why you need to scroll sideways anyway and not something anyone does with drop menus.

You would be better off with a click menu instead of hover which would require using JavaScript but use something that is keyboard accessible. :slight_smile:

1 Like

???

MacOS, Windows 10 - their Finder/OS menus.

FWIW I am getting closer to curing all the ills you’ve mentioned using Flexbox.

It won’t make a difference unless you have changed your design methodology. Flexbox has nothing to do or to contribute to the issue in hand.

They are not web pages. Show me one example of a menu like you want on the web.

1 Like

I am modifying my original post on css menubars to provide a link that demonstrates my latest progress … one biggee down, one to go:

lovesongforever.com/testmenubar

The solved biggee was to get the drop down menu to go over the scrollbar. THE cause was that the li.drop was absolute positioned inside a relative position enclosure. AARG!!!

The one remaining biggee is that as I scroll horizontally, the drop down menu does not follow the parent:

ul#menubar li.drop = parent
ul#menubar li.drop .aMenu = the drop menu itself

PLEASE, no clues … let me fuss with it a bit (a lot)

One of you guys probably said “I told you about that”. But please don’t say it now.

Unfortunately, it’s still not accessible to keyboard navigation. frown

1 Like

Sorry I can’t resist :slight_smile:

If I have given advice then I have taken time to think and help out as best I can. If you missed the advice the first time time around (or didn’t understand it) then perhaps you should go back and re-read my answers more fully now that you have found out the same for yourself. :wink:

I already pointed that out to you at the start and then tested it for you to show that it was not possible and you would run into the issue as shown in my codepen and as your current demonstration.

I’m not sure what you don’t understand when I say there is no way to make a drop down menu work properly inside a scrollable element and have the drop menu remain outside the scrollable element and in touch with the trigger point when the menu has scrolled sideways. It is not possible to do this unless you write some JS to move the menu to the new position of the scrolled item

I’ve been doing these menus for 25 years and I can tell you that you cannot do what you are attempting in pure CSS. Its not desirable either unless you can build in some accessibility features but that’s a whole set of other questions that need to be addressed.

Looking at your code you are obviously at a very early stage in your html and css journey and while this is a good chance for you to learn how to do things it is not good to try and achieve the impossible with limited knowledge.

Lose the scroll container and instead make sure your menu doesn’t overflow.

If you must have a scrolling sideways menu with a dropdown then you better start learning some advanced JS to do this.

Sorry if the above sounds a bit harsh but I’d rather you didn’t waste years on something that can’t possibly work in the manner you are attempting.:slight_smile:

4 Likes

I’ve added the necessary JS to my old demo so you can see the sort of coding you will need to use. This is a fully working example which is also keyboard friendly in modern browsers.

The codepen below is a very simplified barebones example just to show the js technique rather than confusing you with the multiple menus.

In your example you would need to add this script.

(function () {
  const scroller = document.querySelector("#menubar");
  const dropDown = document.querySelectorAll("ul#menubar > li.drop > .aMenu");
  scroller.addEventListener("scroll", checkScroll);

  function checkScroll() {
    for (let i = 0; i < dropDown.length; i++) {
      dropDown[i].style.transform =
        "translateX(-" + scroller.scrollLeft + "px)";
    }
  }
})();

Of course it won’t work as smoothly as my example but will show you how it can be made to work :slight_smile:

3 Likes

Javascript it is = accessing scrolled drop down menus (found my solution on stackoverflow.com)

/* from stackoverflow.com */
function scrollMenusAdjust() {

	$(document).ready(function() {

		$(".aMenu").each(function() {
			var _this = $(this);
			_this.css("left", _this.parent().position().left);
			
			$("#menubar").scroll(function() {
				_this.css("left", _this.parent().position().left);
			});
		});
	
	});

}   // function scrollMenusAdjust {

Before I present the actual link to my re-vamped code, it seems I am down to 2 remaining problems:

(1) keyboard accessibility; arrow keys work for scrolling the menubar, but accessing dropped down items (with <a>) via the <tab> key or <cr> is a whole new journey for me, so that will take some time.

(2) I have found out that calling 2 functions with on (“click” …) is definitely not as simple as calling within the “click” handler the 2 functions in sequence. My guess is that I will have to use some sort of callback approach because I want the 1st function to finish before the 2nd function starts = a work in progress.

Anyway - yes I have previously posted the link, but …

lovesongforever.com/testmenubar

I already gave you a similar solution (without the need for jquery either) so I’m a little upset that you didn’t acknowledge my work :frowning: I gave you a working solution to copy from and indeed I gave you the whole code to add to your page.

The version I gave you works with the keyboard in modern browsers as I already mentioned. It uses the :focus-within pseudo class and if you look through my code you can see it in action and how to apply it.

2 Likes

Didn’t get back from Arlington Cemetery until very late, but this morning I took care of the citing for your code … even gave you a Menu - take a look:

lovesongforever.com/testmenubar

1 Like