HTML navigation of tabs broken - javascript

I have my portfolio website in English and translated it in to German with a combination of JSON and Javascript. I have a dropdown menu to pick a language, and once a language is picked a javascript script switches the content of every indicated id with the content of the other language.
I also have a navigation menu which gets underlined when you hover over it and when you click it, it takes you to its respective area on the website. However, the moment the user switches the language, both of these functions do not work anymore i.e the href="#header# as well as nav ul li a:hover::after{} break.
You can mimic this behaviour at alexverheecke.com. Before selecting a language, you can hover over "Home", "About" and it will become underlined and upon clicking, will take you to the section. Once you switch language, this breaks.
I'm assuming this will be a bit time-consuming for someone to look at but I would appreciate any ideas that could help in fixing this.
const jsonDE = {
"_Home": "Startseite",
// ...
}
document.querySelector('#language').addEventListener("change", function() {
if (this.value == "๐Ÿด๓ ง๓ ข๓ ฅ๓ ฎ๓ ง๓ ฟ ENG") {
for (let key in jsonEN) {
document.querySelector('#' + key).textContent = jsonEN[key]
}
else if (this.value == "๐Ÿ‡ฉ๐Ÿ‡ช DE") {
for (let key in jsonDE) {
document.querySelector('#' + key).textContent = jsonDE[key]
}
}
});
nav {
display: flex;
/* so image and links side-by-side */
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
}
nav ul li {
display: inline-block;
/* so horizontally aligned */
list-style: none;
margin: 10px 20px;
/* space between links */
}
nav ul li a {
color: white;
text-decoration: none;
font-size: 18px;
position: relative;
/* because abolute in :after */
}
nav ul li a::after {
content: '';
width: 0%;
height: 3px;
background: #3a65ed;
position: absolute;
left: 0;
bottom: -6px;
transition: 0.2s;
}
nav ul li a:hover::after {
width: 100%;
}
<nav>
<ul id="sidemenu">
<li id="_Home">Home </li>
<select id="language" class="language">
<option>๐Ÿด๓ ง๓ ข๓ ฅ๓ ฎ๓ ง๓ ฟ ENG</option>
<option>๐Ÿ‡ฉ๐Ÿ‡ช DE</option>
</select>
</ul>
</nav>

If you check your site with the DOM inspector you can see that after you change language the a elements have been removed from within the li of your navigation bar.
I would assume this is because your JSON content holds HTML, yet you're updating the textContent of the element. Change textContent to innerHTML and try again.
Also note that you can simplify the language switching logic by putting the language code as a property within a single object of the JSON. Then you only need one loop to work with every language. Note the use of a value attribute on the option elements to avoid the need to have to cater for the subscript language codes which have been added to the text within the UI of the option.
Below is a working example with both of the above issues corrected:
// mock JSON object...
const translations = {
"DE": {
"_Home": "Startseite"
},
"EN": {
"_Home": "Home"
},
"IT": {
"_Home": "Casa"
}
}
// content switching logic
document.querySelector('#language').addEventListener("change", function() {
for (let key in translations[this.value]) {
document.querySelector('#' + key).innerHTML = translations[this.value][key]
}
});
nav {
display: flex;
/* so image and links side-by-side */
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
}
nav ul li {
display: inline-block;
/* so horizontally aligned */
list-style: none;
margin: 10px 20px;
/* space between links */
}
nav ul li a {
/* color: white; removed so white text is visible */
text-decoration: none;
font-size: 18px;
position: relative;
/* because abolute in :after */
}
nav ul li a::after {
content: '';
width: 0%;
height: 3px;
background: #3a65ed;
position: absolute;
left: 0;
bottom: -6px;
transition: 0.2s;
}
nav ul li a:hover::after {
width: 100%;
}
<nav>
<ul id="sidemenu">
<li id="_Home">Home </li>
</ul>
</nav>
<select id="language" class="language">
<option value="EN">๐Ÿด๓ ง๓ ข๓ ฅ๓ ฎ๓ ง๓ ฟ ENG</option>
<option value="DE">๐Ÿ‡ฉ๐Ÿ‡ช DE</option>
<option value="IT">แดตแต€ IT</option>
</select>

Related

Toggle An Element And Also Remove Its Visibility When Clicking Outside Of The Element - JavaScript

I have a navigation with two items that have submenus. I currently have a class that toggles on and off that shows these submenus when clicked.
I would like it so when I click anywhere on the page they disappear if they are visible.
At the moment I think my code is a bit long-winded for what it currently achieves and perhaps it would be better to use e.target when clicking?
You can currently toggle the menus off-and-on by clicking either menu-item (this includes clicking the visible menu item a second time).
I thought to remove the 'visible' class by clicking outside of the menu-item I could do a simple document.addEventListener('click', function(e) {}) on the entire document to remove the 'visible' class if it was showing, but that doesn't seem to work.
Note: I need to do this without using a blur event listener
Codepen: https://codepen.io/emilychews/pen/bGWVVpq
var menu_item_1 = document.getElementById('item-1'),
menu_item_2 = document.getElementById('item-2'),
sub_menu_item_1 = document.getElementById('sub-item-1'),
sub_menu_item_2 = document.getElementById('sub-item-2')
if (menu_item_1) {
menu_item_1.addEventListener('click', function(e){
sub_menu_item_1.classList.toggle('visible')
// hide submenu 2
sub_menu_item_2.classList.remove('visible')
}, false)
}
if (menu_item_2) {
menu_item_2.addEventListener('click', function(e){
sub_menu_item_2.classList.toggle('visible')
// hide submenu 1
sub_menu_item_1.classList.remove('visible')
}, false)
}
body {
display: flex;
justify-content: center;
margin: 0;
height: 100vh;
width: 100%;
}
header {
margin-top: 2rem;
display: flex;
width: 50%;
justify-content: space-evenly;
align-items: center;
padding: 1rem;
background: red;
height: 2rem;
}
.menu-item {
position: relative;
padding: 1rem;
background: yellow;
cursor: pointer;
}
.submenu {
display: none; /* changes to 'block' with javascript */
padding: 1rem;
background: lightblue;
position: absolute;
top: 4rem;
left: 0;
width: 6rem;
}
.submenu.visible {
display:block;
}
<header>
<div id="item-1" class="menu-item menu-item-1">ITEM 1
<div id="sub-item-1" class="submenu submenu-1">SUB-ITEM-1</div>
</div>
<div id="item-2" class="menu-item menu-item-2">ITEM 2
<div id="sub-item-2" class="submenu submenu-2">SUB-ITEM-2</div>
</div>
</header>
There are a few different ways to achieve this, not all of which involve JS, I'll outline a few possible approaches below:
Pure CSS:
The first (and most likely easiest) is to use css-only. This again uses tabindex="-1" like Samuel's answer to make your menu item buttons focusable. Once a button is focused, you can apply some CSS to the focused item's associated submenu using the :focus pseudo-class selector:
.menu-item:focus > .submenu { /* select the focused menu-item's child elements with the class submenu */
display: block;
}
See example below:
body {
display: flex;
justify-content: center;
margin: 0;
height: 100vh;
width: 100%;
}
header {
margin-top: 2rem;
display: flex;
width: 50%;
justify-content: space-evenly;
align-items: center;
padding: 1rem;
background: red;
height: 2rem;
}
.menu-item {
position: relative;
padding: 1rem;
background: yellow;
cursor: pointer;
}
.submenu {
display: none; /* changes to 'block' with CSS */
padding: 1rem;
background: lightblue;
position: absolute;
top: 4rem;
left: 0;
width: 6rem;
}
.menu-item:focus > .submenu {
display: block;
}
<header>
<div id="item-1" class="menu-item menu-item-1" tabindex="-1">ITEM 1
<div id="sub-item-1" class="submenu submenu-1">SUB-ITEM-1</div>
</div>
<div id="item-2" class="menu-item menu-item-2" tabindex="-1">ITEM 2
<div id="sub-item-2" class="submenu submenu-2">SUB-ITEM-2</div>
</div>
</header>
The main drawback to this is that we're using :focus, meaning that if you click on a menu-item again, it will remain focused rather than bluring, which as a result will keep the menu item in-view rather than hiding it. The below approaches that use JS handle this case though:
Adding an event-listener to the document:
Another possible solution is to update your JS. This involves selecting all menu items and submenu items using querySelectorAll(). You can then add event listeners to your menu-items by looing through the NodeList returned by the call to .querySelectorAll(). When you click on a menu-item, you can grab its associated submenu item using .querySelector() on the current menuItem. In order to hide the items when you click elsewhere on the screen, you can listen for click events on the document by adding an event listener to that, and hide your submenu items accordingly. Within your event listeners that you add to your menu items, you can call .stopPropagation() to prevent the click event on the menu items from bubbling up to the document and causing the document event-listener to execute (and hide all items).
const menuItems = document.querySelectorAll(".menu-item"); // Get all menu items in an array-like structure (NodeList)
const submenuItems = document.querySelectorAll(".submenu"); // select all submenu items
const hideMenus = (menus, ignore) => menus.forEach(menu => { // loop through all items (use: [...menus].forEach((menu) => {) for better browser support)
if (menu !== ignore) // if we encounter an element that we want to keep visible, skip it, otherwise, remove its visibility
menu.classList.remove("visible");
});
menuItems.forEach(menuItem => { // loop through the NodeList menu items
menuItem.addEventListener("click", (e) => {
e.stopPropagation(); // stop event from bubbling up to the document and executing the below `document.addEventListener()` when menu item is clicked
if (e.target === menuItem) { // don't hide when we click on a sub-menu-item (e.target = child sub-menu-item if that is clicked)
const thisSubmenu = menuItem.querySelector(".submenu");
thisSubmenu.classList.toggle('visible'); // toggle visibility of submenu under our item
hideMenus(submenuItems, thisSubmenu); // hide all other submenus
}
});
});
document.addEventListener("click", (e) => {
hideMenus(submenuItems);
});
body {
display: flex;
justify-content: center;
margin: 0;
height: 100vh;
width: 100%;
}
header {
margin-top: 2rem;
display: flex;
width: 50%;
justify-content: space-evenly;
align-items: center;
padding: 1rem;
background: red;
height: 2rem;
}
.menu-item {
position: relative;
padding: 1rem;
background: yellow;
cursor: pointer;
}
.submenu {
display: none;
/* changes to 'block' with javascript */
padding: 1rem;
background: lightblue;
position: absolute;
top: 4rem;
left: 0;
width: 6rem;
}
.submenu.visible {
display: block;
}
<header>
<div id="item-1" class="menu-item menu-item-1">ITEM 1
<div id="sub-item-1" class="submenu submenu-1">SUB-ITEM-1</div>
</div>
<div id="item-2" class="menu-item menu-item-2">ITEM 2
<div id="sub-item-2" class="submenu submenu-2">SUB-ITEM-2</div>
</div>
</header>
Using event delegation:
You can update the above example to use event delegation, which allows you to only use one event listener on the document rather than adding one per menu item (thus helping limit the resources used by your browser). You can then use e.target and .closest() to determine what element you clicked on (see code comments for details):
const submenuItems = document.querySelectorAll(".submenu"); // select all submenu items
const hideMenus = (menus, ignore) => menus.forEach(menu => { // loop through all items (use: [...menus].forEach((menu) => {) for better browser support)
if(menu !== ignore) // if we encounter an element that we want to keep visible, skip it, otherwise, remove its visibility
menu.classList.remove("visible");
});
document.addEventListener("click", (e) => {
const clickedItem = e.target, menuItem = clickedItem.closest(".menu-item");
// v-- use `= menuItem && menuItem.querySelector(...)` for better browser support
const thisSubmenu = menuItem?.querySelector(".submenu"); // grab the submenu from the menuItem we clicked on (or parent menuItem if we clicked on a submenu item)
if(clickedItem === menuItem) // we clicked on a menu-item
thisSubmenu.classList.toggle('visible'); // toggle visibility of submenu under our menu-item
hideMenus(submenuItems, thisSubmenu);
});
body {
display: flex;
justify-content: center;
margin: 0;
height: 100vh;
width: 100%;
}
header {
margin-top: 2rem;
display: flex;
width: 50%;
justify-content: space-evenly;
align-items: center;
padding: 1rem;
background: red;
height: 2rem;
}
.menu-item {
position: relative;
padding: 1rem;
background: yellow;
cursor: pointer;
}
.submenu {
display: none; /* changes to 'block' with javascript */
padding: 1rem;
background: lightblue;
position: absolute;
top: 4rem;
left: 0;
width: 6rem;
}
.submenu.visible {
display:block;
}
<header>
<div id="item-1" class="menu-item menu-item-1">ITEM 1
<div id="sub-item-1" class="submenu submenu-1">SUB-ITEM-1</div>
</div>
<div id="item-2" class="menu-item menu-item-2">ITEM 2
<div id="sub-item-2" class="submenu submenu-2">SUB-ITEM-2</div>
</div>
</header>
I also added console.log on each submenu to make sure they are interactive before the menu closes.
const menus = Array.from(document.querySelectorAll('.menu-item'));
function handleOnClickOutsideMenu(e) {
const target = menus.filter(menu => menu.contains(e.target));
if (target.length) {
// user is clicking inside a menu: don't do anything.
// this is handled by handleOnMenuToggle.
return;
}
// close all the menus in the page
menus.forEach(menu => menu.classList.remove('expanded'));
// we don't need it anymore (it is added dynamically in the handleOnMenuToggle)
document.removeEventListener('click', handleOnClickOutsideMenu);
}
function handleOnMenuToggle(e) {
// close other menus
menus
.filter(menu => menu !== e.currentTarget)
.forEach(menu => menu.classList.remove('expanded'));
// toggle current menu
e.currentTarget.classList.toggle('expanded');
// Important optimization:
// we want the click event on the document only when a menu is expanded
if (e.currentTarget.classList.contains('expanded')) {
document.addEventListener('click', handleOnClickOutsideMenu);
} else {
document.removeEventListener('click', handleOnClickOutsideMenu);
}
}
menus.forEach(menu => {
menu.addEventListener('click', handleOnMenuToggle);
});
body {
display: flex;
justify-content: center;
margin: 0;
height: 100vh;
width: 100%;
}
header {
margin-top: 2rem;
display: flex;
width: 50%;
justify-content: space-evenly;
align-items: center;
padding: 1rem;
background: red;
height: 2rem;
}
.menu-item {
position: relative;
padding: 1rem;
background: yellow;
cursor: pointer;
}
.submenu {
display: none;
padding: 1rem;
background: lightblue;
position: absolute;
top: 4rem;
left: 0;
width: 6rem;
}
/* adding .expanded on menu-item so it can handle multiple sub menu */
.menu-item.expanded .submenu {
display: block;
}
<header>
<div id="item-1" class="menu-item menu-item-1">ITEM 1
<div id="sub-item-1" class="submenu submenu-1" onclick="console.log(this)">SUB-ITEM-1</div>
</div>
<div id="item-2" class="menu-item menu-item-2">ITEM 2
<div id="sub-item-2" class="submenu submenu-2" onclick="console.log(this)">SUB-ITEM-2</div>
</div>
</header>
One way to solve this would be to take advantage of focus and blur events. div elements do not receive focus by default, but we can add the tabindex attribute to fix that.
When you click the div it becomes focused, so we simply listen for a blur event and hide the div.
var menu_item_1 = document.getElementById('item-1'),
menu_item_2 = document.getElementById('item-2'),
sub_menu_item_1 = document.getElementById('sub-item-1'),
sub_menu_item_2 = document.getElementById('sub-item-2')
if (menu_item_1) {
menu_item_1.addEventListener('click', function(e){
sub_menu_item_1.classList.toggle('visible')
// hide submenu 2
sub_menu_item_2.classList.remove('visible')
}, false)
}
if (menu_item_2) {
menu_item_2.addEventListener('click', function(e){
sub_menu_item_2.classList.toggle('visible')
// hide submenu 1
sub_menu_item_1.classList.remove('visible')
}, false)
}
// listen for blur events
menu_item_1.addEventListener('blur', function(e){ sub_menu_item_1.classList.remove('visible')
})
menu_item_2.addEventListener('blur', function(e){ sub_menu_item_2.classList.remove('visible')
})
body {
display: flex;
justify-content: center;
margin: 0;
height: 100vh;
width: 100%;
}
header {
margin-top: 2rem;
display: flex;
width: 50%;
justify-content: space-evenly;
align-items: center;
padding: 1rem;
background: red;
height: 2rem;
}
.menu-item {
position: relative;
padding: 1rem;
background: yellow;
cursor: pointer;
}
.submenu {
display: none; /* changes to 'block' with javascript */
padding: 1rem;
background: lightblue;
position: absolute;
top: 4rem;
left: 0;
width: 6rem;
}
.submenu.visible {
display:block;
}
<header>
<div id="item-1" class="menu-item menu-item-1" tabindex="-1">ITEM 1
<div id="sub-item-1" class="submenu submenu-1" tabindex="-1">SUB-ITEM-1</div>
</div>
<div id="item-2" class="menu-item menu-item-2" tabindex="-1">ITEM 2
<div id="sub-item-2" class="submenu submenu-2" tabindex="-1">SUB-ITEM-2</div>
</div>
</header>

Addressing issue with disappearing li elements in navbar (HTML, CSS, JS)

document.addEventListener("DOMContentLoaded", () => {
let menuBtn = document.querySelector("#menu-button");
let menu = document.querySelector("#menu");
let menuItems = menu.getElementsByTagName("li");
menuBtn.addEventListener("click", e => {
if (e.target.innerText === ("โœ•")) {
e.target.innerText = "โ˜ฐ";
[...menuItems].forEach(item => item.style.display = "none");
} else if (e.target.innerText === "โ˜ฐ") {
e.target.innerText = "โœ•";
[...menuItems].forEach(item => item.style.display = "block");
}
});
});
header {
width: 100%;
height: 100px;
}
#menu {
display: flex;
flex-direction: row;
margin: 0 auto;
justify-content: space-around;
font-size: 2rem;
}
#menu-button {
display: none;
}
li {
list-style-type: none;
}
a {
text-decoration: none;
color: rgb(0, 0, 0);
}
#media screen and (max-width: 1050px) {
#menu {
flex-direction: column;
width: 100%;
height: 100%;
}
#menu li {
padding: 1.5rem;
display: none;
}
#menu-button {
display: block;
font-size: 3rem;
cursor: pointer;
outline: none;
border: none;
}
}
<header>
<nav>
<button id="menu-button">โ˜ฐ</button>
<ul id="menu">
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</nav>
</header>
It's a simple nav menu with desktop-first approach that uses flexbox.
Viewport is less than 1050px and therefore shows hamburger button
Hamburger button is clicked to show menu in dropdown form. Hamburger button changes to "X".
"X" is clicked. The JS code changes all li elements to display: none
PROBLEM: Viewport is increased beyond breakpoint of 1050px. Since li elements were changed to display: none, menu is not shown.
Would appreciate suggestions on how to address this.
Also, smaller but nagging issue.
Viewport is less than 1050px and therefore shows hamburger button
Hamburger button is clicked to show menu in dropdown form. Hamburger button changes to "X".
Viewport is increased beyond breakpoint of 1050p and then back below breakpoint. Since all li elements were set to display: block in JS code, the dropdown menu appears. I'd like to make it so that the hamburger icon appears whenever viewport size is decreased.
Thanks for all and any help!
Add & remove CSS classes instead of setting the inline style. Doing this will give CSS more control. Inline styles can only be overwritten by using !important and that will make it even harder to overwrite.
Instead of showing and hiding every individual <li>, only hide the parent <ul>. That will also hide all the children inside of it.
The example below adds and removes an active class to the #menu element when clicking the menu button. This active class shows the #menu on mobile where it is hidden. On larger screens, #menu is always shown.
document.addEventListener("DOMContentLoaded", () => {
let menuBtn = document.querySelector("#menu-button");
let menu = document.querySelector("#menu");
// First question:
// Add a class instead of inline styles.
menuBtn.addEventListener("click", e => {
if (e.target.innerText === ("โœ•")) {
e.target.innerText = "โ˜ฐ";
menu.classList.remove('active');
} else if (e.target.innerText === "โ˜ฐ") {
e.target.innerText = "โœ•";
menu.classList.add('active');
}
});
// Second question:
// Watch a media query, reset the button and hide the
// menu when changing from large to a small size.
const mediaQuery = window.matchMedia('screen and (max-width: 1050px)');
mediaQuery.addEventListener('change', ({ matches }) => {
if (!matches) return;
menuBtn.innerText = "โ˜ฐ";
menu.classList.remove('active');
});
});
header {
width: 100%;
height: 100px;
}
#menu {
display: flex;
flex-direction: row;
margin: 0 auto;
justify-content: space-around;
font-size: 2rem;
}
#menu-button {
display: none;
}
li {
list-style-type: none;
}
a {
text-decoration: none;
color: rgb(0, 0, 0);
}
#media screen and (max-width: 1050px) {
#menu {
display: none;
flex-direction: column;
width: 100%;
height: 100%;
}
#menu.active {
display: flex;
}
#menu li {
padding: 1.5rem;
}
#menu-button {
display: block;
font-size: 3rem;
cursor: pointer;
outline: none;
border: none;
}
<header>
<nav>
<button id="menu-button">โ˜ฐ</button>
<ul id="menu">
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</nav>
</header>

How to get mega menu with nested UL without JS?

We have the following html structure for our menu (see codepin). We would like to modify the menu without having to use JS on page load to move any elements around.
Here is what I tried, but cannot get the custom-dropdown to show like the screenshot below.
Here is my codepin that I have so far, but we are having hard time getting it to align in two columns like the screenshot. The goals below have been simplified, but should be applicable to other links like Category and Company as well since they follow similar structure.
Goal (see screenshot):
On hover of Testing 1, Collaboratively testing 1 and transition accurate should display
On hover of Collaboratively testing 1 then the Enthusiastically communicate cross-platform and Uniquely reconceptualize accurate should display
Screenshot:
Underline below Testing 1 is to simulate on hover effect
Grey background behind Collaboratively Testing is to indicate on hover effect, which results in goal #2 where they are display to the right.
Multi-Level Drop Down Menu with Pure CSS
ul {
list-style: none;
padding: 0;
margin: 0;
background: #1bc2a2;
}
ul li {
display: block;
position: relative;
float: left;
background: #1bc2a2;
}
/* This hides the dropdowns */
li ul { display: none; }
ul li a {
display: block;
padding: 1em;
text-decoration: none;
white-space: nowrap;
color: #fff;
border-bottom: 3px solid #1bc2a2
}
ul li a:hover {border-bottom: 3px solid #2c3e50}
/* Display the dropdown */
li:hover > ul {
display: block;
position: absolute;
}
li:hover li { float: none; }
li:hover a { background: #1bc2a2; }
li:hover li a:hover { background: #2c3e50; }
.main-navigation li ul li { border-top: 0; }
/* Displays second level dropdowns to the right of the first level dropdown */
ul ul ul {
left: 100%;
top: 0;
}
/* Simple clearfix */
ul:before,
ul:after {
content: " "; /* 1 */
display: table; /* 2 */
}
ul:after { clear: both; }
here comes your html code
<h1>Multi-Level Drop Down Menu with Pure CSS</h1>
<ul class="main-navigation">
<li>Home</li>
<li>Front End Design
<ul>
<li>HTML</li>
<li>CSS
<ul>
<li>Resets</li>
<li>Grids</li>
<li>Frameworks</li>
</ul>
</li>
<li>JavaScript
<ul>
<li>Ajax</li>
<li>jQuery</li>
</ul>
</li>
</ul>
</li>
</ul>

Change one link into two on hover

I'm trying to create a link that changes into two links when you hover over the text. You can see something like what I want to do here: https://www.kenzo.com/en/ You can see that the collections link changes into two separate links for men and women when you hover over the link. At the moment I have managed to create a link that separates into two words when hovered over but not into two links.
Here is my HTML code:
<li><span>Collection</span></li>
And here is my CSS code:
#nav-item1:hover span {
display:none;
}
#nav-item1:hover:before {
content: "Men Women";
}
So the text changes which is great, but I haven't quite figured out how to turn the text into two separate links. I'm not sure if I have to use JS for this or not, as my JS knowledge terrible.
Any ideas?
If I understand you right you can try something like this:
li {
list-style: none;
}
li a {
display: none;
margin-left: .3em;
}
li:hover span {
display: none;
}
li:hover a {
display: inline-block;
}
<li>
<span>Collection</span>
Man
Women
</li>
Okay so here is a small breakdown of how you can achieve this.
There is a block element on the top of things.
Then there are two hidden elements that are children of the block element.
And when you hover over the block element the other ones are shown.
You can also hide the child element that contains the text on hover.
.block:hover .hide {
display: inline;
}
.block {
color: black;
font-size: 20px;
}
.hide {
display: none;
}
<div class="block">
<span class="default text">Hover</span>
<a class="hide" href="#">Snowball</a>
<a class="hide" href="#">Kitten</a>
<div>
.splitted {
display: none;
}
.links:hover .one-link {
display: none;
}
.links:hover .splitted {
display: inline;
}
<span class="links">
Collection
Men
Women
</span>
Please try this
#nav-item1{
position: relative;
}
#nav-item1:before,
#nav-item1:after{
display: none;
position: absolute;
top: 100%;
color: #000;
}
#nav-item1:hover:before,
#nav-item1:hover:after{
display: block;
}
#nav-item1:before{
content: 'Men';
right: 50%;
}
#nav-item1:after{
content: 'Women';
left: 50%;
color: green;
}
<ul>
<li><span>Collection</span>
</li>
</ul>

hidden submenu in nav bar displaying on hover but not dropping down

I am very new to javascript, so I apologize in advance if I waste anyone's time with a problem that may have a "duh" answer :-)
I am creating a navigation bar for a webpage. It starts off as an unordered list, and I am styling it to float the list items horizontally across the page. That part works fine for me.
I started to work at incorporating an unordered list as a submenu of one of my original list items. When I hover the mouse over the main list item, the submenu items appear, and when I mouse out, the submenu items disappear. The problem is that when the submenu items appear, they display on top of the navigation link to the left, instead of breaking out and dropping down below the link that I am hovering over. I tried setting the position to relative, but then it just shoved the submenu to the right.
I think the problem may be with my css. If I do not apply the external style sheet, then things seem to work better.
Here is my html:
<ul class="nav">
<li>Home</li>
<li>Department Members</li>
<ul id="menu" style="display:none;position:absolute">
<li>Brian Kendricks</li>
<li>Tim Jones</li>
<li>David Kline</li>
</ul>
<li>Systems Used</li>
<li>System Status</li>
<li>Projects</li>
</ul>
My css is:
.nav li {
float: left;
width: 20%;
font-family: verdana,arial,sans-serif;
text-align: center;
padding-top: 5px;
padding-bottom: 5px;
background-image:none;
background-color: #004E98;
display: block;
}
.nav a {
color: white;
}
.nav a:hover {
color: white;
}
.nav li:a:hover {
background-color: #093F6D;
}
And here is my javascript:
function drop(menu) {
document.getElementById(menu).style.display = 'block';
document.getElementById(menu).style.position = 'relative';
}
function hide(menu) {
document.getElementById(menu).style.display = 'none';
}
I would like to stick to using javascript, as the course that I am taking does not wish for me to incorporate things like JQuery at this time.
Thanks in advance for any assistance that you may offer in pointing me in the right direction.
Make your submenu a child of the <li> they are under - instead of currently you have it a child of the overall <ul>. Then you can give the parent item relative positioning, and the child list absolute positioning with top 100% (putting it under the parent item).
function drop(menu) {
document.getElementById(menu).style.display = 'block';
}
function hide(menu) {
document.getElementById(menu).style.display = 'none';
}
.nav li {
float: left;
width: 20%;
font-family: verdana,arial,sans-serif;
text-align: center;
padding-top: 5px;
padding-bottom: 5px;
background-image:none;
background-color: #004E98;
display: block;
position: relative;
}
.nav a {
color: white;
}
.nav a:hover {
color: white;
}
.nav li:a:hover {
background-color: #093F6D;
}
.dropmenu {
position: absolute;
top:100%;
left: 0;
}
.dropmenu li {
display: block;
float: left;
width:100%;
}
<ul class="nav">
<li>Home</li>
<li>Department Members
<ul id="menu" class="dropmenu" style="display:none">
<li>Brian Kendricks</li>
<li>Tim Jones</li>
<li>David Kline</li>
</ul>
</li>
<li>Systems Used</li>
<li>System Status</li>
<li>Projects</li>
</ul>

Categories

Resources