The best way to describe this issue is with pictures (Don't mind the Dutch), I'm stuck with this at the moment:
Example1
In the first example you can see that the red dropdown hover lines with the parent in this case. What I want is this:
Example2
The way I did it in Example2 was with element inspect and changing the Ul's manually with margin-top (40px). Which means I have to do 80px, 120px etc. On the next couple of menu links.
Is there an easier way?
Thanks in advance!
Position the dropdown menu relative to the menu container (<ul>) instead of the menu item (<li>).
A simple example on jsFiddle.
The relative HTML:
<ul class="outer">
<li>
Beelden
<ul class="sub-menu">
<li>Geurkaarsen</li>
<li>Rituele kaarsen</li>
<li>Affirmatie kaarsen</li>
</ul>
</li>
</ul>
And CSS:
/* Your outer menu */
ul.outer {
position: relative;
}
li {
/* Whatever styles you set here, don't give it relative positioning */
}
ul.sub-menu {
position: absolute;
top: 0;
right: -100%;
width: 100%;
}
Live demo:
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
height: 100vh;
}
body > ul {
/* This next line is crucial */
position: relative;
background-color: #c5e2d8;
width: 30%;
height: 100%;
}
ul.sub-menu {
display: none;
position: absolute;
top: 0;
right: -100%;
width: 100%;
background-color: tomato;
}
li {
display: block;
color: #444;
padding: .5em;
cursor: pointer;
}
li.has-children::after {
content: '▸';
position: absolute;
right: 5px;
}
li:hover {
background-color: tomato;
}
li.has-children:hover ul {
display: block;
}
<ul>
<li class="has-children">
Beelden
<ul class="sub-menu">
<li>Geurkaarsen</li>
<li>Rituele kaarsen</li>
<li>Affirmatie kaarsen</li>
</ul>
</li>
<li class="has-children">
Kaarsen
<ul class="sub-menu">
<li>Sub-menu 2</li>
<li>I don't know</li>
<li>any Dutch</li>
</ul>
</li>
<li>Wierook</li>
<li>Kruiden</li>
<li>Olien</li>
</ul>
I would like to achieve this fully justified horizontal menu:
Justifying is done with flexbox and works, but I could not get the separating mid-dots justified, too; they are made by using css-content via pseudo-class. Also, I am wondering if there's a better way to vertically center the items than faking it by adding a padding as I have done it.
Here's my code and the fiddle:
ul {
list-style: none;
padding: 0;
margin: 0;
display: flex;
justify-content: space-between;
}
li.home {
padding: 0;
}
li {
vertical-align: middle;
padding-top: 10px;
}
nav {
border-bottom: 1px solid black;
border-top: 1px solid black;
height: 40px;
}
li::after {
//padding: 0em 0.4em;
content: '\00b7';
pointer-events: none;
}
li.home::after,
li.last::after {
content: none;
text-align: justify;
}
<nav id="main-menu">
<ul>
<li class="home">
<img src="http://dummyimage.com/40x40/000/fff">
</li>
<li class="second">Item 1</li>
<li>Item 2</li>
<li>One more Item</li>
<li>Another Item</li>
<li class="last">Contact</li>
</ul>
</nav>
body { margin: 0; } /* 1 */
nav {
height: 40px;
border-bottom: 1px solid black;
border-top: 1px solid black;
}
ul {
display: flex;
justify-content: space-between; /* 2 */
align-items: center; /* 2 */
height: 100%;
list-style: none;
padding: 0;
margin: 0;
}
li:not(.home) {
flex: 1; /* 3 */
height: 100%;
border: 1px dashed red; /* 4 */
background-color: lightgreen; /* 4 */
}
li:not(.home) > a { /* 5 */
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
li img { vertical-align: bottom; } /* 6 */
li { position: relative; } /* 7 */
li:not(.home):not(:last-child)::before { /* 8 */
position: absolute;
content: '\26AB'; /* 4 */
left: 100%;
top: 50%;
transform: translate(-50%,-50%);
z-index: 1;
pointer-events: none;
}
<nav id="main-menu">
<ul>
<li class="home">
<img src="http://dummyimage.com/40x40/000/fff">
</li>
<li class="second">Item 1</li>
<li>Item 2</li>
<li>One more Item</li>
<li>Another Item</li>
<li class="last">Contact</li>
</ul>
jsFiddle
Notes:
Remove default margins on body element
Methods for Aligning Flex Items
Consume all remaining space with flex-grow property
Borders, background colors, and larger bullets for illustration purposes only
Enable anchor elements to fully cover list item space and align text with flex properties
Remove baseline alignment (i.e., whitespace underneath image)
Establish nearest positioned ancestor for absolute positioning
Use absolute positioning to align bullets
You can vertically center the items with align-self: center; but the dot separators are in my opinion impossible to achieve with pseudo elements like :before or :after.
I would recommend to use separate <li> tags for separators like below:
Note that your image element needs display: block; to have a proper height.
ul {
list-style: none;
padding: 0;
margin: 0;
display: flex;
justify-content: space-between;
}
img {
display: block;
}
li.home {
padding: 0;
}
li {
align-self: center;
}
nav {
border-bottom: 1px solid black;
border-top: 1px solid black;
height: 40px;
}
<nav id="main-menu">
<ul>
<li class="home">
<img src="http://dummyimage.com/40x40/000/fff">
</li>
<li class="second">Item 1</li>
<li class="separator">·</li>
<li>Item 2</li>
<li class="separator">·</li>
<li>One more Item</li>
<li class="separator">·</li>
<li>Another Item</li>
<li class="separator">·</li>
<li class="last">Contact</li>
</ul>
</nav>
Fiddle version
I have an unordered list which is inside a div tag and initially the list is empty. When items are added on to it, it will expand and I want it to be scroll-able once it the length of the list exceeds that of the web page, i.e I do not want the web page to scroll, I want only the unordered list to scroll. However currently, the scroll bar for my unordered list is not appearing.
My html code is:
<div style="width: 25%; float: right; " class="online_users">
<div class="panel panel-primary">
<div class="panel-heading">
<span class="glyphicon glyphicon-comment"></span> Online Users
<ul id="ListOfOnlineUsers" style="overflow: auto;height:100%; word-wrap: break-word;" class="list-group">
</ul>
</div>
</div>
</div>
My CSS code is
html{
height: 100%
}
{
margin: 0;
padding: 0;
}
body {
padding: 50px;
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
height: 100%;
}
a {
color: #00B7FF;
}
.chat
{
list-style: none;
margin: 0;
padding: 0;
}
.chat li
{
margin-bottom: 10px;
padding-bottom: 5px;
border-bottom: 1px dotted #B3A9A9;
}
.chat li.left .chat-body
{
/*margin-left: 60px;*/
}
.chat li.right .chat-body
{
/*()margin-right: 60px;*/
}
.chat li .chat-body p
{
margin: 0;
color: #777777;
word-wrap: break-word;
}
.panel .slidedown .glyphicon, .chat .glyphicon
{
/*margin-right: 5px;*/
}
.panel-body
{
overflow-y: scroll;
top: 1em;
left: 1em;
height: 250px;
}
::-webkit-scrollbar-track
{
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
background-color: #F5F5F5;
}
::-webkit-scrollbar
{
width: 12px;
background-color: #F5F5F5;
}
::-webkit-scrollbar-thumb
{
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
background-color: #555;
}
/* CSS used here will be applied after bootstrap.css */
body, html {
height: 100%;
background-repeat: no-repeat;
background-image: linear-gradient(rgb(154, 145, 162), rgb(12, 97, 33));
}
.card-container.card {
width: 350px;
padding: 40px 40px;
}
.card {
background-color: #F7F7F7;
/* just in case there no content*/
padding: 20px 25px 30px;
margin: 0 auto 25px;
margin-top: 50px;
/* shadows and rounded borders */
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
-moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
-webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
}
.btn {
font-weight: 700;
height: 36px;
-moz-user-select: none;
-webkit-user-select: none;
user-select: none;
cursor: default;
}
.form-signin input[type=text],
.form-signin button {
width: 100%;
display: block;
margin-bottom: 10px;
z-index: 1;
position: relative;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.btn.btn-signin:hover,
.btn.btn-signin:active,
.btn.btn-signin:focus {
background-color: rgb(12, 97, 33);
}
Set the list's max-height to the height of its parent (or whatever you need it to be) and then set its overflow property to auto.
Here's a quick example:
div{
border:1px solid #000;
font-family:arial;
height:100px;
width:200px;
}
ul{
list-style:none;
max-height:100px;
margin:0;
overflow:auto;
padding:0;
text-indent:10px;
}
li{
line-height:25px;
}
li:nth-child(even){
background:#ccc;
}
<div>
<ul>
<li>text</li>
<li>text</li>
<li>text</li>
<li>text</li>
<li>text</li>
<li>text</li>
</ul>
</div>
Try to add a wrapper and set max-height to the wrapper
Html
<div class="listWrapper">
<ul>
<li>content</li>
<li>content</li>
<li>content</li>
<li>content</li>
<li>content</li>
<li>content</li>
<li>content</li>
<li>content</li>
<li>content</li>
<li>content</li>
<li>content</li>
</ul>
</div>
Css
ul, li {
list-style:none;
padding:0;
margin:0;
}
.listWrapper {
max-height:100px;
overflow-y:auto;
}
Fiddle Demo
You can change the height of the ul to max-height: 100vh, that way the ul will always have the size of the viewport.
For browser support check this : http://caniuse.com/#search=vh
In case you want it inside a div that doesn't have the viewport height, follow #Shaggy answer.
With height set to 100% your container will not display scrollbars.
https://developer.mozilla.org/en-US/docs/Web/CSS/overflow
.panel {
width: 200px;
}
.list-group {
overflow: auto;
height: 200px;
}
<div class="online_users">
<div class="panel panel-primary">
<div class="panel-heading">
<span class="glyphicon glyphicon-comment"></span> Online Users
<ul id="ListOfOnlineUsers" class="list-group">
<li>some item</li>
<li>some item</li>
<li>some item</li>
<li>some item</li>
<li>some item</li>
<li>some item</li>
<li>some item</li>
<li>some item</li>
<li>some item</li>
<li>some item</li>
<li>some item</li>
<li>some item</li>
<li>some item</li>
<li>some item</li>
<li>some item</li>
<li>some item</li>
<li>some item</li>
<li>some item</li>
<li>some item</li>
<li>some item</li>
<li>some item</li>
</ul>
</div>
</div>
</div>
You have the right CSS properties defined for class .panel-body but you do not use it in your HTML yet. Move the <ul> into a separate div with the class .panel-body. That should do the trick:
<div style="width: 25%; float: right; " class="online_users">
<div class="panel panel-primary">
<div class="panel-heading">
<span class="glyphicon glyphicon-comment"></span> Online Users
</div>
<div class="panel-body">
<ul id="ListOfOnlineUsers" style="height:100%; word-wrap: break-word;" class="list-group">
</ul>
</div>
</div>
</div>
Edit: You should drop the overflow: auto from the <ul> or you get double scroll bars
Edit2: Yet another optimization: set margin: 0 for the <ul> and change the the .panel-body to overflow: auto, so the div's scroll bar is only visible if needed. See my fiddle
No need for the outer div (NOTE this is for horizontal scrollbars. Just change max-width to max-height and overflow-x to overflow-y
ul, li {
list-style:none;
padding:0;
margin:0;
white-space:nowrap;
max-width:300px;
}
ul{overflow-x:scroll;}
CodePen Live Example
Just set the height of your <ul and give it an overflow: scroll;.
That should do it.
Try this >>>
<div class = "list"></div>
and the css property >>>
/* Hide scrollbar for Chrome, Safari and Opera */
.list::-webkit-scrollbar {
display: none;
}
/* Hide scrollbar for IE, Edge and Firefox */
.list {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
I am trying to make a miniature vertical bar like in this site, where they have the navigation and the vertical bars in between each link. I have tried the solution to a previous question, but when I tried to use 'margin-left' to move the text, the bar wouldn't stay between each link, it'd to this.
HTML
<div id="nav-clearfix">
<div id="nav">
<ul class="nav-pages">
<li>HOME</li>
<li><div class="mini-divider"></div></li>
<li>ROSTER</li>
<li><div class="mini-divider"></div></li>
<li>GALLERY</li>
<li><div class="mini-divider"></div></li>
<li>ABOUT US</li>
<li><div class="mini-divider"></div></li>
<li>SPONSORS</li>
</ul>
</div>
</div>
CSS
#nav-clearfix {
width: 100%;
height: 100px;
background: #000;
}
#nav {
margin-left: 10%;
width: 100%;
}
.nav-pages {
padding-top: 10px;
}
.mini-divider {
position: absolute;
top: 26%;
bottom: 71%;
border-left: 1px solid white;
}
.nav-pages li, .mini-divider {
float: left;
margin-left: 50px;
}
CSS
.nav-pages li:not(:last-child) a:after{
content: "";
/* width: 0px; */
background: white;
margin-left: 20px;
position: absolute;
height: inherit;
color: white;
border: 1px solid white;
height: 15px;
}
Remove The Border Related HTML & CSS
<li><div class="mini-divider"></div></li>
DEMO
You can also use + css selector to give border to the next element no need to add extra element for border
added
*{
margin: 0;
padding: 0;
}
for removing default styles given by browsers
* {
margin: 0;
padding: 0;
}
#nav-clearfix {
width: 100%;
height: 100px;
background: #000;
}
#nav {
width: 100%;
}
.nav-pages {
padding-top: 10px;
text-align:center;
}
.nav-pages li {
display: inline-block;
padding: 0 10px;
}
.nav-pages li + li {
border-left: 1px solid white;
}
<div id="nav-clearfix">
<div id="nav">
<ul class="nav-pages">
<li>HOME</li>
<li>ROSTER</li>
<li>GALLERY</li>
<li>ABOUT US</li>
<li>SPONSORS</li>
</ul>
</div>
</div>
Use this .separator class for vertical separator.
CSS
ul > li{
float: left;
display: block;
position: relative;
}
ul > li > a{
padding: 4px 6px;
display: block;
}
.separator {
background: none repeat scroll 0 0 #222;
border-left: 1px solid #333;
float: left;
height: 30px;
width: 1px;
}
HTML
<ul>
<li >
<a href="#" >Home</a>
</li> <span class="separator"></span>
<li> Link 1 </li> <span class="separator"></span>
<li > Link 2 </li> <span class="separator"></span>
<li> Link3 </li> <span class="separator"></span>
<li > Contact </li>
</ul>
jsfiddle: demo
Here's a Codepen link that displays what I have so far:
http://codepen.io/alih/pen/xijbm
Edited: Here's a new Codepen link, with the nested divs replaced with list items & uls. I welcome suggestions for how to do this without extraneous mark-up, but my major concern remains how to center the Drop-down panel against the borders reaching up to the menu above it.
http://codepen.io/alih/pen/KzsAc
I am building a drop-down menu with the following features:
Multiple levels, but only one level of drop-down. Child lists will be displayed inline immediately beneath their parent elements.
The parent level of the menu will be list items of variable width
The drop-down lists will have a background on them that is always the same width
The drop-down lists will appear to be "connected" to the parent element with "ropes" that connect to the left and right edges of the top level menu items.
And here is the bit I am having trouble with: the background on the drop-down list will be centered against these "ropes". On the Codepen demo, this means that the green & grey panel will be centered against the borders "connecting" the panel to the list item above.
This menu needs to work as far back as IE7, and while I may make flagrant use of extraneous divs to achieve my goal, I may not use JavaScript (which is normally how I would solve this: subtract the width of the parent item from the width of the drop-down and add a negative margin of that amount to the drop-down).
What I want to know is: is there any way this is possible using HTML & CSS alone?
My CSS (Edited):
.other {
float:left
}
ul#topnav,
ul#topnav li,
ul#topnav ul {
list-style: none;
margin: 0;
padding: 0;
}
#topnavblock {
background:grey;
width:100%;
position:relative;
z-index:700;
}
#topnav {
z-index:2;
}
#topnav > li > a {
border-right: 1px solid #999;
}
#topnav li a:hover {
color: #444;
text-shadow: -1px -1px 1px #ffffff;
}
#topnav [class^="current"] {
background: lightyellow;
}
#topnav li a {
color: #893200;
text-decoration: none;
padding: 8px 25px 5px 25px;
text-align: center;
display: block;
text-shadow: 1px 1px 1px #ffffff;
font: bold 14px 'Arvo', serif;
}
#topnav [class^="current"] > a {
color: #FF6600;
}
#topnav [class^="current"] > a:hover {
color: #FF6600;
}
ul#topnav {
position: relative;
z-index: 597;
float: left;
left:20px;
padding: 0;
}
ul#topnav > li {
float: left;
min-height: 1px;
line-height: 1.3em;
vertical-align: middle;
}
ul#topnav > li {
padding:10px 0 14px 0;
}
ul#topnav li.hover,
ul#topnav li:hover {
position: relative;
z-index: 599;
cursor: default;
}
ul#topnav ul {
visibility: hidden;
position: absolute;
top: 100%;
left: 0;
z-index: 598;
width: 100%;
}
ul#topnav li .navwrap1 {
background: yellow;
margin-top: -23px;
padding-top: 23px;
width: 210px;
position: relative;
top: 15px;
}
ul#topnav li .navwrap2 {
background:grey;
padding-bottom: 33px;
}
ul#topnav > li > ul {
border-right: 3px solid grey;
margin-top: -11px;
margin-left: 0;
padding-left: 0;
}
ul#topnav ul .navwrap3 {
border-left:3px solid grey;
padding-top:60px;
}
ul#topnav .navwrap2 li {
float: none;
background:lightgreen;
width:100%;
}
ul#topnav ul ul {
position:relative;
top: 1px;
left: 0;
}
ul#topnav ul li a {
padding: 10px 10px 10px 15px;
}
ul#topnav ul ul li a {
padding: 10px 5px 10px 20px;
}
ul#topnav ul ul ul li a {
padding-left:20px;
}
ul#topnav li:hover ul {
visibility: visible;
}
My mark-up (abbreviated, the whole menu is visible at the CodePen link above):
<div id="topnavblock">
<ul id="topnav">
<li>Here is a menu item
<ul>
<li class="navwrap4">
<ul class="navwrap3">
<li class="navwrap1">
<ul class="navwrap2">
<li>Menu item 1</li>
<li>Another menu item of a different length
<ul>
<li>Sub-menu 2</li>
<li>Sub-menu 2
<ul>
<li>Third level nested menu</li>
<li>This also has a child of different length</li>
</ul>
</li>
<li>Sub-menu 2</li>
</ul>
</li>
<li>Sub-menu 3</li>
</ul><!--end navwrap2-->
</li> <!--end navwrap1-->
</ul><!--end navwrap3-->
</li><!--end navwrap4-->
</ul>
</li>
<li>Item
<ul>
<li class="navwrap4">
<ul class="navwrap3">
<li class="navwrap1">
<ul class="navwrap2">
<li>Sub-menu 3</li>
<li>Sub-menu 3
<ul>
<li>Sub-menu 4</li>
<li>Sub-menu 4</li>
<li>Sub-menu 4</li>
</ul>
</li>
<li>Sub-menu 3</li>
</ul><!--end navwrap2-->
</li> <!--end navwrap1-->
</ul><!--end navwrap3-->
</li><!--end navwrap4-->
</ul>
</li>
</ul>
For ul#topnav li .navwrap1 change margin-top: -23px; to margin: -23px auto 0;. That will center that element.