Marker on top of the menu list items - css

How can i create a marker that appears on top of the menu list items when i hover over them ?Like the one they have here .
It's possible to create with only css ?
EDIT:I don't want the code from you , i just want some tips because i don't know from where to start.

Here is a minimal example of what you want to achieve. The most important parts are the :before pseudo element and the position: relative of <a>. Please notice that the width of those "markers" is the width property of your pseudo element. (In this case it's 2px). Here is the CSS-Part of the marker pseudo element.
a:hover:before {
content:"";
width: 2px;
height: 20px;
background: #000;
position: absolute; /* Only works well when the parent is 'position:relative' */
left: 50%;
top: -10px;
}
Minimal Example Snippet
html * {
box-sizing: border-box;
}
ul {
list-style: none;
}
ul > li {
display: inline-block;
}
li > a {
padding: 5px 10px;
position: relative;
}
a:hover:before {
content: "";
width: 2px;
height: 20px;
background: #000;
position: absolute;
left: 50%;
top: -10px;
}
<ul>
<li>Item 1
</li>
<li>Item 2
</li>
<li>Item 3
</li>
<li>Item 4
</li>
<li>Item 5
</li>
</ul>

If you have a simple navigation along the lines of:
<ul>
<li>Link 1</li>
<li>Link 2</li>
<li>Link 3</li>
</ul>
...then you can create a basic hover effect using the :hover CSS pseudo-class:
ul li a:hover {
border-top: 2px solid black;
}

If we're talking just CSS, have a look at the :hover pseudo class.
This can be combined with visiblity to create something like this:
span {
visibility: hidden;
font-weight: bold;
}
p:hover span {
visibility: visible;
}
<p><span>| </span>hello</p>

Try this only CSS:
CSS
.menu-wrap {
overflow: hidden;
width: 100%;
height: auto;
position:relative;
}
.menu-wrap div{
position:relative;
margin-top:100px;
display:inline-block;
border:2px solid red;
width:100px;
height:10px;
padding:10px;
}
.menu-wrap div:hover:before{
content:'|'; /*--------you can put image here as marker*/
position:absolute;
bottom:40;
font-size:1.3em;
margin-left:50px;
font-weight:bold;
}
HTML
<div class="menu-wrap">
<div class="menu-item"></div>
<div class="menu-item"></div>
<div class="menu-item"></div>
</div>
See if it is what you want.

Related

Why adding sticky to CSS drop down menu breaks it?

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>

Why does the main part repaint in this case?

Here is a simple jsbin example: http://jsbin.com/gusaditako/edit?html,css,output
Can anyone explain why the main part is repainting when hovering over menu items? (enable Paint flashing from chrome devtools to make sure).
As I see the pseudo :before selector is to blame but can't figure out exactly why. If you delete the last ul#menu li:hover:before part it doesn't trigger the main part repaint anymore...
Code from the above jsbin:
HTML:
<div id="sidebar">
<ul id="menu">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</div>
<div id="main">Main part. Why does this repaint on menu hover?</div>
CSS:
ul {
margin: 0;
padding: 0;
list-style: none;
}
#sidebar {
width: 200px;
float: left;
background-color: lightgreen;
}
#main {
margin-left: 200px;
width: 500px;
}
ul#menu li {
height: 30px;
line-height: 30px;
padding-left: 20px;
position: relative;
}
ul#menu li:hover {
background-color: lightblue;
}
ul#menu li:hover:before {
content: "";
width: 4px;
background-color: red;
position: absolute;
left: 0;
top: 0;
height: 100%;
}
Well I guess Chrome internally thinks it has to repaint the right part as you're inserting a new element which could possibly affect the main content. One quick fix would be to set the whole sidebar to position:absolute; if that's possible in your case.
#sidebar {
position: absolute;
width: 200px;
float: left;
background-color: lightgreen;
}
http://jsbin.com/lilusajufe/4/edit?html,css,output

Use CSS to position two elements at the same location and make container large enough to hold them

So I have two (or potentially more) elements that I want to occupy the same space. They need to fit inside a container element whose size should be automatically made large enough to contain them. I currently have a couple of possibilities that don't quite work, shown below:
.first {
display: inline-block;
position: relative;
border: 1px solid black;
padding: 1px;
}
.first > li {
display: block;
padding: 0px;
margin: 0px;
position: relative;
}
.second {
display: inline-block;
position: relative;
border: 1px solid black;
padding: 1px;
}
.second > li {
display: block;
padding: 0px;
margin: 0px;
position: absolute;
}
.third {
display: inline-block;
border: 1px solid black;
padding: 1px;
}
.third > li {
padding: 0px;
margin: 0px;
float: left;
margin-right: -100%;
}
<div style="float:right; width: 75%">(Attempt 1: note that the two items are not superimposed, but the container is large enough to hold them)</div>
<ul class="first">
<li>Item number 1</li>
<li>Item number 2</li>
</ul>
<br><br>
<div style="float:right; width: 75%">(Attempt 2: note that this time they are superimposed, but no space is allocated in the container for them)</div>
<ul class="second">
<li>Item number 1</li>
<li>Item number 2</li>
</ul>
<br><br><br><br>
Edited to add a third attempt:<br>
<ul class="third">
<li>Item number 1</li>
<li>Item number 2</li>
</ul>
Ideally I'm looking for a pure CSS solution, but it only needs to work on webkit-based browsers (i.e. chrome / safari).
Updated: add a third attempt that gets the two items overlapping, but allocates enough space to hold both of them side by side, which still doesn't really get me where I want to be.
For reference: I don't know the sizes of the items in advance, so can't (for example) size the container to hold the largest and make the rest overlap it.
like this?
ul {
display: inline-block;
position: relative;
border: 1px solid black;
padding:0; margin:0;
}
ul li {
display: block;
position: absolute;
top:0; left:0;
}
ul li:nth-child(1) {
position:relative;
}
<ul>
<li>Item number 1</li>
<li>Item number 2</li>
</ul>
absolute positioning:
Setting position: absolute on all <li> elements, then setting position: relative on the .current (there are many ways to select a dominant <li> and using a class is just one of them) <li> gives what I think you're after.
We can then set the visibility of every <li> to hidden, and set the visibility of .current to visible to reduce the visual clutter:
ul {
display: inline-block;
padding: .2em .3em;
list-style: none;
border: 2px solid black;
}
li {
position: absolute;
visibility: hidden;
}
li.current {
position: relative;
visibility: visible;
}
<ul>
<li>a</li>
<li>abc</li>
<li>abcdefg</li>
<li>foo bar baz</li>
<li>i dunno lol</li>
<li class="current">42</li>
</ul>
This approach is effectively identical to using display none and list-item:
ul {
display: inline-block;
padding: .2em .3em;
list-style: none;
border: 2px solid black;
}
li {
display: none;
}
li.current {
display: list-item;
}
<ul>
<li>a</li>
<li>abc</li>
<li>abcdefg</li>
<li>foo bar baz</li>
<li>i dunno lol</li>
<li class="current">42</li>
</ul>
Or for the container to always be wide enough for the longest string:
Setting the height of every <li> to 0 and giving just the .current its initial height back to push the <ul>'s border out, we get something like this:
ul {
display: inline-block;
padding: .2em .3em;
list-style: none;
border: 2px solid black;
}
li {
height: 0;
visibility: hidden;
}
li.current {
height: initial;
visibility: visible;
}
<ul>
<li>a</li>
<li>abc</li>
<li>abcdefg</li>
<li>foo bar baz</li>
<li>i dunno lol</li>
<li class="current">42</li>
</ul>
Using JavaScript :O
Although the question calls for a CSS solution, where that might be impossible or unreliable, we can always rely on JS.
In the case that both the width and height of the child <li>s may be different, and that the container should be both wide and high enough for every child, JS provides.
The method below uses getComputedStyle to get the width and height of the relatively rendered <li> elements, and sets position: absolute on them all as they're read.
The parent <ul> then has its width and height set to the largest width and heights of the child <li>s.
The result is a <ul> that's wide and high enough to contain every child <li>, but with all the children positioned absolutely;
var widths = [], heights = [];
// loop through all the li elements
document.querySelectorAll( "li" ).forEach( function( v ) {
// get the computed styles for each li element
var ecs = window.getComputedStyle( v );
// push the width into the widths array
widths.push( ecs.width );
// push the height into the heights array
heights.push( ecs.height );
// set position:absolute on this li element
v.style.position = "absolute";
} );
document.querySelector( "ul" ).setAttribute( "style",
/* sort the widths array and pop the last (and therefore largest) value
then apply it to the width of the ul. */
"width:" + widths.sort().pop() +
/* sort the heights array and pop the last (and therefore largest) value
then apply it to the height of the ul. */
";height:" + heights.sort().pop()
);
ul {
display: inline-block;
padding: .2em .3em;
list-style: none;
border: 2px solid black;
}
li {
visibility: hidden;
}
li.current {
visibility: visible;
}
<ul>
<li>a</li>
<li>abc</li>
<li>abcdefg<br>1234567</li>
<li>foo bar baz</li>
<li>i dunno lol</li>
<li class="current">42</li>
</ul>
display: flex and visibility: hidden
I was wondering if visibility: collapse might be useful, and found a CSS-tricks.com article linking to a csswg.org draft suggesting that visiblity: collapse may be used on <li>s with display: flex to acheive pretty much exactly what you're after.
I couldn't get it to work, and noticed that their own example was not using either display: flex or visibility: collapse!
They are instead manipulating the heights of the children.
Since it is a draft, this may become a useable solution down the road.
I am unfamiliar with the use of flexboxes (deep shame) so wouldn't be surprised if a solution using them exists. I just don't (at this time) know it.
Why not do it like this:
.second > li {
display: inline-block;
padding: 0px;
margin: 0px;
position: absolute;
border-top: 1px solid black;
border-bottom: 1px solid black;
padding: 1px;
left:0;
}
.second > li:first-child {
border-left: 1px solid black;
}
.second > li:last-child {
border-right: 1px solid black;
}
<ul class="second">
<li>Item number 1</li>
<li>Item number 2 greater length</li>
</ul>
First, you should include your two elements inside a container div that you want to have and write property as:
position: absolute;
top: 0;
left: 0;
And, make your container position property as:
position: relative

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;
}

CSS navigation submenu and seperator

I have created a navigation bar that is centered with CSS which works. Each li item is separated with a border which is a background image. When hovering on the nav items, the separator disappears because the hover changes the background (I guess) but I wonder how I can fix this, padding or margin can't work because it will just shift the li element.
Second problem is that the sub menu items aren't displaying correctly and I have no idea why...
Demonstration: http://jsfiddle.net/Xenios/tfbhh/9/embedded/result/
The code: http://jsfiddle.net/Xenios/tfbhh/9/
I'm trying to get this to work for almost a week, and I'm quite tired of it, so I'm looking here for support.
Separator
As you know the main bar (nav_container) has a background image, which makes up the look of the button. The background for each button is the separator and nothing else (10px on the right). So, when your on hover background shows, because its park of the non-hover background.
In order to fix this you need to put the separator in it's own <li>, with the non-hover background. Then when you hover the elements they can easily change to your current on hover image with.
If you don't want to separate the <li> elements then, you will have to will have to make individual full width images for each button, but looking at the way you've gone about making this menu, I doubt you will want to do this.
Here is your working example (I only did the first few buttons): http://jsfiddle.net/tfbhh/43/
Submenu
As I mentioned above, you have set the container background image, you haven't done this on your submenu items, so thats why they don't have a larger looking button. Use your developer toolbar (F12) to see the styling and this should clear it up.
You can use a left padding equal to the width of the separator on the li and change only the background on the a. Also I noticed you used class="separator" on all but the first list item. You could replace that with the :first-child pseudo selector. Then you would get something like this:
li:first-child { padding-left: 0; background: transparent; }
li { padding-left: 3px; background: url(separator.png) no-repeat; }
li a { line-height: 40px; padding: 0 15px; }
li a:hover { background: url(anchor-hover.png) repeat-x; }
Edit: The CSS above covers the core styling of this solution. Here's a working example (using background colors):
http://jsfiddle.net/haa5X/3/
The complete CSS:
ul { overflow: hidden; background: green; }
li:first-child { padding-left: 0; }
li { padding-left: 3px; float: left; background: red; }
li a { float: left; line-height: 40px; padding: 0 15px; background: yellow; }
li a:hover { background: purple; }
The complete HTML:
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
Edit 2: Sorry, missed the part of the submenu:
http://jsfiddle.net/haa5X/4/
The complete CSS:
ul { overflow: hidden; margin: 0; background: green; }
ul > li:first-child { padding-left: 0; }
ul > li { padding-left: 3px; float: left; background: red; }
ul > li a { float: left; line-height: 40px; padding: 0 15px; background: yellow; }
ul > li a:hover { background: purple; }
li ul { display: none; position: absolute; margin-top: 40px; }
li:hover ul { display: block; }
li li { padding-left: 0; float: none; display: block; }
li li a { float: none; display: block; width: 100%; }
The complete HTML:
<ul>
<li>Item 1</li>
<li>Item 2
<ul>
<li>First sub item</li>
<li>Sub item 2</li>
<li>Last sub item</li>
</ul>
</li>
<li>Item 3</li>
</ul>
​

Resources