Why adding sticky to CSS drop down menu breaks it? - css

There are many similar examples, but none I found to deal with this issue. I'm trying to make <nav> bar with drop-down menu to be sticky. I have a <nav> bar with many menu entries, but I simplified it as much as possible to see where it breaks. There is simple example from w3schools, modified a bit, and it stops working as soon as I add position:sticky (you can see it commented out bellow)
So example code in one file for practicality is:
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-size: 28px;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
/* position: -webkit-sticky; /* Safari */
/* position: sticky; */ /* If enabled it breaks dropdown menu */
top: 0;
}
li {
float: left;
}
li a, .mDrop {
display: block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
.mDrop li:nth-of-type(-n+1) { float: down; }
.mDrop {
position: relative;
top: 13.6rem;
}
li .mDrop {
visibility: hidden;
opacity: 0;
width: 8rem;
position: absolute;
transition: all 0.5s ease;
margin-top: 1.5rem;
display: none;
}
li a:hover, .mDrop:hover .li:hover {
background-color: green;
}
li:hover > ul,
li:focus-within > ul,
li ul:hover {
visibility: visible;
opacity: 1;
display: block;
}
ul li ul li { clear: both; width: 100%; }
.active { background-color: #4CAF50; }
</style>
</head>
<body>
<div class="header">
<h2>Scroll Down</h2>
<p>Scroll down to see the sticky effect.</p>
</div>
<ul>
<li><a class="active" href="#home">Home</a></li>
<li>News
<ul class="mDrop">
<li>Drop1</li>
<li>Drop2</li>
<li>Drop3</li>
</ul>
</li>
<li>Contact</li>
<li style="float:right">Help</li>
</ul>
<h3>Sticky Navigation Bar Example</h3>
<p>The navbar will <strong>stick</strong> to the top when you reach its scroll position.</p>
<p>Some text to enable scrolling. </p>
<div style="Height:80vh"></div>
<p>Some text to enable scrolling. </p>
</body>
</html>
I've tried many different options examples and no luck. I don't want to encapsulate entire content area in separate <div>, just would like adding stickiness to working drop-down menu. I also would like solution with CSS/HTML only.
Thanks

Your dropdown is broken because you are giving position: sticky to the ul tag. Since you have two nested uls in your code, the style is applied to both of them.
<ul> <!-- first ul -->
<li><a class="active" href="#home">Home</a></li>
<li>News
<ul class="mDrop"> <!-- second ul -->
...
</ul>
</li>
...
...
</ul>
Solution
First of all, wrap your ul (navbar) in a <nav> element. Don't be afraid of "adding another div". This makes you HTML code more semantic and more readable, no need to say it's good for SEO too.
<nav class="navbar">
<ul>
<li><a class="active" href="#home">Home</a></li>
<li>News
<ul class="mDrop">
<li>Drop1</li>
<li>Drop2</li>
<li>Drop3</li>
</ul>
</li>
<li>Contact</li>
<li style="float:right">Help</li>
</ul>
</nav>
REMOVE these parts from your CSS:
ul {
position: -webkit-sticky; /* remove */
position: sticky; /* remove */
top: 0; /* remove */
}
ADD these to your CSS:
.navbar {
position: sticky;
position: -webkit-sticky;
top: 0;
}
li .mDrop {
visibility: hidden;
opacity: 0;
width: 8rem;
position: absolute;
top: 40px; /* I just added these line. Replace 40px with any value that fits your design */
transition: all 0.5s ease;
margin-top: 1.5rem;
display: none;
}
What I'm basically doing is changing how you "style" your elements. Never use "pure" or "element" selectors like (h1, h2, p, ul) unless you really want to do some general styling; for example, resetting browser default styles.
Full Code
body {
font-size: 28px;
}
.navbar {
position: -webkit-sticky; /* Safari */
position: sticky; /* If enabled it breaks dropdown menu */
top: 0;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
}
li {
float: left;
}
li a,
.mDrop {
display: block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
.mDrop li:nth-of-type(-n + 1) {
float: down;
}
.mDrop {
position: relative;
top: 13.6rem;
}
li .mDrop {
visibility: hidden;
opacity: 0;
width: 8rem;
position: absolute;
top: 40px;
transition: all 0.5s ease;
margin-top: 1.5rem;
display: none;
}
li a:hover,
.mDrop:hover .li:hover {
background-color: green;
}
li:hover > ul,
li:focus-within > ul,
li ul:hover {
visibility: visible;
opacity: 1;
display: block;
}
ul li ul li {
clear: both;
width: 100%;
}
.active {
background-color: #4caf50;
}
<body>
<div class="header">
<h2>Scroll Down</h2>
<p>Scroll down to see the sticky effect.</p>
</div>
<nav class="navbar">
<ul>
<li><a class="active" href="#home">Home</a></li>
<li>News
<ul class="mDrop">
<li>Drop1</li>
<li>Drop2</li>
<li>Drop3</li>
</ul>
</li>
<li>Contact</li>
<li style="float:right">Help</li>
</ul>
</nav>
<h3>Sticky Navigation Bar Example</h3>
<p>The navbar will <strong>stick</strong> to the top when you reach its scroll position.</p>
<p>Some text to enable scrolling. </p>
<div style="Height:80vh"></div>
<p>Some text to enable scrolling. </p>
</body>

Related

Make menu items and submenu items display vertically without covering each other up

As the first step in making my menu responsive, I want to add a media query in css to change the way the menu displays so that each list item is displayed vertically below the previous item, with it's own submenu items displayed below it before the next list item is displayed. Hope that makes sense. Here are the HTML and CSS that make the menu work in the desktop version of the site:
HTML
<nav>
<img id="logo" src="#logoUrl">
<ul>
<li class="#(CurrentPage.Url == "/" ? "current" : null)">Home</li>
#foreach (var item in menuItems)
{
<li class="#(CurrentPage.Id == item.Id ? "current" : null)">
#item.Name
#if (item.Children.Where("Visible").Any())
{
var subMenuItems = item.Children.Where("Visible");
<ul>
#foreach (var sub in subMenuItems)
{
<li>#sub.Name</li>
}
</ul>
}
</li>
}
</ul>
<br class="clear">
</nav>
(This is on Umbraco, so forgive all the Razor bits)
CSS
#logo {
float: left;
margin-right: 25px;
}
nav {
width: 100%;
height: auto;
background-color: #354a49;
}
nav > ul > li {
display: block;
position: relative;
width: auto;
height: 50px;
float: left;
font-size: 1.1em;
margin: 0px 20px 0px 20px;
padding: 15px 8px 13px 8px;
text-align: center;
}
nav ul li a {
color: #fefce9;
margin-left: auto;
margin-right: auto;
}
nav ul li a:hover {
font-style: italic;
}
nav ul ul {
display: none;
position: absolute;
top: 100%;
left: 0;
z-index: 99;
width: 200px;
}
nav ul li:hover {
border-bottom: 2px solid #fefce9;
background-color: #a1b0af;
}
nav ul li:hover > ul {
display: block;
margin-top: 2px;
}
nav ul li ul li {
display: block;
float: none;
padding: 20px 3px;
background-color: #a1b0af;
border-bottom: 2px solid #fefce9;
}
nav ul li ul li a {
color: #fefce9;
}
nav li.current {
background-color: #a1b0af;
border-bottom: 2px solid #fefce9;
}
nav li.current > a {
color: #fefce9;
font-style: italic;
}
And here is the CSS I have in my media query at the moment:
#logo {
margin-right: -50px;
}
nav > ul > li {
float: none;
margin: 0px;
}
nav ul ul {
width: 100%;
}
nav li.current {
background-color: inherit;
}
That displays the main menu items one below the other OK, but when I try to change things so that the submenu items appear between the menu items I just end up with the submenu items appearing over the top of the menu items and each other.
EDIT
Here's the rendered HTML as requested:
</nav>
<img id="logo" src="/media/1042/wshalogo.png">
<ul>
<li class="current">Home</li>
<li>
About us
<ul>
<li>Our People</li>
<li>Who we were and are</li>
<li>Our Houses</li>
<li>Annual Reports</li>
</ul>
</li>
<li>
Being a Tenant
<ul>
<li>Asbestos</li>
<li>Being Safe & Secure</li>
</ul>
</li>
<li>
News
<ul>
<li>Community Garden</li>
<li>Football Team</li>
<li>Health Centre</li>
</ul>
</li>
</ul>
<br class="clear">
</nav>
Your second level ul is position: absolute; which means it's taken out of the normal document flow and won't take up space in relation to any other elements. Try changing absolute to relative. That should keep the items correctly positioned in the menu.
nav ul ul {
display: none;
position: absolute; /* <--- Try changing this to relative. */
top: 100%;
left: 0;
z-index: 99;
width: 200px;
}
Also, the fixed height on your top-level li doesn't let the element grow past 50px. Try setting that instead to a min-height:
nav > ul > li {
display: block;
position: relative;
width: auto;
height: 50px; /* <-- min-height: 50px */
float: left;
font-size: 1.1em;
margin: 0px 20px 0px 20px;
padding: 15px 8px 13px 8px;
text-align: center;
}
That worked in this fiddle but led to awkward jumping when the sub-menu was hovered and then un-hovered.
Also, consider your use-case - if you're doing this to support tablet/mobile devices the :hover state won't work the same way it doesn't when you're using a mouse. Users would have to know to press to the side of the "About Us" link text to see the dropdown, otherwise they'll get taken directly to the "About Us" page without seeing the :hover state. It might be necessary to either show all the items in a tree structure or use JavaScript to add additional functionality for the submenus.
Here's a decent solution to a responsive sub-menu without JavaScript, but it also doesn't use links for top-level menu items that have sub-items.

Alignment in nav menu

I'm working on a nav bar and dropdown menu using only CSS.
I'm trying to align the sub menu with respect to the parent element .dropdown. When I use position:relative on any parent container, so that I can add position:absolute the child elements, very strange formatting things start to happen.
/* Nav */
header nav {
float: right;
margin-top: 43px;
border-style: solid;
border-color: black;
}
header nav li {
display: inline;
margin-left: 50px;
}
header nav li a {
color: black;
transition-property: color;
transition-duration: .2s;
}
header nav li a:hover {
color: orange;
}
/* DROPDOWN MENU */
.dropdown {
}
.drop-nav {
position:absolute;
display:none;
border-style: none;
border-color:black;
padding:10px;
padding-right: 30px;
left:40%;
margin-top: 5px;
background-color: grey;
color:white;
}
.drop-nav li{
margin-left:20px;
}
.dropdown:hover .drop-nav {
display:block;
}
<header>
<h1>
<img src="logo.jpg" alt="coffeeology" />
</h1>
<nav>
<ul class="main-nav">
<li>Home</li>
<li>About Us</li>
<li class="dropdown">Menu
<ul class="drop-nav">
<li>Beverages</li>
<li>Breakfast Items</li>
<li>Brunch</li>
<li>Gelato</li>
</ul>
</li>
<li>Daily Specials</li>
<li>Contact Us</li>
</ul>
</nav>
</header>
The end objective here is to keep the sub menu in a relevant position across various window sizes. Aligning the sub menu to a larger element doesn't solve the problem because the sub menu won't stay fixed with respect to the .dropdownclass.
Any help is appreciated! Thank you.
Is this something you're looking for?
https://jsfiddle.net/28qmkLsf/
/* DROPDOWN MENU */
.dropdown {
position: relative;
}
.drop-nav {
position:absolute;
display:none;
border-style: none;
border-color:black;
padding:10px;
padding-right: 30px;
left:0%;
top: 100%;
background-color: grey;
color:white;
width: 150px;
}
.drop-nav li{
margin-left:20px;
display: block;
}

White space on the left of vertical nav bar

I am having difficulty removing the white space to the left of my vertical nav bar.
I have tried setting padding-left to 0 on my main-bar.
It's my first time building a nav bar, so if you see something semantically wrong with my codes, do let me know as well.
Thank you!
This is the HTML code.
<title>Mockup of Zopim</title>
<body>
<main>
<nav class = "side-bar">
<ul class ="main-bar">
<li class="user-nav"><a class ="big-box" href="#">User</a></li>
<li class="main-nav">Home</li>
<li class="main-nav">Visitor List</li>
<li class="main-nav">Visualization</li>
<li class="main-nav">History</li>
<li class="divider-nav">Manage</li>
<li class="manage-nav">Agents</li>
<li class="manage-nav">Departments</li>
<li class="manage-nav">Shortcuts</li>
<li class="manage-nav">Banned Visitors</li>
<li class="manage-nav">Triggers</li>
<li class="divider-nav">Settings</li>
<li class="settings-nav">Widgets</li>
<li class="settings-nav">Personal</li>
<li class="settings-nav">Accounts</li>
</ul>
</nav>
<article>
<header>
<h1>Hello!</h1>
</header>
</article>
</main>
</body>
This is the CSS code.
#charset "utf-8";
/* CSS Document */
body {
background-color: black;
}
main {
width: 100%;
}
.side-bar {
width: 15%;
height: 100%;
background-color: #585858;
position: relative;
float: left;
}
nav li {
list-style: none;
}
.main-bar {
padding-left: 0px;
}
.main-bar li a {
display: block;
width: 100%;
height: 100%;
line-height: 2.5em;
text-decoration: none;
color: white;
text-align: center;
}
article {
width: 60%;
height: 30%;
float: right;
position: relative;
}
a.big-box {
display: block;
line-height: 7em;
}
header h1 {
color: white;
}
Here is the JSfiddle link.
http://jsfiddle.net/codermax/fe0L3d08/
Most Web browsers have different default settings for the base margins and padding. So The best way to solve this is to set all the margin and padding
*{
margin:0;
padding:0;
}
or
html,body {
margin:0;
padding:0;
}
Also better if you reset your css then you can use. something like this:
http://necolas.github.io/normalize.css/
You'll want to use a reset.css to resolve different browser quirks.
I've updated your sample and set body margin, and padding to 0.
body {
margin:0;
padding:0;
}
http://jsfiddle.net/fe0L3d08/1/

height attribute of div tag is not permitting the sub menus of menu bar

I would like to diplay three horizontal contents. The horizontal contents are following.
1) Logo at the left side. It has been done
2) Menu bar with menus and sub menus with some basic css class.
3) Google map
These three contents should be placed fixed height for all the browsers. So I have set fixed height for these three horizontal div contents. But SubMenu of Menu bar are not showing up. Because, of my fixed div content (which is present in the middle). I dont know how to fix it. Any help is much appreciated. My code are below.
**//Content ONE**
<div id="HeadContainer" style="height: 62px;">
<div id="logoHolder" style="float: left;">
<img src="logo/image.gif" alt="Company Logo" />
</div>
</div>
<hr />**//Content TWO**
<div id="menubar" style="height: 28px;">
<ul class="dropdown">
<li>Draw Region
<ul class="sub_menu">
<li>Add New Region
<ul>
<li>Polygon Tool
</li>
<li>Rectangle Tool
</li>
<li>Circle Tool
</li>
</ul>
</li>
<li>Stop Drawing Region
</li>
</ul>
</li>
<li> Edit Region
</li>
<li>Remove Region
</li>
</ul>
</div>
<hr />**//Content THREE**
<div id="map-canvas" style="height: 400px"></div>
<hr />
CSS I have used for menu bar is following
I have not coded the following. I just copied the script from the net. But it is good nothing problem in it.
ul.dropdown {
position: relative;
}
ul.dropdown li {
font-weight: bold;
float: left;
zoom: 1;
background: #ccc;
}
ul.dropdown a:hover {
color: #000;
}
ul.dropdown a:active {
color: #ffa500;
}
ul.dropdown li a {
display: block;
padding: 4px 8px;
border-right: 1px solid #333;
color: #222;
}
ul.dropdown li:last-child a {
border-right: none;
}
/* Doesn't work in IE */
ul.dropdown li.hover, ul.dropdown li:hover {
background: #F3D673;
color: black;
position: relative;
}
ul.dropdown li.hover a {
color: black;
}
/*
LEVEL TWO
*/
ul.dropdown ul {
width: 220px;
visibility: hidden;
position: absolute;
top: 100%;
left: 0;
}
ul.dropdown ul li {
font-weight: normal;
background: #f6f6f6;
color: #000;
border-bottom: 1px solid #ccc;
float: none;
}
/* IE 6 & 7 Needs Inline Block */
ul.dropdown ul li a {
border-right: none;
width: 100%;
display: inline-block;
}
/*
LEVEL THREE
*/
ul.dropdown ul ul {
left: 100%;
top: 0;
}
ul.dropdown li:hover > ul {
visibility: visible;
}
The submenu is hidden behind the map, add z-index: 100 to ul.dropdown ul, and it should be in front of it. Check the demo.

equivalent tr of CSS?

How do you separate the menu bar from the body in a div, to place everything after contact below it, is there a corresponding code like a newline? I would really appreciate the help :) Thanks in advance
here's a link of picture shot:
CSS
/* because of the * default code it takes out all margin and padding */
* {
margin: 0px;
padding: 0px;
}
#container {
display: table;
}
#row {
display: table-row;
}
#left, #right, #middle {
display: table-cell;
}
#row {
display: table-row;
}
#left, #right, #middle {
display: table-cell;
}
body {
font-family: verdana;
font-size: 10px;
background-color: ABC;
padding: 50px;
margin: auto;
}
h1 {
text-align: center;
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
li {
float: left;
position: relative;
}
li + li {
border-left: 1px solid #ccc;
}
a {
display: block;
padding: 7px 10px;
color: #222; /*changes the color of all item font color in menu bar */
background: #eee; /*changes the background color of Menu bar */
text-decoration: none;
}
a:hover {
color: #fff;
background: #666; /* changes hover bg color of any menu item being pointed*/
}
a:active {
color: #f2f75e;
background: #0090cf;
}
/* Child Menu Styles */
.level-two {
position: absolute;
top: 100%;
left: -9999px;
width: 100px;
}
li:hover .level-two {
left: 0;
}
.level-two li {
width: 100%;
border: 0;
border-top: 1px solid #ccc;
}
HTML
<h1>
<ul class="level-one">
<li> Home </li>
<li> Drops
<ul class="level-two">
<li> One </li>
<li> Two </li>
<li> Three </li>
</ul>
</li>
<li> Contact </li>
</ul>
</div>
<div id="container">
<div id="row">
<div id="left">
<h4>Left Col</h4>
<p>...</p>
</div>
<div id="middle">
<h4>Middle Col</h4>
<p>...</p>
</div>
<div id="right">
<h4>Right Col</h4>
<p>...</p>
</div>
</div>
</div>
</h1>
add clearfix class on both of .
DEMO
.clearfix{
clear:both;
}
DEMO1
One alternative to the clear property is to trigger a new block formatting context on the menu in order to contain the floats inside .level-one :
.level-one {
/* trigger block formatting context to contain floats. */
overflow: hidden;
}
Demo at http://jsfiddle.net/mrYdV/1/
Here is a list of other property/value pairs that trigger block formatting context
W3C specification
Bulletproof backwards-compatible version
There is a great answer with more details covering this method at How does the CSS Block Formatting Context work?
The clear property will do this for you. You can add it to your #container for example:
#container {
display: table;
clear:both;
}
Clear means something like:
clear all elements on both sides of this element

Resources