I am working with a website with css drop down menus within the header div. When the drop down menu appears it resizes the header div therefore shoving down the content div.
In the body of my index.php:
<div class="top"></div>
<div class="container">
<?php include_once("header.php"); ?>
<div class="content"></div>
</div>
The header.php
<div class="header">
<div style="display: table-cell; width: 250px; text-align: center;">
LOGO
</div>
<div style="display: table-cell;">
<br><br><br>
<ul>
<li>Link 1
<ul>
<li>Monkey 1</li>
<li>Monkey 2</li>
<li>Monkey 3</li>
<li>Monkey 4</li>
<li>Monkey 5</li>
<li>Monkey 6</li>
<li>Monkey 7</li>
</ul>
</li>
<li>Link 2
<ul>
<li>Monkey 1</li>
<li>Monkey 2</li>
</ul>
</li>
<li>
Link 3
<ul>
<li>Monkey 1</li>
<li>Monkey 2</li>
<li>Monkey 3</li>
</ul>
</li>
<li>Link 4</li>
<li>Link 5</li>
<li>Link 6</li>
</ul>
</div>
</div>
And main.css
ul{
padding: 0;
list-style: none;
}
ul li{
float: left;
width: 100px;
text-align: center;
}
ul li a{
display: block;
padding: 5px 10px;
color: #333;
background: #f2f2f2;
text-decoration: none;
}
ul li a:hover{
color: #fff;
background: #939393;
}
ul li ul{
display: none;
}
ul li:hover ul{
display: block; /* display the dropdown */
}
.top{
background: #1b2d3c;
width: 100%;
height: 40px;
}
.container{
width: 1100px;
height: 1000px;
}
.header{
display: table-row;
width: 1100px;
height: 130px;
}
.content{
position: absolute;
background: #fff;
width: 1100px;
height: 500px;
}
* {
background: #87a0b4;
margin: 0px;
padding: 0px;
margin-left: auto ;
margin-right: auto ;
}
I apologize for the lengthy post. How can I prevent the problem I am having? I want to be sure I am doing things correctly before I get too deep into the project.
You need to change position of ul li:hover ul to absolute, and add some other properties like this JSFiddel (Source)
ul li:hover ul {
display: block;
position: absolute;
width: 100px;
z-index: 100;
}
Hope this will help you ..
As was said in the previous answer, you need to set position: absolute. I'd like to add a bit of information as to why.
According to MDN:
Elements that are positioned relatively are still considered to be in the normal flow of elements in the document. In contrast, an element that is positioned absolutely is taken out of the flow and thus takes up no space when placing other elements. The absolutely positioned element is positioned relative to nearest positioned ancestor. If a positioned ancestor doesn't exist, the initial container is used.
Basically, by giving an element absolute positioning, it is no longer being taken into account when positioning the rest of the page. It will take up its alloted space in its set position no matter what.
In your case, the div was moving relative to the elements surrounding it. By using position: absolute, you are ommiting and relativity.
Related
I have a hoverable menu as you can see in the code. However, I got a problem when I hover, which the hover content goes out of the page. When I use "position: relative" for the div(content) it is okay but then the text "Example" goes to the left, wonder how to fix.
When I use position: absolute:
When I use position: relative:
ul {
float: right;
position: relative;
}
div {
display: none;
background-color: red;
position: relative;
width: 200px;
}
ul:hover div {
display: block;
}
<ul>
<li>Example</li>
<div>
<ol>
<li>Link 1</li>
<li>Link 2</li>
</ol>
</div>
</ul>
due to lack of space u'r getting this issue make width:200px; for ul
ul {
float: right;
position: relative;
width: 200px;
}
div {
display: none;
background-color: red;
position: relative;
width: 200px;
}
ul:hover div {
display: block;
}
<ul>
<li>Example</li>
<div>
<ol>
<li>Link 1</li>
<li>Link 2</li>
</ol>
</div>
</ul>
You could use position absolute, and manipulate its positions setting a negative margin...
ul {
float: right;
position: relative;
}
div {
display: none;
background-color: red;
position: absolute;
width: auto;
margin-left: -26px;
}
ul:hover div {
display: block;
}
<ul>
<li>Example</li>
<div>
<ol>
<li>Link 1</li>
<li>Link 2</li>
</ol>
</div>
</ul>
Erase the div, apply the width to the ul and apply the display: none and hovering to the ol.
ul {
float: right;
width: 200px;
}
ol {
display: none;
background-color: red;
}
ul:hover ol {
display: block;
}
<ul>
<li>Example</li>
<ol>
<li>Link 1</li>
<li>Link 2</li>
</ol>
</ul>
Second version: If you want everything to be floated right, apply float: right; to ul and li in the HTML structure as used before:
ul {
float: right;
}
ol {
display: none;
background-color: red;
}
li {
float: right;
clear: right;
}
ul:hover ol {
display: block;
}
<ul>
<li>Example</li>
<ol>
<li>Link 1</li>
<li>Link 2</li>
</ol>
</ul>
It's natural behavior, it will depend on header text lenght, it will set your max lenght for below text, you'll need to define a fixed width for the header element and not on child one as you did.
Example of dynamic width (natural div property as a flex container):
ul {
float: right;
position: relative;
}
div {
display: none;
background-color: red;
position: relative;
}
ul:hover div {
display: block;
}
<ul>
<li>ExampleOfMagicMenu</li>
<div>
<ol>
<li>Link 1</li>
<li>Link 2</li>
</ol>
</div>
</ul>
Second example, setting fixed width to the parent box, letting child/s element/s with auto-width (they will never occupy more width than parent, as they can grow in height, overriding height auto with a fixed one will cause overflow):
ul {
float: right;
position: relative;
width: 100px;
text-align: right;
list-style: none;
}
div {
display: none;
background-color: red;
position: relative;
}
ul:hover div {
display: block;
}
<ul>
<li>Example</li>
<div>
<ol>
<li>Link 1</li>
<li>Link 2</li>
</ol>
</div>
</ul>
You can do it with the Flexbox without unnecessary floats and positioning.
Solution with the container as you wrote in the comment:
.container {
max-width: 960px;
margin: 0 auto;
border: 1px solid;
}
ul {
display: flex; /* displays children inline by default that's why you need to change its direction */
flex-direction: column; /* stacks children vertically */
align-items: flex-end; /* places them far right */
}
ul > div { /* modified for accuracy */
display: none;
background-color: red;
width: 200px;
}
ul li:hover + div { /* modified for accuracy since the inner div is the next element after the li */
display: block;
}
li + div:hover {display:block} /* needs to be in order to be displayed when hovering over */
<div class="container">
<ul>
<li>Example</li>
<div>
<ol>
<li>Link 1</li>
<li>Link 2</li>
</ol>
</div>
</ul>
</div>
If you don't fancy the above solution then you can simply add right: 0 to the absolutely positioned div:
.container {
max-width: 960px;
margin: 0 auto;
border: 1px solid;
}
.container:after {
content: "";
display: block;
clear: both;
}
ul {
float: right;
position: relative;
}
ul > div {
display: none;
background-color: red;
position: absolute;
right: 0; /* added */
width: 200px;
}
ul:hover div {
display: block;
}
<div class="container">
<ul>
<li>Example</li>
<div>
<ol>
<li>Link 1</li>
<li>Link 2</li>
</ol>
</div>
</ul>
</div>
I'm a beginner in CSS but I'm currently trying to create a material-design header with "line" under each tab like on this Google site : Our Products | Google
If possible I'd also like the animation when changing tab.
For now my header html is :
<header>
[MY LOGO]
<nav>
<ul>
<li>tab 1</li>
<li>tab 2</li>
<li>tab 3</li>
</ul>
</nav>
</header>
And my CSS :
header {
display: table;
background:#FFF;
box-shadow: 0 0 8px 0 rgba(0,0,0,.3);
width:100vw;
clear: both;
display: table;
overflow: hidden;
white-space: nowrap;
}
nav {
display: inline-block;
margin-left: 5vw;
vertical-align: middle;
}
nav ul {
display: inline-block;
margin 0;
padding: 0;
}
nav li {
display: inline-block;
margin-right: 3vw;
}
nav a {
text-decoration: none;
}
nav a:visited {
color: inherit;
}
nav a:hover,:active,:focus {
color: #b82525;
}
How do I position the shape to be under the .current-nav tab ?
If you inspect the example you have linked to, you will see that one way they do this is by adding a border-bottom to the selected element. You can do this like so
.current-nav {
border-bottom:1px solid #4285f4;
}
They have another technique which is to add an element below, but i'll leave that for you to investigate/reverse engineer.
just use nav ul li a.current-nav{ border-bottom: 1px solid red; } and you are done.
Try this:
<header>
[MY LOGO]
<nav>
<ul>
<li>tab 1</li>
<li>tab 2</li>
<li>tab 3</li>
</ul>
<div class="line-selected right" style="display: block; left: 322px; right: 0.078px;"></div>
</nav>
</header>
The left and right values depends on the sizes of your Logo and of your <li>. You have to change the style of the "line-selected right"class for each event.
I am trying to create a vertical navigation in my HTML document, but I cannot seem to get the main menu to line up evenly. Here is my HTML for the vertical navigation:
<div id="navbar">
<ul>
<li>Menu 1</li>
<li>Menu 2
<ul>
<li>Drop 1</li>
<li>Drop 2</li>
<li>Drop 3</li>
</ul></li>
<li>Menu 3</li>
<li>Menu 4
<ul>
<li>Drop 1</li>
<li>Drop 2</li>
</ul></li>
<li>Menu 5</li>
</ul>
</div>
And my CSS:
#navbar {
margin-left: -40px;
}
#navbar li{
list-style: none;
position: relative;
width: 209px;
padding: 6px;
line-height: 20pt;
cursor: pointer;
}
#navbar ul ul{
margin-left: 100px;
margin-top: -28px;
visibility:hidden;
height: 100px;
}
#navbar ul li:hover ul{
visibility:visible;
}
This is my first post ever, so I apologize if I didn't post in the correct format. This code is also from a much larger HTML/CSS file, so I just copy/pasted the only part I'm having an issue with. If I need to post a screenshot of what I'm talking about I can do that.
Thank you in advance!!
demo - http://jsfiddle.net/uab2hr50/2/
if you are looking to align the sub menu below the main menu
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#navbar ul {
border: 1px solid red;
display: inline-block;
padding: 6px;
}
#navbar li {
list-style: none;
position: relative;
width: 209px;
line-height: 20pt;
cursor: pointer;
}
#navbar ul ul {
display: none;
padding: 0;
border: 0;
}
#navbar ul li:hover ul {
display: block;
}
<div id="navbar">
<ul>
<li>Menu 1
</li>
<li>Menu 2
<ul>
<li>Drop 1
</li>
<li>Drop 2
</li>
<li>Drop 3
</li>
</ul>
</li>
<li>Menu 3
</li>
<li>Menu 4
<ul>
<li>Drop 1
</li>
<li>Drop 2
</li>
</ul>
</li>
<li>Menu 5
</li>
</ul>
</div>
There are a few problems here preventing the display you expect:
First: the fiddle
CSS CHANGES
#navbar li{
list-style: none;
position: relative;
/*width: 209px;*/
padding: 6px;
line-height: 20pt;
cursor: pointer;
display: block;
}
#navbar li:after {
content: '';
display: table;
clear: both;
}
#navbar ul a {
display: inline-block;
}
#navbar ul ul{
margin-top: 0;
visibility:hidden;
height: 100px;
padding: 0;
display: inline-block;
vertical-align: top;
margin-bottom: -9000px;
}
#navbar ul ul li:first-child {
padding-top: 0;
}
We removed quite a bit of your padding and margin rules here, and stopped setting a width on the li that you went ahead and broke out of anyway in the original code.
Then, we told both the a and ul elements to display as inline-block, told them they were to vertically align at the top and removed the padding-top off the first child of your sub-nav.
Then, we way over-compensate for the height of your lists by setting a margin-bottom of -9000px to pull your subsequent list items up to where they belong.
No absolute positioning needed, which would probably require some JavaScript to position everything reliably for you given different conditions.
Hope that helps.
I'm trying to make the navbar elements appear in a row, side by side, with the dropdown one causing a menu to drop down beneath them.
I know there's the nav element and I know there are a thousand jQuery plugins for this. I just want to understand why this isn't working.
http://codepen.io/anon/pen/hjKLD
<!-- Works all the way down to IE7! -->
<header>
<nav>
link
link
<ul class="drop">
<li>
dropdown
</li>
<li class="menu">
link
link
link
link
</li>
</ul>
link
link
</nav>
</header>
li {
list-style-type:none;
margin: 0px;
padding: 0px;
border: 0px;
}
Try
ul, li {
display: inline;
}
Update
I found a quick solution, and without using JavaScript! You might need to make some changes to fix the minor issues.
Here's what I'd suggest for your HTML:
<header>
<nav>
<ul>
<li>link 1</li>
<li>link 2</li>
<li class="menu">Dropdown
<ul class="drop">
<li>link 3</li>
<li>link 4</li>
<li>link 5</li>
<li>link 6</li>
</ul>
</li>
<li>link 7</li>
<li>link 8</li>
</ul>
</nav>
</header>
It's cleaner and more semantic.
Now for the CSS:
a, ul, li {
list-style-type:none;
margin: 0px;
padding: 0px;
border: 0px;
display: inline;
text-decoration: none;
}
a:hover {text-decoration: underline;}
ul {display: inline-block;}
.drop {
display: none;
padding: 5px;
border: 1px solid #000;
background-color: #fff;
}
.menu:hover .drop {
display: block;
position: absolute;
left: 90px;
}
.drop li {display: block;}
No JS required.
Demo via Codepen here.
Need to add display: inline; to the <li> element as well. Otherwise, it's still blocked.
Your list is being displayed as a block element. Which will fill the space horizontaly causing the elements to render vertically.
In order to fix this issue you can chance the display type:
display: inline;
display: inline-block;
Or you can float the element, which will make it no longer fill horizontally and allow the elements to be displayed side by side:
float: left;
See here for more details on css display types http://css-tricks.com/almanac/properties/d/display/
Try this css instead:
a{
vertical-align: top;
}
li {
list-style-type:none;
margin: 0px;
padding: 0px;
border: 0px;
}
ul{
display: inline-block;
margin: 0px;
padding: 0px;
}
This will make them all end up on the same row, but something does still need to be done about the dropdown menu pushing the items to the right further when it's shown.
I think that's what you searching for:
Try this: http://codepen.io/anon/pen/vaEkt
For consistency of markup I swapped the <ul> list in <nav> element.
HTML
<header>
<nav>
link
link
<nav class="drop">
<span>dropdown</span>
<nav class="menu">
link
link
link
link
</nav>
</nav>
link
link
</nav>
</header>
CSS
li {
list-style-type:none;
margin: 0px;
padding: 0px;
border: 0px;
}
nav,
ul {
display: inline-block;
}
.drop {
position: relative;
}
.drop .menu {
position: absolute;
bootom: 0;
left: 0;
}
I have a list that I'd like the main elements to align vertically and the sub elements of each to drop down underneath the main element. I want to keep the position: absolute on the subNav class because the width of this nav will vary from each so I can't set a width. This works in Firefox, but in IE 7 the absolute causes the subnav to display inline (so shifted to the right and up from where I would like). How can I fix this?
Example:
<style>
#nav ul, #nav li ul {
list-style-type: none;
margin: 0;
padding: 0;
}
#nav li {
float: left;
width: 120px;
border-right: 1px solid #000;
padding: 10px;
}
#nav li ul li {
float: none;
width: auto;
height: auto;
border-right: none;
text-align: left;
padding: 0;
}
#nav .subNav {
background: #eee;
position: absolute;
padding: 10px;
}
</style>
</head>
<body>
<div id="nav">
<ul>
<li>Main One
<ul class="subNav">
<li>Sub One A</li>
<li>Sub One B</li>
</ul>
</li>
<li>Main Two
<ul class="subNav">
<li>Sub Two A</li>
<li>Sub Two B</li>
</ul>
</li>
</ul>
</div>
</body>
Don't forget to put in your top and left values.
nav .subNav{
top:10px;
left:20px;
}
nav.containerDiv {
position:relative;
}
HTML
<ul class="nav">
<li>
<div class="containerDiv">
<ul class="subNav">...
</div>
</li>
</ul>
This will result in the subNav being relative to the container div, instead of the whole document.