Changing color of menu on text hover - html

I want to change the color of the menu on text hover. But not when the menu text is hovered but another heading. I have a heading "Not a restaurant, but here for them." and when the user hovers the word "restaurant" the menu text color should change to white and the word "restaurant" to red and the rest of the heading to white. The second part (that "restaurant" changes to red and the rest of the heading to white) already works. But how can I make it that also the color of the menu changes?
.headingRestaurant:hover {
color: red;
}
.headingRestaurant {
cursor: pointer;
}
.textb {
pointer-events: none;
}
.headingRestaurant {
pointer-events: initial;
}
.textb:hover {
color: white;
}
<nav>
<ul>
<li>
Home
</li>
<li>
About
</li>
</ul>
</nav>
<h1 class="textb">
Not a <span id="heading1" class="headingRestaurant">restaurant</span>,
<br> but here for them.
</h1>

Since CSS can only interact with things inside or below the current element, the easiest solution would be to use Javascript to handle the hover for you.
You can use the function addEventListener to add both a mouseover and a mouseout event on your restaurant text to add/remove a hover class to whichever element you want to hover.
var nav = document.querySelector('nav');
var headingRestaurant = document.querySelector('.headingRestaurant');
headingRestaurant.addEventListener('mouseover', function() {
nav.classList.add('hover');
});
headingRestaurant.addEventListener('mouseout', function() {
nav.classList.remove('hover');
});
.headingRestaurant:hover {
color: red;
}
.headingRestaurant {
cursor: pointer;
}
.textb {
pointer-events: none;
}
.headingRestaurant {
pointer-events: initial;
}
.textb:hover {
color: white;
}
nav.hover,
nav.hover a {
color: red;
}
<nav>
<ul>
<li>
<a
href="file:///C:/Users/.../index.html"
>Home</a
>
</li>
<li>
<a
href="file:///C:/Users/.../about.html"
>About</a
>
</li>
</ul>
</nav>
<h1 class="textb">
Not a <span id="heading1" class="headingRestaurant">restaurant</span>,
<br />
but here for them.
</h1>
If you'd like to use html and css only, you'd have to reverse the html flow so that the element you want to change is coded below the element you're hovering over.
In this case I've moved the nav and h1 to a container div and swapped them around so that the h1 is coded above the nav. The display order is then fixed by using both the properties display: flex and flex-direction: column-reverse. The hover in this method uses the css selector ~ which matches an selector that is preceded by another selector. In the case of .textb:hover ~ nav it would select any nav element that is preceded by a .textb which is hovered over. Since the part after the ~ is still a selector, you could also change a specific menu item.
.headingRestaurant {
cursor: pointer;
pointer-events: initial;
}
.textb {
pointer-events: none;
}
.textb:hover {
color: white;
}
.textb:hover .headingRestaurant {
color: red;
}
.textb:hover ~ nav,
.textb:hover ~ nav a {
color: red;
}
.textb:hover ~ nav a.about {
color: purple;
}
.reversed {
display: flex;
flex-direction: column-reverse;
}
<div class="reversed">
<h1 class="textb">
Not a <span id="heading1" class="headingRestaurant">restaurant</span>,
<br />
but here for them.
</h1>
<nav>
<ul>
<li>
<a class="about" href="file:///C:/Users/.../index.html">Home</a>
</li>
<li>
About
</li>
</ul>
</nav>
</div>

:has is definitely the way to go here but there are some clever cookies out there who might come up with something innovative. Note that this isn't fully supported yet.
/* This is just making things pretty */
nav ul li {
display: inline-block;
padding: 0.5rem 1rem;
margin: 0;
border: 1px dotted red;
}
nav ul {
list-style-type: none;
margin: 0;
padding: 0;
}
nav ul li a {
text-decoration: none;
color: inherit;
}
/* This is the functional stuff */
.headingRestaurant:hover {
color: red;
}
.headingRestaurant {
cursor: pointer;
}
.textb {
pointer-events: none;
}
.headingRestaurant {
pointer-events: initial;
}
.textb:hover {
color: white;
}
/* This colours the menu on hover */
body:has(.headingRestaurant:hover) nav {
background-color: lightblue;
}
<nav>
<ul>
<li>
Home
</li>
<li>
About
</li>
</ul>
</nav>
<h1 class="textb">
Not a <span id="heading1" class="headingRestaurant">restaurant</span>,
<br> but here for them.
</h1>

Replace target with whatever class/id you are using to identify your menu element and it will control the styling when hovering on the .headingRestaurant element.
.headingRestaurant:hover target {
}

Related

How to make a CSS :hover persistent after hover? [duplicate]

This question already has answers here:
Make CSS Hover state remain after "unhovering"
(11 answers)
Hover CSS styling that persists after mouse away
(3 answers)
Closed 3 years ago.
I have created a navigation bar with a :hover effect and I'd like to know how to make that effect persistent, even after the cursor is removed from the area. The effect is a background color under the given word. For example, when Home is selected I'd like for that effect to stay on the element until another element (for example, Register) is clicked.
.navbar {
list-style-type: none;
background-color: black;
display: flex;
justify-content: flex-start;
align-items: center;
margin: 0;
height: 50px;
padding: 0;
}
.navbar a {
text-decoration: none;
color: gray;
padding: 17px;
transition: background-color 0.5s linear;
}
.navbar a:hover {
background-color: green;
color: honeydew;
}
body {
margin: 0;
}
<header>
<nav>
<ul class='navbar'>
<li><a href='#home'>Home</a></li>
<li><a href='#download'>Download</a></li>
<li><a href='#register'>Register</a></li>
<li><a href='#contact'>Contact</a></li>
<li><a href='#FAQ'>FAQ</a></li>
</ul>
</nav>
</header>
The desired effect can be achieved with just CSS but it's tricky and the only way I know of would cause your links to become non-functional (since it requires replacing your links with <input type="radio">). So overall, I would recommend to use JavaScript for this.
The JavaScript way would be, using jQuery, to add a class when the mouseover event is triggered and to remove it from all other elements on another desired event getting triggered.
Example: (I have replaced the :hover pseudoselector with a .hover class selector and added the jQuery library and required code.)
jQuery is not required to achieve this effect, you can do this just fine with vanilla JavaScript.
$(".navbar a").on("mouseover", function () {
$(".navbar a").removeClass("hover");
$(this).addClass("hover");
});
.navbar {
list-style-type: none;
background-color: black;
display: flex;
justify-content: flex-start;
align-items: center;
margin: 0;
height: 50px;
padding: 0;
}
.navbar a {
text-decoration: none;
color: gray;
padding: 17px;
transition: background-color 0.5s linear;
}
.navbar a.hover {
background-color: green;
color: honeydew;
}
body {
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>
<nav>
<ul class='navbar'>
<li><a href='#home'>Home</a></li>
<li><a href='#download'>Download</a></li>
<li><a href='#register'>Register</a></li>
<li><a href='#contact'>Contact</a></li>
<li><a href='#FAQ'>FAQ</a></li>
</ul>
</nav>
</header>

Hoverable menu items

I have a menu with different items, these items are returned from a controller, and looks like this.
#foreach (var item in ViewBag.LoggedIn)
{
if (item.Url == path)
{
<li><a class="active" href="#item.Url">#item.Text</a></li>
}
else
{
<li>#item.Text</li>
}
<li class="slider"></li>
}
It is the "li" at the end, which is of class="slider" which is the "hover/slider" I somehow have to define the starting position of that slider.
The hovering is defined like this in the css.
.menu li:nth-child(1):hover ~ .slider,
.menu li:nth-child(1):focus ~ .slider,
.menu li:nth-child(1):active ~ .slider {
left: 0;
background-color: #3498db;
}
.menu li:nth-child(2):hover ~ .slider,
.menu li:nth-child(2):focus ~ .slider,
.menu li:nth-child(2):active ~ .slider {
left: 20%;
background-color: #9b59b6;
}
and so on.
The selected link is defined as active after the button is pushed. The problem is that the "hover/slider" starts at the left side.
This is illustrated in the picture below. In that example About is clicked, but the "hover/slider" starts at Home, which is kinda weird.
I would like to know how I could make the slider/hover (which is at Home in the image) to be where the link is active (About)
The generated HTML is provided below.
<ul class="menu">
<li>
Home
</li>
<li>
Contact
</li>
<li>
<a class="active" href="/Home/About">About</a>
</li>
<li>
Register
</li>
<li>
Log in
</li>
<li class="slider" id="menu_slider"></li>
</ul>
When implementing the slider in the answer I get the following error (the red line is not supposed to be covering the entire menu, just the selected link)
Here is what I understand from your question: You want to move your "slider" under the link that is currently active or hovered. If this is what you want then I have a solution for you.
Since you didn't provide your CSS properties for the rest of the menu, I am using my own CSS properties to achieve this.
Instead of moving the "slider", I am using the padding-bottom property to move the slider. When you run this in your browser, it simulates as if it moved the "slider"
.menu li a.active,
.menu li a:hover {
background-color: #E74C3C;
padding-bottom: 20px;
position: relative;
z-index: 1;
}
Here is the complete solution in code snippet below. Do let me know if this isn't what you wanted and I will update my answer.
.menu {
flex-direction: row;
padding-left: 0;
margin-bottom: 0;
list-style: none;
display: flex;
}
.menu li:not(.slider) {
box-sizing: border-box;
background: #2C3E50;
width: 100%;
}
.menu li a {
color: white;
text-decoration: none;
display: block;
padding: 1rem;
}
.menu li a.active,
.menu li a:hover {
background-color: #E74C3C;
padding-bottom: 20px;
position: relative;
z-index: 1;
}
.menu .slider {
height: 5px;
width: calc(100% - 1rem);
position: fixed;
margin-top: 50px;
background: #D6F1FF;
}
<ul class="menu">
<li>
Home
</li>
<li>
Contact
</li>
<li>
<a class="active" href="/Home/About">About</a>
</li>
<li>
Register
</li>
<li>
Log in
</li>
<li class="slider" id="menu_slider"></li>
</ul>

Dropdown menu in HTML/CSS doesn't actually "drop down"

I'm trying to add a drop-down menu for one of the options in my nav menu for a simple html page. However, when I hover over the nav menu option, the menu doesn't actually drop down. It just replaces the nav menu option with the first option in the drop-down whenever I hover over it. I'm not exactly sure why it isn't "dropping down".
Any help would be really appreciated... Here's the HTML for the nav and attempted drop-down.
<nav>
<ul>
<li>Eiffel Tower</li>
<li>Fashion</li>
<li>Food</li>
<li>Museums</li>
<div class="dropDiv">
<li class="dropdown">History</li>
<div class="dropdownContent">
<a href=leaders.shtml>Leaders of Paris</a>
<a href=future.shtml>Future of Paris</a>
</div>
</div>
<li>Language</li>
<li>Works Cited</li>
</ul>
</nav>
and here is the CSS snippet for the Dropdown menu:
.dropdown {
float: left;
background-color: #FFF0F5;
width: 100%;
}
.dropDiv {
position: relative;
display: inline-block;
width: 100%;
}
.dropdownContent {
display: none;
position: absolute;
background-color: #FFF0F5;
height: 200px;
width: 100%;
z-index: 1;
}
.dropdownContent a {
display: block;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
.dropdownContent a:hover {background-color: #fff8dc;}
.dropDiv:hover .dropdownContent {
display: block;
z-index: 1;
height: 200px;
}
.dropDiv:hover .dropdown {
background-color: #fff8dc;
}
I'm not really sure why the drop-down part isn't displaying, i'm sure it's some stupid mistake but it's eluded me for an hour and a half...
I see you have mentioned position: absolute in dropdownContent class. This is causing to overlap. Just remove it and try. By default it sets to static, which mean Elements render in order, as they appear in the document flow. Where as absolute means element is positioned relative to its first positioned ancestor element.
The problem is in your HTML.
For the dropdown within an item of the 1st level you'll need a code block that looks like your 1st level. That is, another <ul> with a group of <li>s one for each 2nd level option.
You have a lot of unwanted css and markup. Just fix it. I have created a basic one for you. May be you can try,
.dropdownContent {
display: none;
background-color: #FFF0F5;
}
.dropdownContent a:hover {
background-color: #fff8dc;
}
.dropdownContent a{
display: block;
}
.dropdown:hover .dropdownContent {
display: block;
z-index: 1;
}
<nav>
<ul>
<li>Eiffel Tower</li>
<li>Fashion</li>
<li>Food</li>
<li>Museums</li>
<li class="dropdown">
History
<div class="dropdownContent">
<a href=leaders.shtml>Leaders of Paris</a>
<a href=future.shtml>Future of Paris</a>
</div>
</li>
<li>Language</li>
<li>Works Cited</li>
</ul>
</nav>

Maintain Hover / Active over entire parent li element?

I want it so that when I hover over a <li>, the entire element has a highlight of blue, and that the text within the <li> turns from black to white. I also want it so that when I click on the <li>, the <li> becomes active and the blue highlight and change from black to white text stays. I understand I have to use the :hover and :active attributes. Here is my attempt therefore:
HTML:
<div class="facet">
<ul>
<li>
<a href="" class="link">
Name<span class="count">Count</span>
</a>
</li>
</ul>
</div>
CSS:
//Changes the LINK text to white
.link:hover {
background-color: #2897C5;
color: #ffffff;
}
//Attempt to change the entire parent element text to white and have a blue highlight, but this doesn't seem to work
.facet li:active {
background-color: #2897C5;
color: #ffffff;
}
//Normal CSS for the link when it is not hovered over or clicked on
.link {
font-size: 14px;
line-height: 1.3;
text-decoration: none;
display: block;
color: #000;
}
//White text when you hover over the count
.count:hover {
color: #ffffff;
}
//Normal CSS when you don't hover over the count
.count {
position: relative;
float: right;
color: #bdbdbd;
}
NowI have a variety of issues with my attempt above.
1. When I hover over the <li>, the entire thing turns blue which is great, and the "Name" text also turns white. However, the "Count" text only turns white when I have my mouse hover over that portion of the <li>.
2. When I click on the <li>, the element does not apply the active state (which is all white text and blue highlight) to the entire element.
Any ideas on how I can improve? Thanks!
Here's a better version with a lot less CSS: (no solution for the active-bit, but that will have to be solved outside CSS)
ul {
list-style-type: none;
}
.facet li:hover,.facet li:hover .link,.facet li:hover .count {
background-color: #2897C5;
color: #FFF;
}
.link {
font-size: 14px;
line-height: 1.3;
text-decoration: none;
display: block;
color: #000;
padding: .2em;
}
.count {
position: relative;
float: right;
color: red;
}
<div class="facet">
<ul>
<li>
<a href="#" class="link">
Name<span class="count">Count</span>
</a>
</li>
</ul>
</div>

CSS: Class of first menu layer applied on submenu

I've got a navigation menu. But the menu get's wild.
The submenu class (this is the dropdown if you hover firstmenu). 'firstmenu' are the main areas of the site, hence the first level of the list.
Problem: Submenu get's the Firstmenus values. Even the tiny arrow background: url(images/nav-arrow.png) no-repeat center bottom; in - BUT WHY?!
We already looked into this, split up the code, removed typo3, all JavaScript and ended up with this css code:
#firstmenu {
list-style: none;
margin: 0;
padding: 0;
}
#firstmenu .firstLevel {
float: left;
}
#firstmenu .firstLevel a {
display: block;
font-size: 1.166em;
font-weight: 600;
line-height: normal;
color: #333;
padding: 41px 20px 26px;
margin-bottom: 4px;
}
#firstmenu .firstLevel .current a,
#firstmenu .firstLevel a:hover,
#firstmenu .firstLevel a.selected {
color: #fff;
background: url(images/nav-arrow.png) no-repeat center bottom;
}
#firstmenu .firstLevel a:hover,
#firstmenu .firstLevel a.selected {
background-color: #333;
}
/* Drop-Down Menus */
.submenu {
list-style: none;
margin: 0;
padding: 0;
position: absolute;
}
.submenu > ul {
top: 4px !important;
}
.submenu .secoundLevel {
width: 200px;
background: #fca500;
}
.submenu .secoundLevel a {
display: block;
color: #fff;
padding: 8px 15px;
border-top: 1px solid rgba(255,255,255,0.2);
}
.submenu .secoundLevel a:hover {
background-color: #333;
border-color: #1a1a1a;
}
.submenu .secoundLevel:first-child a {
border-top: none;
}
Anyone knows the fix?
EDIT, html:
<nav id="nav">
<ul id="firstmenu" class="clearfix">
<li class="firstLevel"><a href="index.php?id=99" >Startseite</a></li>
<li class="firstLevel current">Rootserver
<ul class="submenu">
<li class="secoundLevel"><a href="index.php?id=96" >Vergleich</a></li>
</ul>
</li>
<li class="firstLevel">Voiceserver
<ul class="submenu">
<li class="secoundLevel">Preisvergleich</li>
</ul>
</li>
</ul>
</nav>
I think the problem is a matter of understanding of CSS selectors. This selector:
#firstmenu .firstLevel a.selected {
color: #fff;
background: url(images/nav-arrow.png) no-repeat center bottom;
}
States the following: Match ALL <a> links that have a parent with class name firstLevel and it having a parent with ID firstmenu
That means this HTML bit matches:
<ul id="firstmenu" class="clearfix">
// snip
<li class="firstLevel current">Rootserver
<ul class="submenu">
<li class="secoundLevel">Vergleich</li>
</ul>
</li>
// snip
because the "secondLevel" menu has an anchor tag (<a>) that is a child (of any order, ie child, grandchild, great-grandchild, etc) of .firstLevel which is a child (of any order) of #firstmenu.
This is exactly how CSS is suppose to work but there ways to prevent what you're seeing.
The first option is to use the child selector (what I sometimes refer to as "direct descendent" selector) >
.firstLevel > a:hover{ /* code */ }
This selector specifically states: "all anchor tag that you hover which are directly descendent from .firstLevel, but no deeper.
Which means, it matches:
<li class="firstLevel">A</li>
but not the link with value "B" below
<li class="firstLevel">A
<ul>
<li><a href="#">B</b></li>
</ul>
</li>
because the second <a> tag is not directly descendant of .firstLevel, there's a <ul> and <li> between them.
The second option is to "overwrite" the previous style by having another rule with a higher CSS specificity.
#firstmenu .firstLevel .submenu a.selected {
background-image: none; /* remove the arrow from drop-down menus*/
}
There's reasons for doing one or the other.
Using the child selector is good when the styles are very specific to that element. You don't want ANY of the styles to carry over to further elements.
Use the "replacement" technique (for lack of a better term) when you're looking to modify only one specific style from another element. Ie. You want to keep the color, font, font-weight, but only want to remove the background image.
I hope that helps!
Here's some (bad) fiddles showing the base case:
http://jsfiddle.net/zTCbF/
with child selector
http://jsfiddle.net/zTCbF/1/
with the replacement technique
http://jsfiddle.net/zTCbF/2/
#firstmenu .firstLevel a {
This will target any anchor tag under .firstLevel including those under .secondLevel
So when you say...
#firstmenu .firstLevel a:hover,
You are applying your hover styles to ALL anchor tags that are descendants of .firstLevel
You want to say ...
#firstmenu .firstLevel > a {
Which will target only anchor tags that are a direct descendant of .firstLevel