How to position two <li>'s within a nested <ul>? - css

I am wanting to display <li>'s as squares in a horizontal line, and have nested squares within them positioned at the bottom left and bottom right of the containing square.
____________ ____________
| | | |
|___ ___| |___ ___|
|_x_|__|_y_| |_x_|__|_y_| etc
I tried adding span's to the <li> but wasn't able to position them correctly.
I've gotten closer with a nested <ul> and two <li>'s within the nested <ul> but there is undesired space between the top level squares.
How do I get control of the spacing between the top level <li>'s?
jsFiddle
http://jsfiddle.net/rwone/4Hzp6/
HTML
<ul class="images_list">
<li class="style_one"><img src="http://dummyimage.com/50/ccc/fff&text=1.png">
<ul class="nested"><li class="delete_span"></li><li class="crop_span"></li></ul>
</li>
<li class="style_one"><img src="http://dummyimage.com/50/ccc/fff&text=2.png">
<ul class="nested"><li class="delete_span"></li><li class="crop_span"></li></ul>
</li>
<li class="style_one">
<img src="http://dummyimage.com/50/ccc/fff&text=3.png">
<ul class="nested"><li class="delete_span"></li><li class="crop_span"></li></ul>
</li>
<li class="style_one">
<img src="http://dummyimage.com/50/ccc/fff&text=4.png">
<ul class="nested"><li class="delete_span"></li><li class="crop_span"></li></ul>
</li>
<li class="style_one">
<img src="http://dummyimage.com/50/ccc/fff&text=5.png">
<ul class="nested"><li class="delete_span"></li><li class="crop_span"></li></ul>
</li>
</ul>
CSS
ul.images_list {
list-style: none;
margin: 0px !important;
padding: 0px !important;
}
ul.nested {
margin: 0px !important;
padding: 0px !important;
display: inline;
position: relative;
left: -54px;
}
li.style_one {
position:relative;
display:inline-block;
/*width: 50px;
height:50px*/
}
.delete_span {
width: 15px;
height: 15px;
background: red;
display: inline-block;
}
.crop_span {
width: 15px;
height: 15px;
background: green;
display: inline-block;
position: relative;
left: 20px;
}

It seams that the problem come from user agent stylesheet (on chrome). Chrome is adding a rules This SO question is talking about it.
It suggest to add ul { padding:0 } but that is not working on your case..
But It might get you on the direction.
ul, menu, dir {
display: block;
list-style-type: disc;
-webkit-margin-before: 1em;
-webkit-margin-after: 1em;
-webkit-margin-start: 0px;
-webkit-margin-end: 0px;
-webkit-padding-start: 40px;//I guess this one is the problem
}
I have tried to override this rules adding !important but it doesn't work.

This achieves the behaviour of what I wanted, I used div's within <li>'s:
http://jsfiddle.net/rwone/4Hzp6/6/
HTML
<ul class="images_list">
<li class="style_one"><img src="http://dummyimage.com/50/ccc/fff&text=1.png">
<div class="crop_it"></div><div class="delete_it"></div>
</li>
<li class="style_one"><img src="http://dummyimage.com/50/ccc/fff&text=2.png">
<div class="crop_it"></div><div class="delete_it"></div>
</li>
<li class="style_one">
<img src="http://dummyimage.com/50/ccc/fff&text=3.png">
<div class="crop_it"></div><div class="delete_it"></div>
</li>
<li class="style_one">
<img src="http://dummyimage.com/50/ccc/fff&text=4.png">
<div class="crop_it"></div><div class="delete_it"></div>
</li>
<li class="style_one">
<img src="http://dummyimage.com/50/ccc/fff&text=5.png">
<div class="crop_it"></div><div class="delete_it"></div>
</li>
</ul>
CSS
ul.images_list {
list-style: none;
margin: 0px !important;
padding: 0px !important;
}
li.style_one {
display: inline-block;
height: 50px;
margin-left: 15px;
position: relative;
width: 50px;
}
li.style_one:first-child {
margin-left: 0px;
}
.crop_it {
background: none repeat scroll 0 0 #FF0000;
bottom: 0;
display: inline-block;
height: 15px;
left: 0;
position: absolute;
width: 15px;
z-index: 9;
}
.delete_it {
background: none repeat scroll 0 0 #008000;
bottom: 0;
display: inline-block;
height: 15px;
left: 35px;
position: absolute;
width: 15px;
}

Simple just change the class ul.nested position relative to position absolute and little bit changes in left and top or copy paste the code below:
CSS CODE:
ul.images_list {
list-style: none;
margin: 0px !important;
padding: 0px !important;
}
ul.nested {
margin: 0px !important;
padding: 0px !important;
display: inline;
position: absolute;
left: 0px;
top: 34px;
}
li.style_one {
position:relative;
display:inline-block;
/*width: 50px;
height:50px*/
}
.delete_span {
width: 15px;
height: 15px;
background: red;
display: inline-block;
}
.crop_span {
width: 15px;
height: 15px;
background: green;
display: inline-block;
position: relative;
left: 20px;
}

Related

Setting overflow-y auto also sets overflow-x

I am trying to make a dropdown box with submenus appearing horizontally, which can also scroll vertically.
I have gotten everything working except for the scroll.
.dropdown-container {
background: white;
border: 1px solid #666;
cursor: pointer;
line-height: 24px;
height: 24px;
position: relative;
width: 150px;
}
.dropdown-container a {
color: black;
padding: 0 10px;
text-decoration: none;
}
.dropdown-container:after {
color: #666;
content: '\f107';
font-family: FontAwesome;
position: absolute;
right: 2px;
top: 0px;
}
.dropdown-container:before {
content: attr(data-content);
padding: 0 10px;
}
.dropdown-container li > a:not(:only-child):after {
content: '\f105';
font-family: FontAwesome;
position: absolute;
right: 4px;
top: 0px;
}
.dropdown-container ul {
background: white;
border: 1px solid #666;
display: none;
right: 1px; /*Why is it being nudged 1px right relative to parent?*/
list-style: none;
margin: 0;
max-height: 80px;
overflow-x: visible;
overflow-y: auto; /*This is the problematic line, remove this and the rest works*/
padding: 0;
position: relative;
width: 100%;
}
.dropdown-container:hover > ul {
display: block;
}
.dropdown-container ul li {
background: white;
position: relative;
}
.dropdown-container ul li:hover {
background: rgba(173, 216, 230, 0.6);
}
.dropdown-container ul li:hover > ul {
display: block;
}
.dropdown-container ul ul {
display: none;
position: absolute;
left: 150px;
width: 150px;
top: -1px; /*Another 1px adjustment required, why aren't they already aligned?*/
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<div class="dropdown-container" role="nav" data-content="Title">
<ul class="dropdown">
<li>
Select 1
</li>
<li>
Select 2
<ul>
<li>
Select 2.1
<ul>
<li>
Select 2.1.1
</li>
</ul>
</li>
<li>
Select 2.2
</li>
</ul>
</li>
<li>
Select 3
</li>
<li>
Select 4
</li>
</ul>
</div>
See JSfiddle here.
But if I set overflow-y on the <ul> to auto to enable scrolling then my submenus get hidden as in the snippet above.
I believe the problem is the same as in this question: when overflow-y: auto and overflow-x: visible, overflow-x is treated as auto too.
Unfortunately the solution suggested (wrapping the <ul> in a position: relative element) has not worked for me.
Does anyone know of another way around this?

How to force child elements to expand the parent element?

I make a drop-down menu with a lot of items (I don't know exactly how many).
I expect the child <ul> to expand to max-width when it has enough items, but actually it expands to parent <div>'s width only, no more.
Why?
Upd: I want to break long lines, not to shrink them by flex.
Upd 2: I want to the child <ul> to be not smaller than the parent <div>.
div {
background: aquamarine;
height: 50px;
position: relative;
width: 200px;
}
ul {
background: blue;
list-style-type: none;
margin: 0;
max-width: 500px;
padding: 5px;
position: absolute;
top: 100%;
}
li {
background: yellow;
margin: 5px;
padding: 5px;
}
a {
background: red;
color: white;
display: inline-block;
margin: 5px;
width: 30px;
}
<div>
<ul>
<li>
<a>A</a>
<a>B</a>
</li>
<li>
<a>A</a>
<a>B</a>
<a>C</a>
<a>D</a>
<a>E</a>
<a>F</a>
<a>G</a>
<a>H</a>
<a>I</a>
</li>
</ul>
</div>
You can move the relative positioning up to a parent element that is wide enough to handle the 500px:
div.wide-load {
width: 500px;
position: relative;
}
div.direct-parent {
background: aquamarine;
height: 50px;
width: 200px;
}
ul {
background: blue;
list-style-type: none;
margin: 0;
max-width: 500px;
padding: 5px;
position: absolute;
top: 100%;
}
li {
background: yellow;
margin: 5px;
padding: 5px;
}
a {
background: red;
color: white;
display: inline-block;
margin: 5px;
width: 30px;
}
<div class="wide-load">
<div class="direct-parent">
<ul>
<li>
<a>A</a>
<a>B</a>
</li>
<li>
<a>A</a>
<a>B</a>
<a>C</a>
<a>D</a>
<a>E</a>
<a>F</a>
<a>G</a>
<a>H</a>
<a>I</a>
</li>
</ul>
</div>
</div>
If you are unable to do this, then your only other option is to make the li's white-space:nowrap - but this will not respect your max-width:
div.direct-parent {
background: aquamarine;
position: relative;
height: 50px;
width: 200px;
}
ul {
background: blue;
list-style-type: none;
margin: 0;
max-width: 500px;
padding: 5px;
position: absolute;
top: 100%;
}
li {
background: yellow;
margin: 5px;
padding: 5px;
white-space: nowrap;
}
a {
background: red;
color: white;
display: inline-block;
margin: 5px;
width: 30px;
}
<div class="direct-parent">
<ul>
<li>
<a>A</a>
<a>B</a>
</li>
<li>
<a>A</a>
<a>B</a>
<a>C</a>
<a>D</a>
<a>E</a>
<a>F</a>
<a>G</a>
<a>H</a>
<a>I</a>
</li>
</ul>
</div>
li {
background: yellow none repeat scroll 0 0;
display: flex;
margin: 5px;
padding: 5px;
}
You can use
display: flex;
It's the principle of max-width. You force an item to never be larger than the specified unit, but this doesn't automatically mean that your element will ever reach that length. In this case, your absolutely positioned <ul> is still restricted to it's initial parent, which forces it to be a maximum of 200px long.
FWIW: An additional option not mentioned yet:
Use intrinsic sizing for the width:
ul {
...
width: max-content;
max-width: 500px;
...
}
From the spec:
max-content If specified for the inline axis, use the max-content inline size; otherwise compute to auto.
NB: you can use max-width: 500px in conjunction with the width property to ensure that the content width never exceeds 500px (max-width will override width).
div {
background: aquamarine;
height: 50px;
position: relative;
width: 200px;
}
ul {
background: blue;
list-style-type: none;
margin: 0;
width: -moz-max-content;
width: -webkit-max-content;
width: max-content;
max-width: 500px;
padding: 5px;
position: absolute;
top: 100%;
}
li {
background: yellow;
margin: 5px;
padding: 5px;
}
a {
background: red;
color: white;
display: inline-block;
margin: 5px;
width: 30px;
}
<div>
<ul>
<li>
<a>A</a>
<a>B</a>
</li>
<li>
<a>A</a>
<a>B</a>
<a>C</a>
<a>D</a>
<a>E</a>
<a>F</a>
<a>G</a>
<a>H</a>
<a>I</a>
<a>A</a>
<a>B</a>
<a>C</a>
<a>D</a>
<a>E</a>
<a>F</a>
<a>G</a>
<a>H</a>
<a>I</a>
</li>
</ul>
</div>
Browser Support is also pretty good (Except for IE/Edge)
You want something like this? I changed the width: 200px of div to max-width:500px and removed the max-width:500px in ul
div {
background: aquamarine;
height: 50px;
position: relative;
max-width: 500px;
}
ul {
background: blue;
list-style-type: none;
margin: 0;
padding: 5px;
position: absolute;
top: 100%;
}
li {
background: yellow;
margin: 5px;
padding: 5px;
}
a {
background: red;
color: white;
display: inline-block;
margin: 5px;
width: 30px;
}
<div>
<ul>
<li>
<a>A</a>
<a>B</a>
</li>
<li>
<a>A</a>
<a>B</a>
<a>C</a>
<a>D</a>
<a>E</a>
<a>F</a>
<a>G</a>
<a>H</a>
<a>I</a>
<a>E</a>
<a>F</a>
<a>G</a>
<a>H</a>
<a>I</a>
</li>
</ul>
</div>

overflow:scroll stops hover states from activating

link to codepen
I'm trying to make it so there is a max-height (or height) set to this very long list, and for the rest to scroll. I was able to easily achieve that with
height:800px;
overflow:scroll;
The Problem I have is that the "#subcategory" items stop displaying on hover when I apply overflow:scroll
Any ideas are greatly appreciated!
Basic HTML Structure
<!-- Start Auto Transport -->
<li id="topCategory">Auto Transport
<ul id="subContainer">
<li id="subCategory">Auto Insurance</li>
<li id="subCategory">Auto Payment</li>
<li id="subCategory">Gas</li>
<li id="subCategory">Parking</li>
<li id="subCategory">Public Transportation</li>
<li id="subCategory">Service Parts</li>
<!-- add new becomes text field, user enters text then it becomes added as category -->
<li class="hideNewCategory">
<a class="mmNewCat" data-number="1" href="#"><i class="icon ion-plus-circled"></i>Add New Category</a>
<input id="mmCat1" class="mmCatInpt" type="text" placeholder="Enter New Category" maxlength="25"></input>
</li>
</ul>
</li>
<!-- End Auto Transport -->
<!-- Start Bills Utilities -->
<li id="topCategory">Bills & Utilities
<ul id="subContainer">
<li id="subCategory">Domain Names</li>
<li id="subCategory">Fraud Protection</li>
<li id="subCategory">Home Phone</li>
<li id="subCategory">Hosting</li>
<li id="subCategory">Mobile Phone</li>
<li id="subCategory">Television</li>
<li id="subCategory">Utilities</li>
<!-- add new becomes text field, user enters text then it becomes added as category -->
<li class="hideNewCategory">
<a class="mmNewCat" data-number="2" href="#"><i class="icon ion-plus-circled"></i>Add New Category</a>
<input id="mmCat2" class="mmCatInpt" type="text" placeholder="Enter New Category" maxlength="25"></input>
</li>
</ul>
</li>
<!-- End Bills Utilities -->
relevant CSS
ul li:hover #topContainer{
display: block;
}
ul li a {
display: block;
color: $blue;
text-decoration: none;
font-family: verdana;
font-size: 14px;
}
#topContainer{
list-style: none;
color: $blue;
width: 260px;
height: auto;
background: $white;
opacity: 0.9;
position: absolute;
z-index: 1000;
height:800px;
overflow:scroll;
}
#topCategory {
float: none;
width: auto;
height: 20px;
text-align: left;
margin-left: 15px;
}
#topCategory a:hover {
color: $white;
background-color: $blue;
}
#topCategory:hover #subContainer {
display: block;
}
#topCategory a {
font-size: 16px;
position: relative;
bottom: 41px;
margin-top: 46px;
margin-left: -15px;
padding: 20px 0 20px 20px;
border-bottom:1px solid $grey-10;
}
#topCategory a:hover {
color: $white;
}
#subContainer {
list-style: none;
color: $blue;
display: none;
font-size: 12px;
min-width: 230px;
width: 150px;
height: auto;
background: $white;
opacity: 0.9;
margin: -107px 0 0 245px; position: absolute;
z-index: 1000;
white-space:nowrap;
}
#subContainer a{
border-bottom:1px solid $grey-10;
margin-top: 41px;
}
#subCategory {
float: none;
width: auto;
height: 20px;
text-align: left;
margin-left: 10px;
}
#subCategory:hover {
background: none;
}
.active {
background: $white;
}
#subCategory {
float: none;
// hover length
width:215px;
// hover length
text-align: left;
height: 25px;
margin-left: 15px;
margin-right: -43px;
}
Subcategory should be a Class name not an Id element, change that and things will look cleaner.
.subcategory {
}
<div class="subcategory"></div>

Position to the right when it's float to the left

I have a menu and a logo on the header, and I am struggling to make the logo to be at the far edge of the left side of the website and the menu to the edge of the right side.
The problem is, when both of them are displayed as inline-block which means they are going to float to the default orientation which is left, I can't figure out a way to change this, please help.
Here's the CSS code:
/*Header*/
.wrapperHeader{
background-color: #FFFFFF;
border-bottom: 1px solid #DDDDDD;
width: 100%;
padding: 15px 0px;
z-index: 1000;
}
.content{
width: 1000px;
max-width: 100%;
margin: auto;
}
.header-logo, #logoImage{
width: 250px;
max-width: 100%;
display: inline-block;
vertical-align: middle;
}
/*Main Menu*/
.header-menu{
width: 690px;
max-width: 100%;
display: inline-block;
vertical-align: middle;
}
#MainMenu li{
position: relative;
padding: 15px;
display: inline-block;
right: 0px;
}
Note: in the html, the logo is in a section and the menu is in anther section and both of them are inside a divide.
HTML code:
<header>
<div class="wrapperHeader">
<div class="content">
<section class="header-logo">
<img id="logoImage" src="assets/elements/logo.png" alt="LOAI Design Studio Logo"/>
</section>
<section class="header-menu">
<nav id="MainMenu">
<ul>
<li><a class="active" href="index.html">Home</a></li>
<li id="PortfolioMenu"><a id="Portfolio" href="#">Portfolio</a>
<ul class="subMenu">
<li>Web Design</li>
<li>Visual Identity</li>
<li>Photography</li>
</ul>
</li>
<li>Testimonials</li>
<li>About Me</li>
<li>Get In Touch</li>
<li><a class="getStartedButton" href="get-started.html">Get Started</a></li>
</ul>
Menu<p id="SmartMenu-logo">LOAI Design Studio</p>
</nav>
</section>
</div>
</div>
</header>
Here I've edited your CSS code, so you can try this
/*Header*/
.wrapperHeader{
background-color: #FFFFFF;
border-bottom: 1px solid #DDDDDD;
padding: 15px 0px;
z-index: 1000;
overflow: hidden;
}
.content{
width: 1000px;
margin: auto;
}
.header-logo, #logoImage{
width: 250px;
float: left;
}
/*Main Menu*/
.header-menu{
width: 690px;
float: right;
}
#MainMenu ul{
margin: 0;
padding: 0;
list-style: none;
}
#MainMenu li{
position: relative;
padding: 5px 15px;
float: left;
list-style: none;
}
li#PortfolioMenu{
padding: 0;
}
li#PortfolioMenu > a{
padding: 5px 15px;
}
ul.subMenu{
display: none;
position: absolute;
}
li:hover ul.subMenu{
display: block;
}
I've used float:left; for the logo, float:right; for the header-menu, removed display:inline-block; and did some other fixes ...
Hope this will help you ...
I would float logo section left, float menu section right and then clear the wrapper using clear:both. Remove the inline-block for this to work properly.

div`s display block inside li element makes it have empty space

I have following code:
<div class="settingsMenu" style="top: 135px; left: 149px; display: block;">
<ul>
<li class="download" onclick="downTemplate('template1')">Download</li>
<li class="delete" onclick="showConfirmationDialog ($(this))">
Delete
<div class="deleteItemConfirmation">
<div class="confirmationText">Are you sure?</div>
<div class="buttons"><button onclick="deleteTemplate ('template1')">Yes</button> <button onclick="hideConfirmationDialog();">No</button></div>
</div>
</li>
<li class="info">Info</li>
</ul>
</div>
CSS:
.settingsMenu{
position: absolute;
top: 0;
left: 0;
display: none;
background-color: #FFFFFF;
border: 1px solid #b5044a;
border-radius: 5px;
width: 150px;
padding: 10px 0;
margin: 0;
z-index: 200;
}
.settingsMenu ul{
list-style-type: none;
width: 100%;
margin: 0px;
padding: 0;
}
.settingsMenu ul li {
color: #000000;
cursor: pointer;
float: left;
font-size: 14px;
font-weight: normal;
font-family: Arial;
height: 18px;
max-width: 100px;
margin: 5px 20px;
padding: 0;
display: block;
padding-left: 30px;
}
.settingsMenu ul li.edit{
background: url("../img/edit-context-menu-icon.svg") no-repeat scroll center left white;
}
.settingsMenu ul li.delete{
background: url("../img/delete-context-menu-icon.svg") no-repeat scroll center left white;
}
.settingsMenu ul li.info{
background: url("../img/info-context-menu-icon.svg") no-repeat scroll center left white;
}
Problem is: while div.deleteItemConfirmation has "display: none;" everything is displaying correctly, when it`s display property becomes "display: block;" strange space appears before text of
<li>Delete</li>
Try changing
<li class="delete" onclick="showConfirmationDialog ($(this))">
Delete
To
<li class="delete" onclick="showConfirmationDialog ($(this))">Delete
Could this help you out:
<ul>
<li>
one</li><li>
two</li><li>
three</li>
</ul>
or
<ul>
<li>one</li
><li>two</li
><li>three</li>
</ul>
or with comments...
<ul>
<li>one</li><!--
--><li>two</li><!--
--><li>three</li>
</ul>
I took the idea from http://css-tricks.com/fighting-the-space-between-inline-block-elements/ and helped me in a few similar situations.

Resources