How to force child elements to expand the parent element? - css

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>

Related

Child take width % from parents parent

Is the following result possible with CSS:
So that li.item takes 50% of the width of div.wrapper, not the ul.list (which is extremly long).
I've added a snippet of a basic setup. Any ideas on the matter are appreciated (please keep in mind I'm looking for CSS options). A jsfiddle playground link: http://jsfiddle.net/6o8t9t8L/
.wrapper {
width: 400px;
overflow-y: hidden;
overflow-x: scroll;
border: 1px solid black;
}
.list {
list-style-type: none;
border: 1px solid red;
width: 2000px;
}
.item {
display: inline-block;
height: 200px;
width: 50%;
border: 1px solid green;
}
<div class="wrapper">
<ul class="list">
<li class="item"></li>
<li class="item"></li>
<li class="item"></li>
<li class="item"></li>
</ul>
</div>
I believe there are some 'workaround' solutions to your issue, so I'll pour in some of my ideas, maybe it will help you out a bit.
Idea 1: Position absolute and a bunch of :nth-child selectors
In order to make the .item have their width relative to .list wrapper, you can absolute position these items, and set .list wrapper to position relative, so that the .item width will be calculated based on .list width.
The major downfall of this idea would be that you have to position these elements next to each, like using the left property, but passing it like a loop:
first item will have left: 0;
second item will have left: 50%;
third item will have left: 100%;
and so on...+50% to the next items
You can either pour in a bunch of :nth-child(n), each with +50% left prop. from each other, OR use some sass stuff to make it faster.
Check out the demo here & sass demo here
*,
*:after,
*:before {
box-sizing: border-box;
}
.wrapper {
width: 400px;
overflow-y: hidden;
overflow-x: scroll;
border: 1px solid black;
/*make the grandparent, .wrapper, relative, so that the grandchilds, .item,
will calculate their width based on this width*/
position: relative;
}
.list {
list-style-type: none;
border: 1px solid red;
width: 2000px;
margin: 50px 0;
padding: 0;
/*since everyone has position absolute, theres no content flow, so a fixed height
has to be supplied*/
height: 200px;
}
.item {
width: 50%;
border: 1px solid green;
position: absolute;
left: 0;
/*you can set a height here, or position them like I did bellow*/
top: 51px;
bottom: 51px;
}
/*now the fun part starts
somehow these .items have to have left: +50% for each of them, like a loop somehow,
so you can either pour in a lot of nth-child(), for how many children you think this
list is going to have, or use sass to write it faster like i did here:
*/
.item:nth-child(1) {
left: 0;
}
.item:nth-child(2) {
left: 50%;
}
.item:nth-child(3) {
left: 100%;
}
.item:nth-child(4) {
left: 150%;
}
.item:nth-child(5) {
left: 200%;
}
.item:nth-child(6) {
left: 250%;
}
.item:nth-child(7) {
left: 300%;
}
.item:nth-child(8) {
left: 350%;
}
.item:nth-child(9) {
left: 400%;
}
.item:nth-child(10) {
left: 450%;
}
.item:nth-child(11) {
left: 500%;
}
<div class="wrapper">
<ul class="list">
<li class="item"></li>
<li class="item"></li>
<li class="item"></li>
<li class="item"></li>
</ul>
</div>
Idea 2: Display: flex
Using display: flex on .wrapper, will allow you to have the widths of the .item to be relative to their grandparent.
The major downfall of this idea would be that the width of .list element, will be overwritten by the width of .wrapper, no matter if you specify it or not. However, not all is lost, if you need that specific width for some styling, you can specify it, and use some pseudo classes with width: inherit, so they'll stretch to whatever width you specified in the first place.
Check out the demo here
*,
*:after,
*:before {
box-sizing: border-box;
}
.wrapper {
width: 400px;
overflow-y: hidden;
overflow-x: scroll;
border: 1px solid black;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
/*bring on the awesomeness*/
margin: 20px;
}
.list {
list-style-type: none;
/*border: 1px solid red;*/
/*you can keep this defined width, items will calculte their width
based on .wrapper class, wich will overwrite this classes width,
however if you have some use for this width, consider using :after, :before
classes like I did bellow, with .list:before*/
position: relative;
z-index: 1;
width: 2000px;
white-space: nowrap;
margin: 20px 0;
padding: 0;
font-size: 0;
/*display inline block extra spacing ....*/
}
.list:before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: inherit;
/*it will inherit the width you set above*/
border: 1px solid red;
}
.item {
display: inline-block;
vertical-align: top;
height: 200px;
width: 50%;
border: 1px solid green;
font-size: 16px;
/*bump back the font-size*/
}
<div class="wrapper">
<ul class="list">
<li class="item">a</li>
<li class="item">b</li>
<li class="item">c</li>
<li class="item">d</li>
</ul>
</div>
<div class="wrapper">
<ul class="list">
<li class="item"></li>
<li class="item"></li>
<li class="item"></li>
<li class="item"></li>
</ul>
</div>
.wrapper {
width: 400px;
border: 1px solid black;
}
.list {
list-style-type: none;
border: 1px solid red;
width: 400px;
display: block;
white-space:nowrap;
padding: 0;
margin: 0;
}
.item {
display: inline-block;
height: 200px;
width: 47%;
border: 1px solid green;
padding: 1%;
}
http://jsfiddle.net/btsewL9v/
I would suggest something like this..
EDIT:
I don't know how many items you are trying to cram into the list, but take a look at this:
http://lea.verou.me/2011/01/styling-children-based-on-their-number-with-css3/

I am creating a horizontal list of months for a fixed size the list is overlapping

This is the Demo and correct me
HTML
<div id = "container">
<ul>
<li><a href="#" style="text-decoration: none;" > JANUARY </a> </li>
<li> FEBURAY </li>
<li><a href="#" style="text-decoration: none;" > MARCH </a> </li>
<li> APRIL </li>
<li> MAY </li>
<li> JUNE </li>
<li> AUGUST</li>
<li> SEPTEMBER</li>
</ul>
</div>
css
#container {
width: 550px;
height: 50px;
background: blue;
border: 2px solid;
overflow: hidden;
}
#container ul li {
display:inline;
padding: .8em 0.5em;
background: yellow;
border-radius: 35%;
margin-left:5px;
text-decoration: none;
}
#container ul li a:hover {
color: #fff;
background-color: #369;
}
Please check the following fiddle http://jsfiddle.net/juc6P/3/
make the following changes in the css
#container
{
width: 550px;
background: blue;
border: 2px solid;
overflow: hidden;
/*either remove height from here so that its set to auto or increase the width*/
}
#container ul li {
display:inline-block;
/*det display property to inline block*/
padding: .8em 0.5em;
background: yellow;
border-radius: 35%;
margin-left:5px;
text-decoration: none;
}
Make the following adjustment to your CSS file.
#container {
width: 550px;
background: blue;
border: 2px solid;
overflow: hidden;
}
Hear I have removed fixed height of the #container.
#container ul li {
display:inline-block;
line-height: 50px;
padding: .8em 0.5em;
background: yellow;
border-radius: 35%;
margin-left:5px;
text-decoration: none;
}
change the line-height to adjust the height of the row.

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

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

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