Unable to identify mobile navbar problem

I;ve tried to create a mobile navbar (hamburger) but it’s not working properly.

For some reason the mobile navbar is displaying “About Eco Bunny” on the index page and the hamburger button appears to not work.

Here is the html code for the navbar. In fareness, I have tried to adapt code from W3).


<div class="topnav" id="myTopnav">
 
  <div class="dropdown">
    <button class="dropbtn">EPC and Retrofit info 
      <i class="fa fa-caret-down"></i>
    </button>
    <div class="dropdown-content">
      <a href="EPC-details-eco-bunny.html">Information about EPCs</a>
      <a href="retrofit-assessment-eco-bunny.html">Information About Retrofit Assessments</a>
     <!-- <a href="#">Link 3</a> -->
    </div>
  </div> 
  <div class="dropdown">
    <button class="dropbtn">Prices and Book
      <i class="fa fa-caret-down"></i>
    </button>
    <div class="dropdown-content">
      <a href="book-EPC-eco-bunny.html">EPC - Energy Proficiency Certificate</a>
      <a href="book-Retrofit-assesment">Retrofit Assessment</a>
      </div>
  

  <div class="dropdown">
          <a href="about-eco-bunny.html">About Eco Bunny</a>
          <a href="contact">Contact Us</a>
     </div>
    </div>

  <a href="javascript:void(0);" style="font-size:15px;" class="icon" onclick="myFunction()">&#9776;</a>
</div>
</div>

Here is the css code for mobiles (nav works fine on my laptop -full screen).

@media screen and (max-width: 600px) {
    
    .grid-item1  img {
      display: none;
    }
    
    .grid-item2 img{
      display: none;
    }

    .logo img {
      position: absolute;
      top: 15px;
      margin: auto;
      
    }

    .grid-container {
      display: grid;
      grid-template-columns: 20% 80%;
      grid-template-rows: 100px;
      /*height: 170px; */
     gap: 5px; 
    /* background-color: rgba(255,90,205,0.1); */
      
     
    }
   
    .topnav a:not(:first-child), .dropdown .dropbtn {
      display: none;
    }
    .topnav a.icon {
      float: right;
      display: block;
      z-index: 1;
    }
  }
  
  @media screen and (min-width: 600px) {

   .logo img {
    display: none;
   } 
        
    .topnav.responsive {position: relative;}
    .topnav.responsive .icon {
    /*  position: absolute; */
      right: 0;
      top: 0;
      z-index: 1;

    }
    .topnav.responsive a {
      float: none;
      display: block;
      text-align: left;
    }
    .topnav.responsive .dropdown {float: none;}
    .topnav.responsive .dropdown-content {position: relative;}
    .topnav.responsive .dropdown .dropbtn {
    display: block;
      width: 90%;
      text-align: left;
      margin: auto;
    } 
  }
@media screen and (max-width: 600px) {
    
    .grid-item1  img {
      display: none;
    }
    
    .grid-item2 img{
      display: none;
    }

    .logo img {
      position: absolute;
      top: 15px;
      margin: auto;
      
    }

    .grid-container {
      display: grid;
      grid-template-columns: 20% 80%;
      grid-template-rows: 100px;
      /*height: 170px; */
     gap: 5px; 
    /* background-color: rgba(255,90,205,0.1); */
      
     
    }
   
    .topnav a:not(:first-child), .dropdown .dropbtn {
      display: none;
    }
    .topnav a.icon {
      float: right;
      display: block;
      z-index: 1;
    }
  }
  
  @media screen and (min-width: 600px) {

   .logo img {
    display: none;
   } 
        
    .topnav.responsive {position: relative;}
    .topnav.responsive .icon {
    /*  position: absolute; */
      right: 0;
      top: 0;
      z-index: 1;

    }
    .topnav.responsive a {
      float: none;
      display: block;
      text-align: left;
    }
    .topnav.responsive .dropdown {float: none;}
    .topnav.responsive .dropdown-content {position: relative;}
    .topnav.responsive .dropdown .dropbtn {
    display: block;
      width: 90%;
      text-align: left;
      margin: auto;
    } 
  }
  

here is the url

Can you let me know what I need to do to correct this?

There are a couple of things to consider to make this work.

Firstly in your small screen media query you should hide all the elements in that nav that you don’t want anyone to see. I assume all you want is the hamburger menu showing and nothing else so in the media query you would hide the elements called dropdown (you can set them to display:none for now but if you want animation when shown another hiding method would be required).

Your JS is working and adding a class of .responsive to the element called #myTopnav. You should be using this class to display the menu in a format suitable for small screens.

So imagine you had hidden the dropdown in your small screen media query like this:

.dropdown{
display:none;
}

Then you click the hamburger and a class of responsive is added to the topnav like this.

<div class="topnav responsive" id="myTopnav">

You then use that class in your small screen media query to reveal the menu.

e.g.

.responsive .dropdown{
display:block;
}

The dropdown menu items will now be shown but of course you won’t see them all as you now have to change their design to fit the new smaller screen size and linearize each item rather than floating them next to each other.

Importantly to note that hover doesn’t really work on mobile so you will have to display the sub menus by default as mobile users will be unable to use them if you don’t show them.

You will also then need to decide that when the menu opens does it push the rest of the page downwards (which is disconcerting) or instead let the open menu slide on top of the content below so there is no page jump.

Also consider making the hamburger bar sticky at the top of the viewport or the user will have to scroll all the way up to use the menu again.

If that makes sense and you can confirm the approach you require I can point some code your way :slight_smile:

Firstly though you need to fix the html for the nav as you have mismatched the tags and the drop downs are being activated on the wrong items.

This is what happens when hovering on the non dropdown buttons;


(Apart from the fact that everything overlaps on my screen which will also need to be addressed at some time)

The html for your topnav should be this:

<div class="topnav" id="myTopnav">
  <div class="dropdown">
    <button class="dropbtn">EPC and Retrofit info
      <i class="fa fa-caret-down"></i>
    </button>
    <div class="dropdown-content">
      <a href="EPC-details-eco-bunny.html">Information about EPCs</a>
      <a href="retrofit-assessment-eco-bunny.html">Information About Retrofit Assessments</a>
      <!-- <a href="#">Link 3</a> -->
    </div>
  </div>
  <div class="dropdown">
    <button class="dropbtn">Prices and Book
      <i class="fa fa-caret-down"></i>
    </button>
    <div class="dropdown-content">
      <a href="book-EPC-eco-bunny.html">EPC - Energy Proficiency Certificate</a>
      <a href="book-Retrofit-assesment">Retrofit Assessment</a>
    </div>
  </div>
  <div class="dropdown">
    <a href="about-eco-bunny.html">About Eco Bunny</a>
    <a href="contact">Contact Us</a>
  </div>
  <a href="javascript:void(0);" style="font-size:15px;" class="icon" onclick="myFunction()">&#9776;</a>
</div>

Now the menu itself will work properly on large screens (but elements will still overlap as that is a responsive issue).

Also I note that you are linking to 2 css files

<link rel="stylesheet" href="[2drops.css](https://ecobunny.co.uk/2drops.css)">
<link rel="stylesheet" href="[index-3.css](https://ecobunny.co.uk/index-3.css)">

In both those files you have mixed styles for the elements so it means you can’t alter the code for the nav without adjusting the code in both those files. It’s a nightmare to maintain and you should have the code in one place. If you want all your nav code separate hen keep it separate and don’t mix it between different files.

You have done similar for the body styles.

e.g.

This is in the dropcss file:

/*2drop.css */
body {
  font-family: "Roboto", sans-serif;
  font-size: 1.25rem;
  max-width: 80%;
  margin: auto;
}

However it will never be used as you have over-ridden it in the index-3.css file here:


/* index-3.css */
body {
  /* background: linear-gradient(#EA7E6A, #FF5ACD);*/
  font-family: "Roboto", sans-serif;
  font-size: 0.75rem;
  background: rgba(255, 90, 205, 0.1);
  padding-bottom: 1.5rem;
  max-width: 80%;
  margin: auto;
}

If there is any lesson that I can offer that will save you hours of frustration it is to be consistent and structure things logically. Even for someone like me used to debugging code your page is already very awkward to manage and its only just started! No wonder you are struggling to see what’s going on :slight_smile:

Don’t tackle too many things at once and get the nav and header finished properly before moving on to other elements.

Thanks for your very helpful reply.

I will work on what you have suggested and see what I can sort out.

My problem started with my thought of once a website container and grids are set up that the website will automatically adapt for mobiles (my understanding of mobile first!). I then I decided to code the site as I wanted it.

It wasn’t until I hosted the site and checked it out that I realised that to have a responsive website isn’t as easy as that.

With regards to the 2 css files:

index-3.css is a copy of my original file for this page.
2drops.css is a file that I created to test out the mobile nav.

I decided to merge the 2 to see if they worked together. My intention was to remove unused and duplicate code from the index-3.css and then merge the two together as soon as I got them working. The idea of doing this then was that it would make it easier to change all site the pages in one step. Good ideas but the wrong timing!

My original idea for index-3 was to create one css file for the entire website. I decided that it might be more efficient to create a css file for each page. The idea being that it would be easier and quicker to load the pages. I crerated the files but as yet haven’t removed the unwanted stuff for the same reasons as above.

As my website is small, I did think of making 2 seperate navbars (mobile and full screen) but it seems that this isn’t good practice. Hence trying to make a responsive one!

1 Like

Generally the main layout css file for a smallish site is a pretty small file size and indeed is usually smaller than the cost of one actual html image in terms of file size. Therefore having separate css files for each page is not really a suitable solution. Also remember that on first visit the css file is cached so all your other pages don’t have to download anything again.

The approach I generally take is create a general css file for all pages that contains all your initial styles and reset css and all the structural styles for the common elements. Generally, header,nav and footer are consistent on all pages with only the content in the main sections changing.

If you find that you have some unique elements in a new page then you can create a separate css file for them assuming they are only used in that page. Remember though that css cascades so the order of files is important and your general css file must be first in source and avoid duplicate code creeping in

I have to go out for an hour but when I come back I’ll try and give an example of how I’d approach that header of yours just to give a slightly more structured approach for you to play with (even if you don;t use it) :slight_smile:

Remember that making mistakes is part of learning and we all make them :wink:

Ok, Here is how I would approach the header although I have used some of your html so that you know roughly where things are. Usually I would use nested lists for the drop down but I stayed with your method for the example.


(Click the Edit on codepen link to see the full page. If you create a free account at codepen you can then just click ‘fork’ and the layout stays in your collection).

Open the window larger and smaller to see the responsiveness and the hamburger will toggle the menu for small screens.

Notice how nothing breaks from small to large and nothing overlaps by accident.

If that’s of interest I’ll show a better methods for your two columns so that they don’t overlap.:wink:

This is what I see at intermediate


views:

Here are the 2 columns tidied up.

I’ve only done this quickly and haven’t validated the code yet so there are bond to be typos but the layout is displaying across all screens nicely and really only the font-size, padding and margins need to be tweaked for smaller versions.

It’s a fraction of the code you had and the html is tidied up as you had invalid structures and missing tags all over the place. Also note that the break element is only used for breaking lines of text such as in poems or addresses or form elements and is not meant to make space or define the end of a paragraph. P elements should be used for paragraphs and they will make space by defining the margins. never use a break for a layout effect or for making space as that’s not its purpose.

I don’t expect you to use my code (you can if you wish) but to learn from the techniques and try and simplify your code into more manageable chunks.:slight_smile:

Thanks for your help on this.

I changed the nav bar layout but i am getting a js script error which is preventing the mobile nav from working. I click on the hamburger, nothing happens

Uncaught TypeError TypeError: Cannot read properties of null (reading ‘addEventListener’)
at showMenu (c:\Users\tony_\OneDrive\Desktop\mobile menu\sitepen.html:18:15)
at (c:\Users\tony_\OneDrive\Desktop\mobile menu\sitepen.html:22:3)

Ihave changed the code/layout. I’ve replaced the about and contact with another drop down and the other two drop down titles.:

<nav class="topnav" id="myTopnav">
  <div class="dropdown-wrap">
    <div class="dropdown">
      <button class="dropbtn">Energy Performance certificate 
        <i class="fa fa-caret-down"></i>
      </button>
      <div class="dropdown-content">
        <a href="EPC-details-eco-bunny.html">Information about EPCs</a>
        <a href="retrofit-assessment-eco-bunny.html">Prices and Booking</a>
      </div>
    </div>
    <div class="dropdown">
      <button class="dropbtn">Retrofit Assessment
        <i class="fa fa-caret-down"></i>
      </button>
      <div class="dropdown-content">
        <a href="book-EPC-eco-bunny.html">Information about Retrofit Assessments</a>
        <a href="book-Retrofit-assesment">Prices and Booking</a>
      </div>
      </div>
      </div>
      <div class="dropdown">
        <button class="dropbtn">Eco Bunny Info
          <i class="fa fa-caret-down"></i>
        </button>
        <div class="dropdown-content">
        <a href="book-EPC-eco-bunny.html">About Eco Bunny</a>
        <a href="book-Retrofit-assesment">Contact Us</a>
      </div>
    </div>
</div>
</div>
<div class="about                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           ">
  <a class="about" href="about-eco-bunny.html">EPC Information</a>
  <a class="contact" href="contact">Retrofit Assessment</a>
</div>
  <button class="hamburger icon">&#9776;</button>
</nav>
<main class="main">

  <h1>When do you need an EPC -Energy Proficiency Certificate or<br>Retrofit Assessment and Comparison </h1>

</main>

There is another minor problem butit looks like i’ve sorted that out!

It looks like I made a mistake with including the code.

<nav class="topnav" id="myTopnav">
  <div class="dropdown-wrap">
    <div class="dropdown">
      <button class="dropbtn">Energy Performance certificate 
        <i class="fa fa-caret-down"></i>
      </button>
      <div class="dropdown-content">
        <a href="EPC-details-eco-bunny.html">Information about EPCs</a>
        <a href="retrofit-assessment-eco-bunny.html">Prices and Booking</a>
      </div>
    </div>
    <div class="dropdown">
      <button class="dropbtn">Retrofit Assessment
        <i class="fa fa-caret-down"></i>
      </button>
      <div class="dropdown-content">
        <a href="book-EPC-eco-bunny.html">Information about Retrofit Assessments</a>
        <a href="book-Retrofit-assesment">Prices and Booking</a>
      </div>
      </div>
      </div>
      <div class="dropdown">
        <button class="dropbtn">Eco Bunny Info
          <i class="fa fa-caret-down"></i>
        </button>
        <div class="dropdown-content">
        <a href="book-EPC-eco-bunny.html">About Eco Bunny</a>
        <a href="book-Retrofit-assesment">Contact Us</a>
      </div>
    </div>
</div>
</div>
<div class="about                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           ">
  <a class="about" href="about-eco-bunny.html">EPC Information &</a>
  <a class="contact" href="contact">Retrofit Assessment</a>
</div>
  <button class="hamburger icon">&#9776;</button>
</nav>
<main class="main">

  <h1>When do you need an EPC -Energy Proficiency Certificate or<br>Retrofit Assessment and Comparison </h1>

</main>```

I meant to mention this to you before **but your custom scripts need to go at the end of the html before the closing body tag. ** If you place them in the head then the script runs before the body exists and finds nothing.

Put the script here just before the closing body tag:

<script>
(function showMenu(d) {
  "use strict";

  const myHamburger = d.querySelector(".hamburger");
  const myNav = d.getElementById("myTopnav");

  myHamburger.addEventListener("click", (event) => {
    event.preventDefault();
    myNav.classList.toggle("responsive");
  });
})(document);
</script>
</body>
</html>

That is a best practice and ensures all content is loaded before the script tries to run.

I’d need to see a working version with your new css as that ‘most likely’ will change the dynamics of how the menu will work. The html you posted is not valid and you have missing and mismatched tags again, :slight_smile:

You still seem to have the about and contact links in that section except that you’ve put a div around them. That will mean they are no longer siblings in that construct so you will need to control their position and appearance form that new parent if the default is not what you wanted.

My best guess is that you want this structure:

<nav class="topnav" id="myTopnav">
  <div class="dropdown-wrap">

    <div class="dropdown">
      <button class="dropbtn">Energy Performance certificate
        <i class="fa fa-caret-down"></i>
      </button>
      <div class="dropdown-content">
        <a href="EPC-details-eco-bunny.html">Information about EPCs</a>
        <a href="retrofit-assessment-eco-bunny.html">Prices and Booking</a>
      </div>
    </div>

    <div class="dropdown">
      <button class="dropbtn">Retrofit Assessment
        <i class="fa fa-caret-down"></i>
      </button>
      <div class="dropdown-content">
        <a href="book-EPC-eco-bunny.html">Information about Retrofit Assessments</a>
        <a href="book-Retrofit-assesment">Prices and Booking</a>
      </div>
    </div>

    <div class="dropdown">
      <button class="dropbtn">Eco Bunny Info
        <i class="fa fa-caret-down"></i>
      </button>
      <div class="dropdown-content">
        <a href="book-EPC-eco-bunny.html">About Eco Bunny</a>
        <a href="book-Retrofit-assesment">Contact Us</a>
      </div>
    </div>
  </div>

  <div class="about">
    <a class="about" href="about-eco-bunny.html">EPC Information &</a>
    <a class="contact" href="contact">Retrofit Assessment</a>
  </div>

  <button class="hamburger icon">&#9776;</button>

</nav>
<main class="main">

  <h1>When do you need an EPC -Energy Proficiency Certificate or<br>Retrofit Assessment and Comparison </h1>

</main>

However as I said above you still have the about and contact links in that section albeit wrapped in a new div called about.

Important The element called dropdown-wrap is used to absolutely position the menu on smaller screens so that it overlays the content nicely. Without this wrapper controlling all those dropdowns as a whole then you won’t be able to make it work smoothly. (That’s why you must never mismatch div tags. Use a good editor and validate regularly.)

If you still can’t get it working I’ll need to see all the code for that section or a demo as before.

Thanks for your help. I’ll take a closer look this evening.

I’ve just opened a codepen account.

I’ll work through your advice this evening. If there’s any problems I’ll submit the code through codepen so that you can have a proper look. Thanks

1 Like

I’ve managed to get the top port sorted as to how I want it.

Codepen is much easier to use. The downside for me is that it doesn’t give the screen size for the output.

Hopefully codepen is here (I don’t know how to upload it )

Glad its progressing :slight_smile:

If you want to see your images in codepen then use the absolute urls to the images or instead just add the base tag href either in the settings of the codepen (or even at the to of the html).

e.g. add this:

<base href="https://ecobunny.co.uk/2drops.html">

You just paste the link to it and it will automatically show your codepen. Don’t use the editor link method just paste it as normal text and it will show up. I’ve edited your post to show it now.

Screen size is basically irrelevant. All you need do is grab the edge of your browser window and drag it down to about 320px and then up to full width. If at any point during that process the layout breaks then throw in a media query and fix it.

If you open developer tools while you drag the browser window the screen size is automatically shown to you. Also if you use developer tools you can click the responsive icon and select a number of pre-set mobile size to look at.

However most of the time just dragging the browser is enough because every day there are new devices and screen resolutions appearing, There are literally hundreds and hundreds of different device sizes so chasing pixels is a non starter. Concentrate on the design and if it breaks during the process I mentioned throw in a media query and fix it. With a few well chosen media queries you have then catered for every device now and in the future.

Be device agnostic. :slight_smile:

Near the top right corner of CodePen, click the button that is just to the right of the ‘Settings’ button. Then change to one of the other two views, but not to ‘Details View’ or to ‘Full Page View’.

change-view

As you drag the vertical dividing line, the width is shown while dragging (but you need really good eyesight!). It can be helpful to use it to check your code works satisfactorily down to 320 pixels width.

2 Likes

Thanks for the info.

I have a problem or two again:

I haven’t done any coding today but I have just visited my codpen area and checked before I do some.

There ios a problem in as much that the house photo changes sizes as I move the screen in and out. It goes below the nav bar at full stretch.I’ve attached two images so that you can see.

I noticwed that the photo goes behing the nav bar so I looked for a z-index so that I could change it. The only one that i found was the sub menu’s. I blocked this out but the photo still enlarged.

I have also tried using style="max-height 150px; max-width: auto; that didn’t work so i tried using auto for both. That sort of worked but the image was far too small on the widest view.

I did wonder if it was the photo but it is the same one with the hopback notice. I just removed the notice.

is there a way to stop the photo from enlarging or going behind the nav bar?


I’ve put the code link here in the hope that it will work

Yes, have a look at my example when something goes wrong with yours and then you can try to work out what the difference is.

This time you simply missed adding the .house class to the image.

       <img class="house" src="https://ecobunny.co.uk/house.svg" 
alt="photo of house for ecobunny.co.uk">

The css is already in place in your code.:slight_smile:

(Note that in html5 images are self closing tags and there are no backslashes needed at the end of the tag).