CSS Flexbox - Set item width to largest one - html

I have a list of items which should display in a row. I dynamically add some items with different text lengths to the list. Is it possible to align the items on the left side and set the width of each item to the width of the largest one?
I added an image to clarify it :
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item with long text added dynamically</li>
</ul>

To get the width of your element using javascript :
document.getElementById('yourID').clientWidth
Then you can use this value to adjust your other items

I don't think this is possible with just the flex-box model and no javascript. A solution (depending on your real use case) would be to use display: table :
ul {
display: table;
list-style-type: none;
table-layout: fixed;
padding: 10px;
position: relative;
}
ul::before {
position: absolute;
z-index:-1;
content: " ";
left:0px;
top:0px;
bottom:0;
width: 500px;
background: #999;
}
li {
display: table-cell;
color: white;
text-align: center;
background: black;
padding: 5px;
height: 30px;
line-height: 30px;
width: 33%;
white-space: nowrap;
}
li+li {
border-left: 10px solid #999;
}
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item with long text</li>
</ul>
Note that it's still tricky but I don't see any better css based solution.

Related

Why do my list items overlap?

I want my list items to be displayed next to each other but for some reason they always overlap. Can someone tell me how to fix this?
#background {
height: 1000px;
background-image: url("https://static.pexels.com/photos/33045/lion-wild-africa-african.jpg");
background-position: center center;
background-size: cover;
}
#menu {
background-color: white;
border: 2px solid grey;
}
ul {
list-style: none;
background-color: white;
}
li {
display: inline-block;
padding: 5px 10px 5px 10px;
border: 2px solid grey;
overflow: none;
position: fixed;
background-color: white;
}
<div id="background">
<div id="menu">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
</ul>
</div>
</div>
Thank you in advance!
You need to remove position: fixed in 'li' element, because if you giving every 'li' element position fixed that will make your item always overlap.
May be you can try update your 'ul' and 'li' element style like this code bellow:
ul {
list-style: none;
position: fixed;
}
li {
display: inline-block;
padding: 5px 10px 5px 10px;
border: 2px solid grey;
overflow: none;
background-color: white;
}
That's because you have define position: fixed for li tags.
#background {
height: 1000px;
background-image: url("https://static.pexels.com/photos/33045/lion-wild-africa-african.jpg");
background-position: center center;
background-size: cover;
}
#menu {
background-color: white;
border: 2px solid grey;
}
ul {
list-style: none;
background-color: white;
}
li {
display: inline;
padding: 5px 10px 5px 10px;
border: 2px solid grey;
overflow: none;
//position: fixed;
background-color: white;
}
<div id="background">
<div id="menu">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
</ul>
</div>
</div>
Take out the position: fixed. This fixes an element within the browser viewport and removes it from the flow. Not what you want.
https://developer.mozilla.org/en-US/docs/Web/CSS/position
fixed
The element is removed from the normal document flow; no space is created for the element in the page layout. Instead, it is positioned relative to the screen's viewport and doesn't move when scrolled. Its final position is determined by the values of top, right, bottom, and left.
give position fixed to ul and you will get list item properly
#background {
height: 1000px;
background-image: url("https://static.pexels.com/photos/33045/lion-wild-africa-african.jpg");
background-position: center center;
background-size: cover;
}
#menu {
background-color: white;
border: 2px solid grey;
}
ul {
list-style: none;
background-color: white;
position: fixed;
padding:5px;
}
li {
display: inline-block;
padding: 5px 10px 5px 10px;
border: 2px solid grey;
overflow: none;
background-color: white;
}
<div id="background">
<div id="menu">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
</ul>
</div>
</div>

Diamond shape layout with CSS

I am attempting to layout an unordered list in a diamond form.
I cannot figure out how to do this without adding hacky <div>'s all over the place.
I'd rather keep it semantically a clean ul.
Code example (I can add id's, that is no problem.)
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
</ul>
I want it to look like this:
Perhaps something like this can be achieved with display: flex? Perhaps display: table-cell? I have tried everything so far, I cannot figure it out.
The layout can be achieved with flexbox all the way through:
ul {
display: flex;
flex-direction: column; /* 1 */
flex-wrap: wrap; /* 1 */
height: 200px; /* 2 */
list-style: none;
padding: 0; /* 3 */
}
li {
flex: 0 0 100%; /* 4 */
display: flex;
justify-content: center; /* 5 */
align-items: center; /* 5 */
background-color: lightyellow;
}
li:not(:first-child):not(:last-child) { /* 6 */
flex-basis: 50%;
}
span {
height: 50px;
width: 100px;
background-color: lightgreen;
border: 1px solid black;
display: flex; /* 7 */
justify-content: center; /* 7 */
align-items: center; /* 7 */
}
* { box-sizing: border-box; }
/* grid lines
ul { border: 1px dashed black; }
li { border: 1px solid red; }
*/
<ul>
<li><span>item 1</span></li>
<li><span>item 2</span></li>
<li><span>item 3</span></li>
<li><span>item 4</span></li>
</ul>
jsFiddle
Notes:
Set the container to column wrap.
For flex items to know where to wrap, a height must be defined on the container.
Remove ul default padding.
Make list items consume all column space.
Center spans vertically and horizontally.
Make second and third list items consume half column space, so both fit in one column.
Center text vertically and horizontally.
I'm interested in seeing if anyone comes up with something a little more clever. Here's the simplest route that came to mind - just using absolute positioning.
ul {
list-style: none;
padding: 0;
position: relative;
width: 200px;
height: 80px;
}
li {
border: 2px solid #000;
font-size: 18px;
padding: 4px;
position: absolute;
}
li:nth-child(1) { top: 50%; left: 0; transform: translateY(-50%); }
li:nth-child(2) { top: 0; left: 50%; transform: translateX(-50%); }
li:nth-child(3) { bottom: 0; left: 50%; transform: translateX(-50%); }
li:nth-child(4) { top: 50%; right: 0; transform: translateY(-50%); }
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
</ul>
ul li{
position:absolute;
}
#item1{
margin-left:10%;
}
#item2{
margin-top:5%;
}
#item3{
margin-top:5%;
margin-left:20%;
}
#item4{
margin-top:10%;
margin-left:10%;
}
<ul >
<li id=item1>item 1</li>
<li id=item2>item 2</li>
<li id=item3>item 3</li>
<li id=item4>item 4</li>
</ul>
here is my version ... just made it work ... you can find a better way or make it better...
another approach with flex (for info since another one is already given):
ul {
display:inline-flex;/* or flex + margin:auto for the demo*/
flex-flow:column;
flex-wrap:wrap;
height:6.25em;/* an height is required to force wraping into columns , mind basic margin, padding and lines wanted /set for li */*/
padding:0;
margin:0;
width:25em;/* whatever you want*/
background:gray;
}
li {
display:block;/* removes the bullet */
padding:0.25em;
border:solid;
width:32%;
margin:0.5em;/* whatever, just mind for ul height*/
box-sizing:border-box;/* includes padding and borders into height calculation .... */
}
li:first-of-type,li:last-of-type {
margin:2em 0;/* increase at least margin-top */
}
body {
text-align:center;/* to center inline-flex-container and li's text */
}
ul:hover {
font-size:1.25em;/* see behavior when font-size is different */
}
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
</ul>
You can just change the 2nd and 3rd <li>'s into <span>'s and wrap them in a <li>:
ul {
list-style: none;
}
li {
display: inline-block;
padding: 0;
vertical-align: middle;
}
li > span {
display: block;
}
li:not(:nth-of-type(2)),
li > span {
border: 2px solid black;
margin: 4px;
}
<ul>
<li>item 1</li>
<li>
<span>item 2</span>
<span>item 3</span>
</li>
<li>item 4</li>
</ul>
It's simple, quick, and doesn't require any sort of weird positioning.
To be fully semantically correct, you should technically use an ol, since you have an order to your items:
Usage note: The <ol> and <ul> elements both represent a list of items. They differ in that, with the <ol> element, the order is meaningful. As a rule of thumb to determine which one to use, try changing the order of the list items; if the meaning is changed, the <ol> element should be used, otherwise you can use <ul>.

Need help in CSS nav Style

I am trying to build CSS nav bar but i am in a bit trouble. In my code, background box is collapsing with content inside it .My question is why it is collapsing and can it be solved by not giving height to the box.Here is my code.
HTML
<div class="item">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
CSS
body {
color: #648;
}
.item ul {
list-style: none;
padding: 0;
margin: 0;
}
* {
}
.item {
padding: 20px;
width: 70%;
/* height: 65px; */
background-color: blanchedalmond;
margin: 50px auto;
border-radius: 10px;
}
.item li {
float: left;
width: 45px;
margin: 10px;
border-radius: 10px;
padding: 20px;
background-color: aqua;
}
Use display:inline or display:inline-block instead of float:left.
http://jsfiddle.net/x2ubrrh3/
Update
When display:flex is used you have to stop the elements from floating afer your list is finished (clear:both)
See here: http://jsfiddle.net/x2ubrrh3/1/

On hover over li make second row li move

I am trying to show border color on hover over the list of items. When i move mouse over first row items, the second row items move towards right. Please check jsFiddle
<ul class="tiles">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
css
ul.tiles { width: 400px; }
ul.tiles li {
float: left;
list-style-type: none;
width: 100px;
height: 100px;
margin: 10px;
background: white;
}
ul.tiles li:hover {
border: 1px solid black;
}
}
Add a transparent border to your li:
li {
border: 1px solid transparent;
}
ul.tiles { width: 400px; }
ul.tiles li {
float: left;
list-style-type: none;
width: 100px;
height: 100px;
margin: 10px;
background: white;
}
ul.tiles li:hover {
border: 1px solid black;
}
ul.tiles li {
border: 1px solid transparent;
}
<ul class="tiles">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
you can user box-sizing: border-box; on the ul.tiles li
http://jsfiddle.net/gm8zvfsk/
The box-sizing property is used to tell the browser what the sizing
properties (width and height) should include.
Should they include the border-box or just the content-box which is
the default value of the width and height properties.
For example, if you want two bordered boxes side by side, it can be
achieved through setting box-sizing to "border-box". This forces the
browser to render the box with the specified width and height, and
place the border and padding inside the box.
JS Fiddle.
As Praveen said, using outline fixes the issue.
ul.tiles li:hover {
outline: 1px solid black;
}

li alignment behaves strange if remove new lines after items

I have next navigation block in html template
<nav class="navigation">
<ul class="nav">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
</ul>
</nav>
with css
.navigation {
padding: 0 0 19px;
}
.nav {
font: 20px/22px "futura_demi_c", Arial, Helvetica, sans-serif;
text-align: justify;
text-align-last: justify;
list-style-type: none;
padding: 0;
margin: 0;
}
.nav:after {
content: "";
display: inline-block;
width: 100%;
overflow: hidden;
}
.nav li {
display: inline-block;
}
.nav a {
color: #020202;
}
Items have to be aligned justify in navigation block and occupy all entire width. And they are, if I use the code above.
But if i remove new lines after each 'li' all items move to the right without spaces between them
<nav class="navigation">
<ul class="nav">
<li>Item 1</li><li>Item 2</li><li>Item 3</li><li>Item 4</li><li>Item 5</li><li>Item 6</li>
</ul>
</nav>
Is it normal behaviour or my css is wrong?
Behaviour is the same for all browsers.
Jsfiddle examples: correct - http://jsfiddle.net/x9zfP/1 wrong - http://jsfiddle.net/AMK8z/1/
Tnx!
The behaviour is expected, because of the display: inline-block. This means whitespace between the elements will be considered.
See also CSS-Tricks - Fighting the Space Between Inline Block Elements
your css is wrong, "." is for class and "#" for id.
your ul has an id, so first replace all occurencies of ".nav" with "#nav"
here the correct css:
.navigation {
padding: 0 0 19px;
}
#nav {
font: 20px/22px "futura_demi_c", Arial, Helvetica, sans-serif;
text-align: justify;
text-align-last: justify;
list-style-type: none;
padding: 0;
margin: 0;
width:100%;
display:table
}
/* useless
#nav:after {
content: "";
display: inline-block;
width: 100%;
overflow: hidden;
}
*/
#nav li {
display: table-cell;
}
#nav a {
color: #020202;
}
basically your parent element need to have a width, and child need the property "display:table-cell".
The behavior is normal because your li has no padding or margin, so there's nothing there to keep the split apart.
This fixes your issue:
.nav li {
display: inline-block;
padding: 0 30px;
}
http://jsfiddle.net/AMK8z/1/