TapeGun007 Posted February 17, 2017 Share Posted February 17, 2017 (edited) I think I'm not googling the right phrase so I can't seem to find the right answer. I'm not super great with CSS especially when it comes to drop down menus. I usually spend time on the back end of a website, not the front end. Here is my CSS: /***** Begin Menu CSS *****/ ul { width: 100%; list-style-type: none; margin: 0; padding: 0; overflow: hidden; background-color: #333; } li { float: left; } li a, .dropbtn{ display: inline-block; font-size: 15px; color: white; text-align: center; padding: 14px 16px; text-decoration: none; border-right: 1px solid #bbb; } /* Color of the main menu text when hovering */ li a:hover { background-color: red; } /* Once the mouse has moved off the main menu button and is now highlighting a sub menu button, this defines what that main menu button color is */ .dropdown:hover{ background-color: red; } /* Color of main menu button when not selected */ .dropbtn { background-color: 333; } li .dropdown { position:relative; display: inline-block; } li:last-child { border-right: none; } .dropdown-content{ display: none; position: absolute; background-color: #f9f9f9; min-width: 160px; box-shadow: 5px 7px 5px 0px rgba(0,0,0,0.2); z-index: 1; } /* Links inside the dropdown */ .dropdown-content a{ color: black; padding: 12px 16px; text-decoration: none; display: block; text-align: left; background-color: #f6f6f6; /* Sets background color of the drop down menu (not selected) */ } /* Change color of dropdown links on hover */ .dropdown-content a:hover {background-color: #ccc} .dropdown:hover .dropdown-content{ display: block; } /* I have no idea what this does as it appears nothing... li a:hover:not(.active) { background-color: #blue; } */ .active { background-color: #990000; } .active dropdown-content{ display: none; position: absolute; min-width: 160px; box-shadow: 5px 7px 5px 0px rgba(0,0,0,0.2); z-index: 1; } .active dropdown-content a{ color: black; padding: 12px 16px; text-decoration: none; display: block; text-align: left; } /***** End Menu CSS *****/ And here is the HTML: (PHP Function) function Active($menuselection, $page){ if($page == "$menuselection"){ echo "active"; }else{ echo "dropdown"; } } (HTML) <table width="100%"> <tr> <td> <ul> <li> <a class="<?=Active("menu.php", $webpage); ?>" href="menu.php">Home</a> </li> <li class="<?=Active("tms.php", $webpage); ?>"> <a href="javascript:void(0)" class="dropbtn">Territory Manager</a> <div class="dropdown-content"> <a href="#">Add TM</a> <a href="search.php?search=TM">Search TM</a> </div> </li> <li class="<?=Active("sales.php", $webpage); ?>"> <a href="javascript:void(0)" class="dropbtn">Sales</a> <div class="dropdown-content"> <a href="#">Add Sales Person</a> <a href="search.php?search=sales">Search Sales</a> </div> </li> <li class="<?=Active("drivers.php", $webpage); ?>"> <a href="drivers.php" class="dropbtn">Drivers</a> <div class="dropdown-content"> <a href="#">Add Driver</a> <a href="drivers.php">Search Drivers</a> </div> </li> <li class="<?=Active("passengers.php", $webpage); ?>"> <a href="javascript:void(0)" class="dropbtn">Passengers</a> <div class="dropdown-content"> <a href="#">Add Passenger</a> <a href="search.php?search=passengers">Search Passengers</a> </div> </li> </ul> </td> </tr> </table> So... the drop down menu works wonderfully except for one thing... if I were to click on "Drivers" for example, now that it is actively selected... the drop down menu is now gone so I cannot select "Add Driver" or "Search Drivers". I just cannot seem to figure out why I cannot get the drop to work on a menu item that is selected. Any help would be greatly appreciated. EDIT By Psycho: Wrapped HTML within code tags Edited March 8, 2017 by Psycho Quote Link to comment Share on other sites More sharing options...
Psycho Posted March 8, 2017 Share Posted March 8, 2017 The CSS class name 'dropdown' is what applies the properties to make the functionality happen. However, your logic is either applying THAT class or the other class 'active'. The active class does not have the applicable properties to make that functionality happen. The easiest solution is to always use the 'dropdown' class and ADD the active class when needed. Also, you are making this more difficult than needed by reproducing code for the elements. Create an array with the links needed and create them dynamically. Quote Link to comment Share on other sites More sharing options...
Psycho Posted March 8, 2017 Share Posted March 8, 2017 OK, the code below will fix your problem and make the code easier to maintain and ensure consistency. However, the 'Active' class is being applied to the LI element and is not 'doing' anything because the colors you see are due to styles applied from the to the anchor elements - not the LI elements. You can fix that by changing the 'active' definition in the CSS to this. li.active a { background-color: #990000; } Then change the PHP code to define an array for the menu items and a function to generate the menu HTML content as follows //definition of available menu $menuLinks = array( 'Home' => array( 'href' => 'menu.php' ), 'Territory Manager' => array( 'href' => 'tms.php', 'children' => array ( 'Add TM' => '#', 'Search TM' => 'search.php?search=TM' ), ), 'Sales' => array( 'href' => 'sales.php', 'children' => array ( 'Add Sales Person' => '#', 'Search Sales' => 'search.php?search=sales' ), ), 'Drivers' => array( 'href' => 'drivers.php', 'children' => array ( 'Add Driver' => '#', 'Search Drivers' => 'drivers.php' ), ), 'Passengers' => array( 'href' => 'passengers.php', 'children' => array ( 'Add Passenger' => '#', 'Search Passengers' => 'search.php?search=passengers' ) ) ); //Function to create html content for menu function createMenu($menuLinks, $webpage=false) { $menuLinksHtml = ''; foreach($menuLinks as $parentLabel => $parentLink) { //Determine link if parent is active or not $active = ($webpage == $parentLink['href']) ? ' active' : ''; $menuLinksHtml .= "<li class=\"dropdown{$active}\">\n"; //Determine if parent link has children if(!isset($parentLink['children'])) { //No child elements $menuLinksHtml .= "<a href='{$parentLink['href']}'>{$parentLabel}</a>\n"; } else { //Has child elements $menuLinksHtml .= "<a href=\"javascript:void(0)\" class=\"dropbtn\">{$parentLabel}</a>"; $menuLinksHtml .= "<div class=\"dropdown-content\">\n"; foreach($parentLink['children'] as $childLabel => $childLink) { $menuLinksHtml .= "<a href=\"{$childLink}\">{$childLabel}</a>\n"; } $menuLinksHtml .= "</div>\n"; } $menuLinksHtml .= "</li>\n"; } //Return HTML content return $menuLinksHtml; } Now you can change the menu by just changing the array. Lastly, change the HTML to just this <ul> <?php echo createMenu($menuLinks, $webpage); ?> </ul> No need to create a table (that's so 1980's). If needed you could wrap it in a div. 1 Quote Link to comment Share on other sites More sharing options...
TapeGun007 Posted March 8, 2017 Author Share Posted March 8, 2017 (edited) Thanks for the reply Psycho. I am not good with CSS, so while I understand what you are saying I do not know how to apply it. I am guessing you mean I need something like this? .active:hover .dropdown-content{ position: relative; display: block; } Now that DOES give me a "drop down" on the selected item, but not correctly. I'll have to keep reading and see how to fix, but at least you got me on the right track! What I completely do not understand is when you said: Create an array with the links needed and create them dynamically. Edited March 8, 2017 by TapeGun007 Quote Link to comment Share on other sites More sharing options...
TapeGun007 Posted March 8, 2017 Author Share Posted March 8, 2017 Oh sorry, I didn't know another reply was coming... now I see the explanation. Quote Link to comment Share on other sites More sharing options...
TapeGun007 Posted March 8, 2017 Author Share Posted March 8, 2017 Wow Psycho... I wasn't asking for all that, but this is certainly eye opening on a way better method of generating a simple menu. Yes, HTML tables are old hat, but I was just trying to better learn CSS, so I wasn't focused too much on that. My only frustration with building "tables" using <div> and CSS is there seems to be no replacement of "colspan" or "rowspan" (that I can find anyway). I put all of this into a testcss.php file exactly as you have it above and it works fine except the highlight of the selected menu item. I set "Home" to this: $menuLinks = array( 'Home' => array( 'href' => 'testcss.php' ), So when I click home it's not highlighted in the dark red. In my HTML I just put the additional CSS in a style tag: <!DOCTYPE HTML> <html> <head> <link rel="stylesheet" type="text/css" href="css/rs.css"> </head> <style> li.active a { background-color: #990000; } </style> <body> I also put it at the end of the css file actually just now. Quote Link to comment Share on other sites More sharing options...
Solution Psycho Posted March 8, 2017 Solution Share Posted March 8, 2017 (edited) OK, I gave you a lot of information, so let's take it one step at a time. 1. Your main problem was that the function Active() was either applying the 'dropdown' class OR the 'active' class. The dropdown class is the one that applied the styles which create the dropdown affect. So, if you only apply the 'Active' class you lose the dropdown affect. You can apply multiple classes to the same element by separating them with spaces. So, you want to always apply the 'dropdown' class to all of the relevant element and add the 'active' class only to the one where it applies. 2. Even if you were to properly apply the classes per #1 (Inactive class="dropdown" or Active class="dropdown active"), the definition for the 'active' class would do nothing because it is applied to the <li> element. The background colors you are seeing are due to styles applied to the anchor tags (<a></a>) not the <li> tags. That can be easily fixed, by changing the definition for active in the stylesheet to: li.active a { background-color: #990000; } What that means is for any <li> elements with the 'active' class, find any anchors (<a></a>) and apply the formatting. Those two things alone will directly fix your problem. But, your HTML follows a predictable format. Rather than copy/paste code and change labels, hrefs, etc. - create the content with a function. That way you know you won't have any copy/paste errors. This is especially helpful when you need to make changes to the format. So, I suggest creating an array that defines the menu (the parent links and the child links), then creating a function to produce the HTML output. This way you can easily add/edit/modify the menu links by just changing the array - which you can use as an include file. You would not have to modify core code to change the menu. Or, if you want to change the menu structure you just need to change the function. So, I provided an array for the current menu items you had as well as a function to create the menu - as well as fix the above issues. Here is a working script with all the pieces <?php //hardcoded $webpage value for testing purposes $webpage = "drivers.php"; //definition of available menu $menuLinks = array( 'Home' => array( 'href' => 'menu.php' ), 'Territory Manager' => array( 'href' => 'tms.php', 'children' => array ( 'Add TM' => '#', 'Search TM' => 'search.php?search=TM' ), ), 'Sales' => array( 'href' => 'sales.php', 'children' => array ( 'Add Sales Person' => '#', 'Search Sales' => 'search.php?search=sales' ), ), 'Drivers' => array( 'href' => 'drivers.php', 'children' => array ( 'Add Driver' => '#', 'Search Drivers' => 'drivers.php' ), ), 'Passengers' => array( 'href' => 'passengers.php', 'children' => array ( 'Add Passenger' => '#', 'Search Passengers' => 'search.php?search=passengers' ) ) ); //Function to create html content for menu function createMenu($menuLinks, $webpage=false) { $menuLinksHtml = ''; foreach($menuLinks as $parentLabel => $parentLink) { //Determine link if parent is active or not $active = ($webpage == $parentLink['href']) ? ' active' : ''; $menuLinksHtml .= "<li class=\"dropdown{$active}\">\n"; //Determine if parent link has children if(!isset($parentLink['children'])) { //No child elements $menuLinksHtml .= "<a href='{$parentLink['href']}'>{$parentLabel}</a>\n"; } else { //Has child elements $menuLinksHtml .= "<a href=\"javascript:void(0)\" class=\"dropbtn\">{$parentLabel}</a>"; $menuLinksHtml .= "<div class=\"dropdown-content\">\n"; foreach($parentLink['children'] as $childLabel => $childLink) { $menuLinksHtml .= "<a href=\"{$childLink}\">{$childLabel}</a>\n"; } $menuLinksHtml .= "</div>\n"; } $menuLinksHtml .= "</li>\n"; } //Return HTML content return $menuLinksHtml; } ?> <html> <head> <style> /***** Begin Menu CSS *****/ ul { width: 100%; list-style-type: none; margin: 0; padding: 0; overflow: hidden; background-color: #333; } li { float: left; } li a, .dropbtn{ display: inline-block; font-size: 15px; color: white; text-align: center; padding: 14px 16px; text-decoration: none; border-right: 1px solid #bbb; } /* Color of the main menu text when hovering */ li a:hover { background-color: red; } /* Once the mouse has moved off the main menu button and is now highlighting a sub menu button, this defines what that main menu button color is */ .dropdown:hover{ background-color: red; } /* Color of main menu button when not selected */ .dropbtn { background-color: 333; } li .dropdown { position:relative; display: inline-block; } li:last-child { border-right: none; } .dropdown-content{ display: none; position: absolute; background-color: #f9f9f9; min-width: 160px; box-shadow: 5px 7px 5px 0px rgba(0,0,0,0.2); z-index: 1; } /* Links inside the dropdown */ .dropdown-content a{ color: black; padding: 12px 16px; text-decoration: none; display: block; text-align: left; background-color: #f6f6f6; /* Sets background color of the drop down menu (not selected) */ } /* Change color of dropdown links on hover */ .dropdown-content a:hover {background-color: #ccc} .dropdown:hover .dropdown-content{ display: block; } /* I have no idea what this does as it appears nothing... li a:hover:not(.active) { background-color: #blue; } */ li.active a { background-color: #990000; } .active dropdown-content{ display: none; position: absolute; min-width: 160px; box-shadow: 5px 7px 5px 0px rgba(0,0,0,0.2); z-index: 1; } .active dropdown-content a{ color: black; padding: 12px 16px; text-decoration: none; display: block; text-align: left; } /***** End Menu CSS *****/ </style> </head> <body> <ul> <?php echo createMenu($menuLinks, $webpage); ?> </ul> </body> </html> EDIT: Removed the Active() function that is not used in my code. Edited March 8, 2017 by Psycho 1 Quote Link to comment Share on other sites More sharing options...
TapeGun007 Posted March 8, 2017 Author Share Posted March 8, 2017 Ah nevermind, I'm dumb. <?php echo createMenu($menuLinks, "testcss.php"); ?> Thank you so very much Psycho, this is awesome! Quote Link to comment Share on other sites More sharing options...
Psycho Posted March 8, 2017 Share Posted March 8, 2017 (edited) I put all of this into a testcss.php file exactly as you have it above and it works fine except the highlight of the selected menu item. I set "Home" to this: $menuLinks = array( 'Home' => array( 'href' => 'testcss.php' ), So when I click home it's not highlighted in the dark red. Then that means $webpage does not equal 'testcss.php'. I don't know how you are defining that variable. But, if you use the working example I posted above - you can set $webpage to the href value of an element in the array it will be shown as selected. So, you need to look at how you are defining $webpage. EDIT: In the createMenu() function, I defined the second parameter with a default value so it is not required. Depending on how $webpage is defined, it may not "known" which page you are on when it first loads (?). If so, you can define the default value in the function parameter to match the href for the home link. Edited March 8, 2017 by Psycho Quote Link to comment Share on other sites More sharing options...
Psycho Posted March 8, 2017 Share Posted March 8, 2017 (edited) I just found a problem. Changing the 'active' class definition above applied the dark red background to ALL the anchors in that group - even the child elements. Use this instead to only apply it to the parent element (which will have the dropbtn class) li.active a.dropbtn { background-color: #990000; } Edited March 8, 2017 by Psycho Quote Link to comment Share on other sites More sharing options...
TapeGun007 Posted March 8, 2017 Author Share Posted March 8, 2017 (edited) Yeah, I had noticed and was trying to find the issue. But drop down box of the selected item is still dark red (background) even with that. The background of a the active item drop down should be #f6f6f6 (or whatever other color). Edited March 8, 2017 by TapeGun007 Quote Link to comment Share on other sites More sharing options...
Psycho Posted March 8, 2017 Share Posted March 8, 2017 Yeah, I had noticed and was trying to find the issue. But drop down box of the selected item is still dark red (background) even with that. The background of a the active item drop down should be #f6f6f6 (or whatever other color). OK, so you want the "active' element to turn bright red (like the inactive elements) when hovered over? Quote Link to comment Share on other sites More sharing options...
TapeGun007 Posted March 8, 2017 Author Share Posted March 8, 2017 (edited) So that background color on the drop down which is the same as the background of "Drivers" is a bit hard on the eyeballs. Edited March 8, 2017 by TapeGun007 Quote Link to comment Share on other sites More sharing options...
Psycho Posted March 9, 2017 Share Posted March 9, 2017 The modification I posted two responses up should fix that. I was looking at the CSS and it could do with some clean-up, but I'm not the best person for that. Quote Link to comment Share on other sites More sharing options...
TapeGun007 Posted March 9, 2017 Author Share Posted March 9, 2017 li.active a.dropbtn { background-color: #f6f6f6; /* This set the background of the actively selected top menu item */ } What that does is makes the word "Driver" on the main menu turn to a light gray. But it doesn't change the background color of the drop down box. Quote Link to comment Share on other sites More sharing options...
Psycho Posted March 9, 2017 Share Posted March 9, 2017 I guess I'm a little confused over why you changed the color of that property to gray. I thought you wanted the selected parent to be dark-red and the drop-down items to be gray. The change I made to the selector is to only apply the properties to the active' anchor tags with the dropbtn class - which would only be the parent item. When doing that I get the result below. Is that what you want? Quote Link to comment Share on other sites More sharing options...
TapeGun007 Posted March 9, 2017 Author Share Posted March 9, 2017 That's very odd. Your picture is exactly how I would like it to look, but on my screen... it's like the picture above (minus the dark red Home button). Can you re-post your entire page code? I did go into Chrome and completely delete all cached files and such just to be sure. Quote Link to comment Share on other sites More sharing options...
Psycho Posted March 10, 2017 Share Posted March 10, 2017 I used the EXACT same example page that I posted in post #7 with the change I provided on post #10. But, the snippet you posted on post #10 had changed the color. This is what I posted: li.active a.dropbtn { background-color: #990000; } This is what you posted li.active a.dropbtn { background-color: #f6f6f6; /* This set the background of the actively selected top menu item */} Change it back. Quote Link to comment Share on other sites More sharing options...
TapeGun007 Posted March 10, 2017 Author Share Posted March 10, 2017 (edited) Hi Psycho, I already changed the color back to #99000 (I was just testing to see what that did). This is not the issue. The *ONLY* difference between your picture and my picture is that under the "drivers" menu option (set to active), you have a background of #f6f6f6 (for "add driver" and "search drivers") and I have background color of #99000. This is what I'm trying to understand. I thought maybe it was a browser issue, but I tried this in Chrome, Firefox, and Edge all with the same result. Here is my entire code: <?php //definition of available menu $menuLinks = array( 'Home' => array( 'href' => 'Home.php' ), 'Territory Manager' => array( 'href' => 'tms.php', 'children' => array ( 'Add TM' => '#', 'Search TM' => 'search.php?search=TM' ), ), 'Sales' => array( 'href' => 'sales.php', 'children' => array ( 'Add Sales Person' => '#', 'Search Sales' => 'search.php?search=sales' ), ), 'Drivers' => array( 'href' => 'testcss.php', 'children' => array ( 'Add Driver' => '#', 'Search Drivers' => 'testcss.php' ), ), 'Passengers' => array( 'href' => 'passengers.php', 'children' => array ( 'Add Passenger' => '#', 'Search Passengers' => 'search.php?search=passengers' ) ) ); //Function to create html content for menu function createMenu($menuLinks, $webpage=false) { $menuLinksHtml = ''; foreach($menuLinks as $parentLabel => $parentLink) { //Determine link if parent is active or not $active = ($webpage == $parentLink['href']) ? ' active' : ''; $menuLinksHtml .= "<li class=\"dropdown{$active}\">\n"; //Determine if parent link has children if(!isset($parentLink['children'])) { //No child elements $menuLinksHtml .= "<a href='{$parentLink['href']}'>{$parentLabel}</a>\n"; } else { //Has child elements $menuLinksHtml .= "<a href=\"javascript:void(0)\" class=\"dropbtn\">{$parentLabel}</a>"; $menuLinksHtml .= "<div class=\"dropdown-content\">\n"; foreach($parentLink['children'] as $childLabel => $childLink) { $menuLinksHtml .= "<a href=\"{$childLink}\">{$childLabel}</a>\n"; } $menuLinksHtml .= "</div>\n"; } $menuLinksHtml .= "</li>\n"; } //Return HTML content return $menuLinksHtml; } ?> <!DOCTYPE HTML> <html> <head> <!-- <link rel="stylesheet" type="text/css" href="components/css/rs.css"> --> <style> /***** Begin Menu CSS *****/ ul { width: 100%; list-style-type: none; margin: 0; padding: 0; overflow: hidden; background-color: #333; } li { float: left; } li a, .dropbtn{ display: inline-block; font-size: 15px; color: white; text-align: center; padding: 14px 16px; text-decoration: none; border-right: 1px solid #bbb; } /* Color of the main menu text when hovering */ li a:hover { background-color: red; } /* Once the mouse has moved off the main menu button and is now highlighting a sub menu button, this defines what that main menu button color is */ .dropdown:hover{ background-color: red; } /* Color of main menu button when not selected */ .dropbtn { background-color: 333; } li .dropdown { position:relative; display: inline-block; } li:last-child { border-right: none; } .dropdown-content{ display: none; position: absolute; background-color: #f9f9f9; min-width: 160px; box-shadow: 5px 7px 5px 0px rgba(0,0,0,0.2); z-index: 1; } /* Links inside the dropdown */ .dropdown-content a{ color: black; padding: 12px 16px; text-decoration: none; display: block; text-align: left; background-color: #f6f6f6; /* Sets background color of the drop down menu (not selected) */ } /* Change color of dropdown links on hover */ .dropdown-content a:hover {background-color: #ccc} .dropdown:hover .dropdown-content{ display: block; } /* I have no idea what this does as it appears nothing... li a:hover:not(.active) { background-color: #blue; } */ li.active a { background-color: #990000; } .active dropdown-content{ display: none; position: absolute; min-width: 160px; box-shadow: 5px 7px 5px 0px rgba(0,0,0,0.2); z-index: 1; } .active dropdown-content a{ color: black; padding: 12px 16px; text-decoration: none; display: block; text-align: left; } li.active a.dropbtn { background-color: #990000; } /***** End Menu CSS *****/ </style> </head> <body> <ul> <?php echo createMenu($menuLinks, "testcss.php"); ?> </ul> </body> </html> Edited March 10, 2017 by TapeGun007 Quote Link to comment Share on other sites More sharing options...
Psycho Posted March 10, 2017 Share Posted March 10, 2017 (edited) OK, here's the problem (I'll take some of the blame). In post #10 I stated (emphasis added) Changing the 'active' class definition above applied the dark red background to ALL the anchors in that group - even the child elements. Use this instead . . . I meant for you to change/replace the existing definition for the 'active' class. Instead you added a new definition. So, the original definition that applied styles to the drop-down elements was still applicable. Here is part of what you just posted li.active a { <!-- is applied to ALL 'a' elements in the 'active' section --> background-color: #990000; } .active dropdown-content{ display: none; position: absolute; min-width: 160px; box-shadow: 5px 7px 5px 0px rgba(0,0,0,0.2); z-index: 1; } .active dropdown-content a{ color: black; padding: 12px 16px; text-decoration: none; display: block; text-align: left; } li.active a.dropbtn { <!-- applied to ONLY the 'a' element with the 'dropbtn' class in active section --> background-color: #990000; } That last one should replace the first one. Edited March 10, 2017 by Psycho Quote Link to comment Share on other sites More sharing options...
TapeGun007 Posted March 11, 2017 Author Share Posted March 11, 2017 (edited) Ah. Dadgum it, I really worked hard trying to figure out the error on my own. Now I understand. I had thought about that, but what I also misunderstood is that the last CSS code always overwrites the first CSS code... which apparently is NOT true. But yes, that fixed it, and I'm very grateful for all your help!!!! I feel like you really went the extra mile on this.. and it's very much appreciated. Edited March 11, 2017 by TapeGun007 Quote Link to comment Share on other sites More sharing options...
Psycho Posted March 13, 2017 Share Posted March 13, 2017 I had thought about that, but what I also misunderstood is that the last CSS code always overwrites the first CSS code... which apparently is NOT true. No, that is true. But the first definition was for a larger group, whereas the second definition was for a smaller group. As an analogy, you might say all dogs will have a blue collar and then all Labradors will have a red collar. Any dog that is not a Labrador will have a blue collar. The second definition (which is more specific) has no impact on the non-Labrador dogs. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.