I'm working on making a responsive menu that by default is displayed inline with the site title. However on mobile the menu needs to display as a list below the site title and it's toggled by hitting a + or -. I've achieved all of this except for two small issues.
I can't seem to get the menu to display relative to the document flow so that it overlaps the text on the pages
I need the menu to be the full width of the page.
I'm not sure if I just need to take this menu and put it in its own div outside of the nav or if I'm just forgetting some css rule. It's currently set up as:
<nav>
<div id="nav-div">
<div id="title"></div>
<div id="menu-toggle"></div>
<div id="nav-links">
<ul>
<li>link 1</li>
<li>link 2</li>
<li>link 3</li>
</ul>
</div>
</div>
</nav>
CSS:
#nav-links {
position:absolute;
width:100%;
ul {
}
li {
display:block;
float: none;
border-bottom: 1px solid black;
&:last-child {
border-bottom: none;
}
a {
}
}
}
You need to set top and left properties on #nav-links. And if you set right too, you wont need width: 100%. Also make it position:relative. Like this:
#nav-div {
position: relative;
height: 50px;
}
#nav-links {
position:absolute;
left: 0;
right: 0;
...
}
Change 50px to whatever your navbar height is.
The way I ended up doing this was:
ul {
position: absolute;
width: 100%;
right: 0px;
left: 0px;
li {
width: 100%;
a {
width: #small-width; //defined with my variables
margin: 0px auto;
display: block;
}
}
}
Related
I made a simple HTML page with a simple drop-down menu (made with CSS). I have a problem with the drop-down text transparency: it shows the bottom text (as explained in the image below). The text in the menu is a link, so it's included in a tag. I tried to change the text color and opacity property but doesn't solve the problem. Any idea?
.menu {
margin-right: 0px;
margin-left: -40px;
}
li {
display: block;
float: left;
width: 25%;
height: 50px;
line-height: 50px;
font-family: Helvetica, sans-serif;
font-size: 20px;
text-align: center;
color: white;
background-color: #000000;
}
.pat:hover {
color: #EC008C;
}
.l {
width: 100%;
height: 50px;
margin-left: -20px;
}
.sub-menu {
visibility: hidden;
}
.menu .pat:hover .sub-menu {
visibility: visible;
}
<ul class="menu">
<li>Home</li>
<li class="pat">Patenti
<ul class="sub-menu">
<li class="l">Patente A</li>
<li class="l">Patente B</li>
<li class="l">Patenti superiori</li>
</ul>
</li>
<li>News</li>
<li>Contatti</li>
</ul>
Instead of visibility: hidden; and visibility: visible; on hover for submenus, it's better to use display: none and display: block, and use position: absolute on the submenu and position: relative on its parent menu entry.
The reason display: none doesn't take any space (and position: absolute will prevent the visible submenu to change the design of the main menu entries), whereas visibility: hidden; reserves the space for the hidden element and just makes it invisible, which makes it impossible to properly position it independently of objects which it should cover when visible.
Just add position: relative to .menu. It will create a stacking context causing it to appear above body text.
Here is a modified pen. I have rewritten all rules but only the last one is important.
My menu is using a series of nested <ul> tags with sub <ul> and <li> within existing <li> calls. This is pretty standard for most menu's are far as I am aware. To make my website work well on mobile devices, I have decided to take a more responsive design approach and use #media query's to show or hide content as the browser is resized.
When my menu is shrunk down, the drop downs are hidden (for now). I will most likely introduce a hamburger type menu later on where you can click on a + icon beside the menu on the mobile version and see it's sub links.
As of right now, when the browser is resized the menu is then ordered as an absolute display and this disables the scrolling on the menu. If a user, say on an iPhone, turns the phone sideways, the menu is then cut off and they cannot scroll down to see the rest of the menu in this orientation. Here is an image to depict the issue:
And here is an example of the nested html code:
<div id="navmenu">
<ul>
<li><div class="home"></div></li>
<li class='storelink dropdown'><a class='dropbtn' href='/store'>Store</a>
<div class='dropdown-content'>
<a href='/store?group=1'>All Items</a>
</div>
</li>
<li class='cartmenu'><a href='/cart'>Cart</a></li>
<li class='accountmenu dropdown'><a class='dropbtn' href='/account'>Account</a>
<div class='dropdown-content'>
<a href='/account'>Customer login</a>
</div>
</li>
<li><a href='/services'>Services</a></li>
</ul>
</div>
and finally the relevant css
#navmenu .dropdown:hover .dropdown-content {
display: block;
position: absolute;
}
#navmenu {
overflow-y: scroll;
display: none;
clear: both;
background: #333;
left: 0;
position: absolute;
float: none;
margin: 0;
padding: 0;
width: 100%;
border-bottom: 2px solid #fff;
}
#navmenu ul {
width: 100%;
text-align: center;
}
#navmenu li {
float: none;
clear: both;
background: #333;
width: 100%;
text-align: center;
}
#navmenu li a {
display: block;
width: 100%;
clear: both;
margin: 0;
padding: 10px 0;
}
Why won't this scroll when resized? Thanks
Try adding this:
#navmenu {
height: 100%;
...
}
Hmm, you can try giving your #navmenu a fixed height.
Alternatively, you can try setting #navmenu to position:fixed (not absolute) and height:100%.
I want my sub menu to span the full width of the browser window like the below image:
I am using Bootstrap, also my main menu is floated to the right.
I have created a demo on what I have done so far. How do I achieve this result?
http://codepen.io/ifusion/pen/oLVVXj
First of all, bootstrap makes you really unflexible. So if you want to use it I suggest to move the submenu out of the menu's elements, because the width:100%; is dependent on the parent. So everything that should be wider than the parent, shouldn't be the child of this parent element. In addition position:absolute is dependent on the next parent with position:absolute or position:relative. So there are many things that don't make it easy. To move the submenu would make it a lot easier. There you can just use width:100%; and position:absolute with left:0.
Alternatively to get the submenu out of the flow of the page, you could use position:fixed. And width:100%. Check out the Codepen for this solution. I like the first one more, even if it's more work. However, fixed positioning has some side effects, but maybe it's not important for you.
The position absolute child will position with respect to the closest position relative parent, so removing the position relative for main-menu li will solve this issue. Also remove the padding and margin from the body and html.
body, html{
margin: 0;
padding: 0;
}
.main-menu {
list-style-type: none;
padding: 0;
margin: 0;
float: right;
}
.main-menu li {
float: left;
}
.main-menu li a {
display: block;
background: #c2c2c2;
padding: 20px;
color: #337ab7;
text-decoration: none;
}
.main-menu-dropdown {
position: absolute;
left: 0;
right: 0;
display: block;
padding: 0;
list-style-type: none;
background-color: black;
text-align: center;
}
.main-menu-dropdown li {
float: none;
display: inline-block;
margin-left: -4px;
}
.main-menu-dropdown li a {
background: black;
display: inline-block;
}
<div class="container">
<div class="col-md-12">
<ul class="main-menu">
<li>First item</li>
<li>
<a class="has-dropdown" href="#">Second Item</a>
<ul class="main-menu-dropdown clearfix">
<li>Sub item 1</li>
<li>Sub item 2</li>
<li>Sub item 3</li>
</ul>
</li>
<li>Third Item</li>
<li>Fourth Item</li>
</ul>
<div class="col-md-12">
I need the sub menu to span the width of the browser
</div>
</div>
</div>
First off, the width of the submenu is being restricted because it's parent element has position: relative.
Once that is removed the submenu becomes full width, however the items are still aligned left.
In the example below I made .main-menu-dropdown use display: flex and then centered the items within it.
http://codepen.io/adrianlynch/pen/RRddjk
.main-menu-dropdown {
position: absolute;
left: -15px;
right: -15px;
display: flex;
justify-content: center;
margin: 0;
padding: 0;
list-style-type: none;
background: black;
}
UPDATE: Simplified HTML & CSS as per one of the answers below. The problem is still occurring however.
I have a working nav that is something like this:
item11item2item3 Centered item4item5item6
I want to add padding between the items so it looks like this:
item1 item2 item3 Centered item4 item5 item6
The items on the left are right-justified. The items on the right are left-justified.
The Problem
If I use float: right; to justify the list, I get item3 item2 item1.
If I use float: left; and set the container width to auto, I can get the correct layout, but only when I use px padding.
When I use % padding like padding-left: 3%; it breaks and looks like this:
item1 item2 Centered item4 item5 item6
item3
Here's my HTML:
<div class="container">
<nav>
<ul class="left">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<ul class="center">
<li>Centered</li>
</ul>
<ul class="right">
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
</ul>
</nav>
</div>
Here's my CSS:
/* Reset */
html, body, nav, li {
margin: 0; padding: 0; border: 0;
}
li {
list-style-type: none;
list-style-position: outside;
}
/* Styles */
.container {
width: 100%;
height: auto;
}
nav {
width: 80%;
margin: 0 auto;
}
nav > ul.left {
position: absolute;
right: 55%;
}
nav > ul.left > li {
float: left;
padding-right: 5%;
}
.center {
position: absolute;
left: 45%;
width: 10%;
}
.center li {
text-align: center;
}
nav > ul.right {
position: absolute;
left: 55%;
width: 45%;
}
nav > ul.right > li {
float: left;
padding-left: 5%;
}
Notes:
I'm using absolute positioning & containers in order to keep "Centered" perfectly centered even if the widths of the left and right nav items aren't identical.
I'm using % based widths because it's a flexible layout (reponsive)
the above code works ok, but I'd really like to make the padding percentage based so it's flexible.
So it appears that the li-container div inherits the width correctly and accounts for the padding when I use pixels, but not when I use percentages. Is this typical behavior? What is the solution?
Here's a jsFiddle in case you want to play around with it.
ADDITIONAL UPDATE:
The chief problem seems to be the need to have the "left" items right-justified. If I use float:right then I get reverse order, which isn't good. If I use float:left on the left items, then the order is correct, but I need to remove explicit width from the container, or the items aren't right-justified. Removing explicit container width causes the issue I'm experiencing.
Using the element inspector in Chrome on that fiddle, with the padding on 3% on .left .li I gather this:
.left .li-container's calculated width: 128px
Each individual li's width: 43px
You have three li's --> 3 * 43 = 129px
That would cause the width of the child li's to extend the parent container's width, thus wrapping to a new line. So it probably has to do with rounding off in the calculation of the actual width from that percentage value.
To compensate for this, I can only think of a jQuery/JS solution at the moment but I doubt you'd want that, and just want it in pure CSS.
Note: I would just add this as a comment but unfortunately I can't because that requires 50 rep. Sorry for not providing a complete answer!
Edit: Here's a new solution. Hope this looks like expected. ;)
HTML
<nav>
<ul class="left">
<li>Item 1 longer longer</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<ul class="centered">
<li>Centered</li>
</ul>
<ul class="right">
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
</ul>
</nav>
CSS
ul, li {
margin: 0;
padding: 0;
list-style-type: none;
}
nav {
position: relative;
min-width: 700px;
}
nav > ul {
width: 100%;
background: red;
}
nav > ul > li {
display: inline-block;
text-align: center;
background: green;
color: white;
}
nav > ul.centered {
position: absolute;
left: 40%;
width: 20%;
background: orange;
}
nav > ul.centered > li {
display: block;
background: orange;
}
nav > ul.left {
position: absolute;
left: 0;
max-width: 40%;
}
nav > ul.left > li {
float: right;
padding: 2%;
}
nav > ul.right {
position: absolute;
left: 60%;
max-width: 40%;
}
nav > ul.right > li {
float: left;
padding: 2%;
}
Demo
Try before buy
Update
The only way to get all things lined up, in the right order without any breaking ever is using display: inline-block. I've updated only the left side to demonstrate it.
Final thoughts: As this will never break, you have to set a min-width for the <nav>-element, otherwise the elements will overlap on screens that are too small. What you experienced before, when the width of the parent container of floating elements gets too small and they break into the next line, is the expected behavior for floating elements.
Updated CSS
nav > ul.left {
position: absolute;
left: 0;
max-width: 40%;
text-align: right;
white-space: nowrap;
line-height: 0;
font-size: 0;
}
nav > ul.left > li {
display: inline-block;
padding: 10%;
line-height: auto;
font-size: 12px;
}
Demo
Try display: inline-block
Here's also a link to my first solution.
Using a list, I want to create a list of links as in the image
<div id="toolbarbottom" class="toolbar" style="position: fixed; clear: both; overflow: visible; bottom: 0px; left: 0px; width: 100%;">
<ul>
<li id="active"><span><a id="current" href="#add" class="button">News</a></span></li>
<li><span> Updates</span> </li>
<li><span>Contact Us</span></li>
<li><span>Website </span></li>
<li><span>Refresh</span> </li>
</ul>
</div>
I am kind of stuck on the CSS (button) and probably the spacing between the list elements. to make the list appear in this form. Anyone with an idea of how I can tackle this please?
or another way is to use floats, and make the ul display: inline-block to contain the floated li's
you need to slightly change the HTML so the span is inside the a - this is so you can hide the spanned text, but keep the image background and clickable area for the a elements, also I'd give each link a unique reference (class or ID) so the backgrounds can be applied separately.
example HTML:
<div id="toolbarbottom" class="toolbar" style="position: fixed; top: 0px; left: 0px; width: 100%;">
<ul>
<li class="active"><span>News</span></li>
<li><span> Updates</span></li>
<li><span>Contact Us</span></li>
<li><span>Website </span></li>
<li><span>Refresh</span> </li>
</ul>
</div>
you can then put the whole background on the ul and put the individual images on each link.
#toolbarbottom ul {
list-style: none;
margin: 0;
padding: 0;
display: inline-block;
width: 100%;
background: #ff0;
}
#toolbarbottom li {
float: left;
width: 80px;
height: 80px;
border: 1px solid #000; /* not required, just to show where individual links are */
}
#toolbarbottom li a { /* make link fill the li element */
display: block;
height: 80px;
}
#toolbarbottom li span { /* hide the text */
position: absolute;
clip: rect(1px, 1px, 1px, 1px);
clip: rect (1px 1px 1px 1px);
}
/* couple examples of where to put individual backgrounds */
#toolbarbottom #mupdates {background: #dad;}
#toolbarbottom #mcontact {background: #0f0;}
fiddle: http://jsfiddle.net/YaS9J/
css
#toolbarbottom li {
display:inline-block;
padding:0 10px;
}
/* if you have one */
#toolbarbottom li img {
display:block;
}
You should first set up your css as an external style sheet rather than hard code it into your html. (See http://www.w3.org/TR/html4/present/styles.html for more on this). To add spacing between the li elements you can use the css cascade to add some bottom padding as follows:
#toolbarbottom ul li {
padding-bottom:4px;
}
To make the list appear inline you would use:
#toolbarbottom ul{
list-style: none;
display: inline;
padding-left: 0;
margin-left: 0;
}
Those button look like images, so to achieve that you'd just include them within each li element:
<li><img src="/path/to/image.jpg"></li>