responsive mega menu with multiple levels in Bootstrap 3

I specialize in creating mega menu navigation using Bootstrap 3.

HTML:

<div class="container">
    <nav class="navbar navbar-default">
        <div class="navbar-header">
            <button class="navbar-toggle" type="button" data-toggle="collapse" data-target=".js-navbar-collapse">   <span class="sr-only">Toggle navigation</span>
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>

            </button>   <a class="navbar-brand" href="#">MegaMenu</a>

        </div>
        <div class="collapse navbar-collapse js-navbar-collapse">
            <ul class="nav navbar-nav">
                <li class="dropdown mega-dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">Collection <span class="glyphicon glyphicon-chevron-down pull-right"></span></a>

                    <ul class="dropdown-menu mega-dropdown-menu row">
                        <!-- Dropdown Content Here -->
                        
                    </ul>
                </li>
            </ul>
                            <ul class="nav navbar-nav">
                <li class="dropdown mega-dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">Collection 2<span class="glyphicon glyphicon-chevron-down pull-right"></span></a>

                    <ul class="dropdown-menu mega-dropdown-menu row">
                        <!-- Dropdown Content Here -->
                        
                    </ul>
                </li>
            </ul>
        </div>
        <!-- /.nav-collapse -->
    </nav>
</div>

CSS:

body {
    font-family:'Open Sans', 'sans-serif';
    background:#f0f0f0;
}
.navbar-nav>li>.dropdown-menu {
    margin-top:20px;
    border-top-left-radius:4px;
    border-top-right-radius:4px;
}
.navbar-default .navbar-nav>li>a {
    width:200px;
    font-weight:bold;
}
.mega-dropdown {
    position: static !important;
    width:100%;
}
.mega-dropdown-menu {
    padding: 20px 0px;
    width: 100%;
    box-shadow: none;
    -webkit-box-shadow: none;
}
.mega-dropdown-menu:before {
    content:"";
    border-bottom: 15px solid #fff;
    border-right: 17px solid transparent;
    border-left: 17px solid transparent;
    position: absolute;
    top: -15px;
    left: 285px;
    z-index: 10;
}
.mega-dropdown-menu:after {
    content:"";
    border-bottom: 17px solid #ccc;
    border-right: 19px solid transparent;
     

Now, I have two <ul> for the navigation menus. In both, I see a submenu. This means that if I click on Collection or Collection 2, I see a submenu. However, there seems to be an issue with the second submenu placement beneath Collection 2.

How can this issue be fixed?

Problem Description: When clicking on Collection and Collection 2, one submenu appears below Collection only instead of both.

Note: The position of the arrow needs to be adjusted. For both dropdowns, the upward arrows are indicating the same position. These positions need to be changed as follows:

  1. First Dropdown: https://i.sstatic.net/xlWPN.png
  2. Second Dropdown: https://i.sstatic.net/RrP9D.png

JSFIDDLE DEMO

Answer №1

The issue arises due to the positioning of the CSS triangle in relation to the overall navbar. Since this element's position remains constant, the triangle fails to reposition itself accordingly.

An effective solution is to nest the triangle within the currently selected item. To achieve this, simply remove:

.mega-dropdown-menu:before {
    content:"";
    border-bottom: 15px solid #fff;
    border-right: 17px solid transparent;
    border-left: 17px solid transparent;
    position: relative;
    top: -15px;
    left: 150px;
    z-index: 10;
}
.mega-dropdown-menu:after {
    content:"";
    border-bottom: 17px solid #ccc;
    border-right: 19px solid transparent;
    border-left: 19px solid transparent;
    position: absolute;
    top: -17px;
    left: 283px;
    z-index: 8;
}

and replace it with:

.open .dropdown-toggle:after {
    border-bottom: 15px solid #fff;
    border-left: 17px solid transparent;
    border-right: 17px solid transparent;
    content: "";
    left: 163px;
    position: absolute;
    bottom: -21px;
    z-index: 1500;
}
.open .dropdown-toggle span:after {
    border-bottom: 17px solid #ccc;
    border-left: 19px solid transparent;
    border-right: 19px solid transparent;
    content: "";
    left: -10px;
    position: absolute;
    bottom: -41px;
    z-index: 8;
}

This will attach the triangle to the text and down arrows, adjusting its position relative to these elements.

See a demonstration on Fiddle - http://jsfiddle.net/7eHFd/4/

Update: If the triangle remains static when resizing, wrap the above code with a media query like so:

@media (min-width: 768px) {
}

View an updated version on Fiddle - http://jsfiddle.net/7eHFd/5/

Answer №2

Solution: JS Fiddle Solution Link

Insights:

According to this resource, it is not possible to manipulate the CSS of pseudo elements. The styling and content generated by :after or :before are not part of the Document Object Model (DOM) and hence cannot be targeted or modified.

In addition, the solution provided is ideal for:

  1. Creating a responsive design
  2. Centering the menu arrow within the menu item

Challenges Encountered:

Pseudo Class CSS:

.mega-dropdown-menu:before {
    content:"";
    border-bottom: 15px solid #fff;
    border-right: 17px solid transparent;
    border-left: 17px solid transparent;
    position: absolute;
    top: -15px;
    left: 285px;
    z-index: 10;
}
.mega-dropdown-menu:after {
    content:"";
    border-bottom: 17px solid #ccc;
    border-right: 19px solid transparent;
    border-left: 19px solid transparent;
    position: absolute;
    top: -17px;
    left: 283px;
    z-index: 8;
}

To address this issue, the `.mega-dropdown-menu' class needs to have its pseudo border styling reset.

Solution: JS Fiddle Solution Link

Therefore, a new element must be introduced with the following styling attributes:

CSS Revisions:

.show{
    display: block;
}
.arrow1, .arrow2 {
    position: absolute;
    z-index: 99999;
    display: none;
}
.open .arrow1, .open .arrow2 {
    display: block;
}
.arrow1 span:after, .arrow2 span:after {
    content:"";
    border-bottom: 15px solid #fff;
    border-right: 17px solid transparent;
    border-left: 17px solid transparent;
    position: absolute;
    top: 6px;
    left: 2px;
}
.arrow1 span:before, .arrow2 span:before {
    content:"";
    border-bottom: 17px solid #ccc;
    border-right: 19px solid transparent;
    border-left: 19px solid transparent;
    position: absolute;
    top: 4px;
}
.mega-dropdown-menu:after, .mega-dropdown-menu:before{border: none;} 

JavaScript Modifications:

$(".nav > li.mega-dropdown").eq( 0 ).append("<p class='arrow1 arrOw'><span></span></p>");
$(".nav > li.mega-dropdown").eq( 1 ).append("<p class='arrow2 arrOw'><span></span></p>");

$(".nav > li.mega-dropdown").eq( 0 ).click(function () {
    //x = $(".mega-dropdown.open").position();
    x = $(this).position();
    aa = x.left+75;
    $(this).find(".arrow1").css("left", aa);
});
$(".nav > li.mega-dropdown").eq( 1 ).click(function () {
    //x = $(".mega-dropdown.open").position();
    x = $(this).position();
    aa = x.left + 75;
    $(this).find(".arrow2").css("left", aa);
});

If there are any further issues, please leave a comment below.

Best Regards, D.

Answer №3

Resolved an Issue here >> Mega drop down triangle

View in Full Screen

Confirmed to be working on 1920 X 1080 Resolution!

Currently tackling the second issue.

CSS code snippet:

  body {
    font-family:'Open Sans', 'sans-serif';
    background:#f0f0f0;
}
.navbar-nav>li>.dropdown-menu {
    margin-top:20px;
    border-top-left-radius:4px;
    border-top-right-radius:4px;
}
.navbar-default .navbar-nav>li>a {
    width:200px;
    font-weight:bold;
}
.mega-dropdown {
    position: static !important;
    width:100%;
}
.mega-dropdown-menu {
    padding: 20px 0px;
    width: 100%;
    box-shadow: none;
    -webkit-box-shadow: none;
}
.mega-dropdown-menu-1:before {
    content:"";
    border-bottom: 15px solid #fff;
    border-right: 17px solid transparent;
    border-left: 17px solid transparent;
    position: absolute;
    top: -15px;
    left: 30%;
    z-index: 10;
}
.mega-dropdown-menu-1:after {
    content:"";
    border-bottom: 17px solid #ccc;
    border-right: 19px solid transparent;
    border-left: 19px solid transparent;
    position: absolute;
    top: -17px;
    left: 30%;
    z-index: 8;
}
.mega-dropdown-menu-2:before {
    content:"";
    border-bottom: 15px solid #fff;
    border-right: 17px solid transparent;
    border-left: 17px solid transparent;
    position: absolute;
    top: -15px;
    left: 50%;
    z-index: 10;
}
.mega-dropdown-menu-2:after {
    content:"";
    border-bottom: 17px solid #ccc;
    border-right: 19px solid transparent;
    border-left: 19px solid transparent;
    position: absolute;
    top: -17px;
    left: 50%;
    z-index: 8;
}
.mega-dropdown-menu > li > ul {
    padding: 0;
    margin: 0;
}
.mega-dropdown-menu > li > ul > li {
    list-style: none;
}
.mega-dropdown-menu > li > ul > li > a {
    display: block;
    padding: 3px 20px;
    clear: both;
    font-weight: normal;
    line-height: 1.428571429;
    color: #999;
    white-space: normal;
}
.mega-dropdown-menu > li ul > li > a:hover, .mega-dropdown-menu > li ul > li > a:focus {
    text-decoration: none;
    color: #444;
    background-color: #f5f5f5;
}
.mega-dropdown-menu .dropdown-header {
    color: #428bca;
    font-size: 18px;
    font-weight:bold;
}
.mega-dropdown-menu form {
    margin:3px 20px;
}
.mega-dropdown-menu .form-group {
    margin-bottom: 3px;
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Are there any jQuery plugins available that can display a loader image while a page is loading?

After extensive research on Google, I have been unable to find the plugin I need. If you are aware of any suitable plugins, please let me know. Thank you in advance! ...

Is there a way to iterate through indexed variables in javascript?

After receiving an array of data from a JQuery .ajax function, I noticed that the fields in the array are named and numbered like part1, part2, part3, etc. I attempted to loop through this data using the code below, but unfortunately, it resulted in NaN: ...

In IE8/IE9, Div does not surpass PDF but functions correctly on FF and Chrome

Is it possible to have a DIV displayed over a PDF document? This method seems to work with Firefox, but not with Internet Explorer 8 or 9. It's worth noting that the problem persists regardless of which PDF file is being pointed to. <html> < ...

Ensure that every line of code within the button element contains all the required attributes

Struggling to get the underline on every section of my button. Attempted utilizing the -webkit-box-decoration-break property, but unfortunately it was unsuccessful. https://i.sstatic.net/jsGeQ.png It is necessary for both the initial line (New Delhi,) an ...

Ways to determine if an object has a provided attribute?

As I work on creating a small website using django, I encountered an issue: In my site, I want to view posts in detail, but not every post includes an image attribute - leading to errors when trying to display images that do not exist. The solution lies ...

Is there a valid substitute for using hot links with images?

Currently, I am instructing a group of individuals on the intricacies of web development with a specific focus on AngularJS. As part of an exercise that I designed for them, they are required to fetch data from the freely accessible pokeapi.co. One interes ...

Adjusting the image placement within a modal window (using bootstrap 3)

Behold, an example modal: <!-- Large Modal --> <div class="modal fade bs-example-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel"> <div class="modal-dialog modal-lg"> <div class="modal-content"> ...

Change the position of an array element when displayed on an HTML page

I'm trying to figure out a way to manipulate the position of an HTML element that is stored inside an array. The issue I am facing is that my code generates a new div every time a specific function is called, and this div has a class applied to it for ...

Display all elements that come before and after the current element

For debugging purposes, I need to output the IDs of all previous images in a check. The issue arises when trying to assign classes to all previous elements using the script below, as the images are not being added to the correct classes. $(document).on(&a ...

What is the best way to design a footer that remains fixed at the bottom of the screen but becomes unfixed when the user scrolls down?

Currently, I am working on creating a footer that remains fixed at the bottom of the user's screen regardless of the screen size. However, I also want the header to transition from a fixed position to being part of the page when the user scrolls down. ...

Adjust the color of the navbar only after a user scrolls, with a slight delay rather than

My code changes the navbar colors when I scroll (200ms). However, I would like the changes to occur when I am slightly above the next section, not immediately. In other words, what adjustments should I make to change the color in the next section and not ...

The length of the LinearProgress bar does not match the length of the navbar

Utilizing the LinearProgress component from Material UI, I created a customized ColoredLinearProgress to alter its color: import React, { Component } from 'react'; import { withStyles } from '@material-ui/core/styles'; import { LinearP ...

JS selection-dropbox

As someone who is relatively new to JS, I am struggling a bit. The goal of the code is to display items with specific content (ALL, A, B, C). While the code works fine with buttons, I can't seem to get it to work with a 'Dropdown-select', ...

selection menu and advancement gauge

While working on my code, I have a task where I need to make the progress bar move a specific amount when a name is clicked based on the option's value. <!DOCTYPE html> <html> <head> <title>testinggg</title> &l ...

Is it possible to loop through a subset of a collection using *ngFor?

Is it possible to iterate through a specific range of elements in a collection using *ngFor? For instance, I have a group of checkboxes with their form control name and label specified as follows: [{id: 'c1', label: 'C1'}, ...] Assum ...

Issues with jQuery compatibility when used alongside HTML and CSS

My coding tool is flagging errors in my JavaScript file, including: -'$' usage before definition. -Incorrect spacing between 'function' and '(' This is the content of my JS file: $(document).ready(function() { $(window).s ...

Is it possible to create a hyperlink in the <button> element?

Having been immersed in HTML5 for quite a while now, I recently encountered a challenge while working on my login/register page project. I wanted to create a button that would redirect me to another HTML page upon clicking. While I am familiar with the < ...

Presentation and selection list

Here is the CSS code I am using: .nav li a { background-color:#000; color:#fff; text-decoration:none; padding:10px 15px; display:block; } .nav > li { float:left; } .nav li a:hover { background-color:#4db4fa; } .nav li ul { ...

Setting a background image in vanilla-extract/css is a straightforward process that can instantly enhance

I am brand new to using vanilla-extract/CSS and I have a rather straightforward question. I am attempting to apply a background image to the body of my HTML using vanilla-extract, but I am encountering issues as I keep getting a "failed to compile" error. ...

Efficiently update a multi-step form using Ajax and jQuery by adding new content without needing to reload the

Is it possible to create a multistep form on a single page without reloading the div with content from a PHP file, but instead appending it below? Here is my current progress: $(document).on('submit', '#reg-form', function(){ var ln = ...