Hover element to effect sibling element - css

I have a navigation bar with a list of links and a search bar. It looks like this:
<ul>
<li class="link">Link 1</li>
<li class="link">Link 2</li>
<li class="link">Link 3</li>
<li class="link search">search</li>
</ul>
When the user hovers the "search" element, I want to
Apply a width of 500px to the hovered search elements
Apply a margin of -150px to the sibling "link" element
The CSS that I've written to do this is:
ul {
margin: 0;
padding: 0;
list-style: none;
width: 500px;
float: right;
}
.link {
width: 150px;
float: left;
line-height: 80px;
}
.search {
background: red;
width: 50px;
}
.search:hover{
width: 500px
}
.search:hover + .link {
margin-left: -150px;
}
This however has no effect on the sibling "link" elements
With pure CSS, is it possible to apply the the declarations "margin-left: -150px" on the hover of "search"?
I've created a fiddle here to illustrate the problem
https://jsfiddle.net/qut1nz9j/

If you use flex you can do like this. (Current browser support ~96%)`
The trick is you put the search link first in your markup and use order to show it last. With this you can use the sibling selector ~ to achieve what you want.
nav {
width: 700px;
background: green;
height: 80px;
float: left;
}
nav ul {
margin: 0;
padding: 0;
list-style: none;
width: 500px;
display: inline-flex;
}
.link {
width: 150px;
line-height: 80px;
order: 1;
}
.search {
background: red;
width: 50px;
order: 2;
}
.search:hover {
width: 500px
}
<nav>
<span>Site Name</span>
<ul>
<li class="link search">search</li>
<li class="link">Link 1</li>
<li class="link">Link 2</li>
<li class="link">Link 3</li>
</ul>
</nav>
Thanks to Joum, here is a nice addition to my solution: https://jsbin.com/yipujadewi/edit?css,output
If someone really need to target previous sibling and can't use flex, here is an abuse of direction: ltr/rtl in combination with display: table.
Src: CSS Tables, Invert order of displayed content
nav {
width: 700px;
background: green;
height: 80px;
float: left;
}
nav ul {
margin: 0;
padding: 0;
list-style: none;
width: 500px;
display: inline-table;
direction: rtl;
}
.link {
width: 150px;
line-height: 80px;
display: table-cell;
direction: ltr;
text-align: left;
}
.search {
background: red;
width: 50px;
}
.search:hover {
width: 500px
}
.search:hover ~ .link {
color: #fff;
}
<nav>
<span>Site Name</span>
<ul>
<li class="link search">search</li>
<li class="link">Link 3</li>
<li class="link">Link 2</li>
<li class="link">Link 1</li>
</ul>
</nav>

Related

css: sort divs/lis into two columns

Suppose there are two kinds of elements, let's say words and numbers. They should be sorted into two columns. For the example I'm using listitems, but I don't mind changing to divs or something else if that helps.
<div id="container">
<ul>
<li>foo</li>
<li>bar</li>
<li class="num">1</li>
<li class="num">2</li>
<li>baz</li>
</ul>
</div>
Right now I'm achieving this somewhat by using margins, with the following css:
#container {
width: 500px;
margin: auto;
}
li {
float: left;
width: 200px;
background-color: #eee;
margin-bottom: 2px;
margin-right: 300px;
}
.num {
float: right;
margin-right: 0px;
margin-left: 300px;
}
resulting in
http://jsfiddle.net/he13vug4/
What would be a more elegant way to achieve this?
How could I make the numbers "start" (in terms of vertical position) already besides "bar" or even "foo"? (The next word should, however, only start below the numbers). That is, I'd like
or
instead of
They should be sorted into two columns, side by side
Do you need support for older browsers? If not, CSS Grid could help you
Result
#container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-auto-flow: dense;
gap: 10px;
width: 500px;
margin: auto;
list-style: none;
}
li {
background-color: #eee;
}
.word {
grid-column: 1;
}
.num {
grid-column: 2;
}
<ul id="container">
<li class="word">foo</li>
<li class="word">bar</li>
<li class="num">1</li>
<li class="num">2</li>
<li class="word">baz</li>
</ul>
And same code on JSFiddle
Use only left floating and play with clear and margin like below:
#container {
width: 500px;
margin: auto;
}
ul {
list-style:none;
}
li {
float: left;
width: 200px;
background-color: #eee;
margin-bottom: 2px;
}
li + li:not(.num) {
clear:both;
}
li + li.num {
margin-left:10px;
}
li.num + li.num {
margin-left:210px;
}
<div id="container">
<ul>
<li>foo</li>
<li>bar</li>
<li class="num">1</li>
<li class="num">2</li>
<li>baz</li>
<li>baz</li>
<li class="num">1</li>
<li class="num">2</li>
<li class="num">3</li>
<li>baz</li>
<li>baz</li>
</ul>
</div>

Hovering over a menu item to highlight background of subnav

I'm trying to make it so when you hover over one of the categories in the header nav "CALLS | CHATS | MORE" the subnav below shows and the ul that is associated with the header nav changes its background color i know i can just add a class using jQuery but could i not do this with a sibling selector or something? i just think my HTML is layed out incorrectly at the moment for it to work TIA. this is what i currently have.
<header class="header">
<ul class="header__nav">
<li class="header__navItem header__navItem--calls">Calls</li>
<li class="header__navItem header__navItem--chats">Chats</li>
<li class="header__navItem header__navItem--more">More</li>
</ul>
<nav class="navigation">
<div class="navigation__wrapper cf">
<ul class="navItems navItems--calls">
<li class="navItems__item"></li>
<li class="navItems__item"></li>
<li class="navItems__item"></li>
<li class="navItems__item"></li>
<div class="bgHover"></div>
</ul>
</div>
</nav>
</header>
.header {
height: 5.8rem;
background: rgba(25, 25, 25, 0.9);
position: absolute;
width: 100%;
z-index: 999;
&__nav {
display: inline-block;
text-align: center;
font-size: 0;
left: 50%;
position: absolute;
transform: translateX(-50%);
padding: 0;
margin: 0;
}
&__navItem {
color: $white;
display: inline-block;
#include font-size(18);
padding: 0 4rem;
line-height: 5.8rem;
letter-spacing: 0.1rem;
position: relative;
cursor: default;
font-weight: 400;
text-transform: uppercase;
font-family: $lato;
&--calls {
&:hover ~ .navigation__wrapper .navItems .bgHover {
max-height: 35rem;
}
&:hover {
color: red;
}
}
}
I'm presuming you want the submenu to appear below the header nav. If so, then move your sub nav into the li tag for the corresponding header item, like so:
<li class="header__navItem header__navItem--calls">Calls
<ul class="navItems navItems--calls">
<li class="navItems__item">First</li>
<li class="navItems__item">Second</li>
<li class="navItems__item">Third</li>
<li class="navItems__item">Fourth</li>
</ul>
</li>

Background color won't take up whole element

I have a drop down menu button that turns grey when hovered over. However, the grey does not expand throughout the whole button, but stops at the where I set the padding.
HTML:
#dropdown {
list-style: none;
display: none;
position: absolute;
background-color: #fff;
padding: 10px;
z-index: 99999;
width: 230%;
}
#dropdown li:hover,
#dropdown li:active {
background-color: #e3e3e3;
}
#dropdown.active, #menu:target #dropdown {
display: block;
}
<ul class="main-nav js--main-nav">
<li id="menu">
Help▾
<ul id="dropdown">
<li>Give</li>
<li>Get Help</li>
<li>Get Involved</li>
</ul>
</li>
</ul>
What I want is for the grey to take up all of the drop-down menu when hovered over, as opposed to just stopping at the padding.
EDIT: I should have clarified, when I meant I want it to take up "all" of the drop down menu, I meant just the "li" when I hover over that.
Is this what you were looking for?
#dropdown {
list-style: none;
display: none;
position: absolute;
background-color: #fff;
padding: 10px;
z-index: 99999;
width: 230%;
}
#dropdown:hover {
background-color: #eee;
}
#dropdown li:hover,
#dropdown li:active {
background-color: #e3e3e3;
}
#dropdown.active, #menu:target #dropdown {
display: block;
}
<ul class="main-nav js--main-nav">
<li id="menu">
Help▾
<ul id="dropdown">
<li>Give</li>
<li>Get Help</li>
<li>Get Involved</li>
</ul>
</li>
</ul>

Mouseenter event on parent when a child is absolute positioned

I'm tring to make a simple drop-down menu, which would be triggered on hover event over some element and stay active as long as the cursor is over that element or is over the dropdown list.
Sample code:
HTML
<div class="header">
<div class="items">
<div class="item">
<span>Caption</span>
</div>
<ul class="items_hidden">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
</div>
<input type="text">
CSS
.items {
float: right;
position: relative;
}
.item {
text-align: right;
}
.items_hidden {
display: none;
margin-top: 7px;
list-style: none;
z-index: 2000;
width: 80px;
border: 1px solid #f2f2f2;
text-align: left;
padding: 10px;
color: #333;
line-height: 30px;
border-bottom: 3px solid #f2f2f2;
}
input {
width: 100%;
}
JS
$(function() {
$('.items').on('mouseenter', function(e) {
$('.items_hidden').show();
});
$('.items').on('mouseleave', function(e) {
$('.items_hidden').hide();
});
});
I got that working, when the dropdown list is positioned relative, but the problem is once the list is displayed, it causes all following content to move down.
Here is an example: https://jsfiddle.net/2ya06aLo/
Another way would be to position the list absolute, so it wouldn't affect the content below. But in that case the list disappears as soons as I move the cursor out of 'Caption' (in contrast with the first fiddle).
Here is the second example https://jsfiddle.net/8L6ojqLm/
What would be a solution to make the list behave like in 1 and at the same time do not affect the rest of the content like in 2 ?
You can don't use JS
Example
.items {
float: right;
position: relative;
}
.item {
text-align: right;
padding: 10px;
}
.items_hidden {
position: absolute;
right: 0;
top: 20px;
display: none;
margin-top: 7px;
list-style: none;
z-index: 2000;
width: 80px;
border: 1px solid #f2f2f2;
text-align: left;
padding: 10px;
color: #333;
line-height: 30px;
border-bottom: 3px solid #f2f2f2;
}
input {
width: 100%;
}
.items:hover .items_hidden{
display: block;
}
<div class="header">
<div class="items">
<div class="item">
<span>Caption</span>
</div>
<ul class="items_hidden">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
</div>
<input type="text">
Live JSFiddle - https://jsfiddle.net/grinmax_/8L6ojqLm/1/
Couldn't it be done via pure css?
https://www.w3schools.com/howto/howto_css_dropdown.asp
Maybe this would help.
.navigation {
width: 100%;
}
.mainmenu, .submenu {
list-style: none;
padding: 0;
margin: 0;
}
.mainmenu a {
}
.mainmenu a:hover {
background-color: #D90000;
}
.mainmenu li:hover .submenu {
display: block;
max-height: 400px;
}
.submenu{
max-height: 400px;
}
.submenu a {
background-color: #FF4D4D;
}
.submenu a:hover {
background-color: #D90000;
}
.submenu{
overflow:hidden;
display:none;
}
<nav class="navigation"><!-- pocetak navigacije -->
<ul class="mainmenu">
<li>Link</li>
<li class="start">Link
<ul class="submenu">
<li>Link</li>
<li>Link</li>
<li>Link</li>
</ul>
</li>
<li>Home</li>
</ul>
</nav>
To take up the comment of CBroe: The problem seems to be the "gap" between the and the element. To remove it you could either
give the "item"-Element a height so that it "reaches down" to the ul-element or
or remove the margin-top of the ul-element

how to overlap a list of menus over an image

When the menu "product" is clicked or mouse over, the another list of menus appear.. but the image block which is below the menu bar, moves away from the position. if i use css [ position:absolute;], then the image box remains static and the product's sub-menu overlaps the image block, which is what i wanted. but the image blocks width & height settings change drastically, thereby spoiling the alignment.
pls chk the codings in jsFiddle
.home_menu {
border: 1px solid black;
width: 98%;
height: 3.3%;
margin-right: auto;
margin-left: auto;
}
div#menuDemo {
clear: both;
//border:1px solid black;
height: 78%;
width: 100%;
position: relative;
left: 0;
top: 0;
background-color: #A55927;
/*Remove this next one in production - Used for demo purpose only*/
margin-bottom: 0.1%;
padding-top: 0.7%;
z-index: 4;
}
div#menuDemo ul {
list-style: none;
margin: 0;
padding: 0;
background-color: #A55927;
}
div#menuDemo > ul > li {
float: left;
text-align: center;
}
div#menuDemo ul li {
width: 25%;
//border: 5px solid purple;
}
div#menuDemo ul li a {
text-decoration: none;
font-weight: bolder;
text-align: center;
}
div#menuDemo > ul > li > ul {
display: none;
text-align: center;
}
div#menuDemo > ul > li:hover > ul {
display: block;
text-align: center;
}
.sub1 {
width: 100%;
//border:1px solid green;
}
.colouring {
color: black;
font-weight: bolder;
}
.colour {
//border:1px solid blue;
color: black;
text-align: center;
//width:100%;
}
.wrapper {
border: 5px solid pink;
width: 98.8%;
height: 82%;
margin-top: 1%;
z-index: 2;
}
.uniform_block {
border: 5px solid green;
width: 100%;
height: 40%;
cursor: pointer;
}
.uniform_block img {
width: 100%;
height: 100%;
}
<body>
<div class="home_menu">
<div id="menuDemo">
<ul>
<li id="homeMenu">About Us
</li>
<!-- <li >About Us</li> -->
<li>Products
<ul class="sub1">
<li> Uniforms
<ul>
<li> &nbsp
</li>
<li> Automobile Industry Uniforms
</li>
<li> Pharmaceutical Uniforms
</li>
<li> Food Industry Uniforms
</li>
<li> Government Sector Uniforms
</li>
<li> School/College Uniforms
</li>
<li> &nbsp
</li>
</ul>
</li>
<li>Shoes
<ul>
<li> &nbsp
</li>
<li> Industrial Shoes
</li>
<li> Safety & Security Shoes
</li>
<li> Executive Shoes
</li>
<li> &nbsp
</li>
</ul>
</li>
</ul>
</li>
<li>Contact Us
</li>
</ul>
</div>
</div>
<div class="wrapper">
<div class="uniform_block">
<img src=" http://t0.gstatic.com/images?q=tbn:ANd9GcSH-kRi3rkVciPcH_c6dDJJI6C1ntzwcKl9MoVQIyuKk8F7unpf" />
</div>
<div class="home_footer">
<div class="footer_contents"></div>
</div>
</div>
</body>
kindly help. My requirement is, when i mouse over the "product menu", the drop down menu should be viewed above the image block which is below the menu bar.
Add position:absolute to the css of your ul menu (in your case, the sub1 class), and remove the width:100% so it can inherit the default width of its parent. Absolute positioning will prevent your browser from trying to put your ul element after the previous element on the page.
ul.sub1 {
position:absolute;
}
http://jsfiddle.net/C2YXp/2/

Resources