I have an html page structure like this:
<div id="list">
<ul>
<li style="background-color:orange;">Lorem</li>
<li style="background-color:red;">Lorem</li>
.............
<li style="background-color:black;">Lorem</li>
<li style="background-color:blue;">Lorem</li>
</ul>
</div>
On this page, I want all list element to have the same width - I don't care about the content, only the color is really important in this case - and I want all thos elements to fit in their parent div (#list) when the page just loaded, this mean no scroll.
And this list is not final, I can add or delete somme elements in my list after the page load. I would like to know if there is a CSS way to get this result, JavaScript is not really suitable in this case.
Is that possible ?
You can achieve this kind of behavior by using flex:
HTML structure:
<div id="list">
<ul>
<li style="background-color:orange;">Lorem</li>
<li style="background-color:black;">Lorem</li>
...
<li style="background-color:blue;">Lorem</li>
</ul>
</div>
CSS:
#list {
border-style: solid;
border-width: 3px;
white-space: nowrap;
}
#list ul {
display: flex;
flex-direction: row;
margin: 5px;
padding: 0;
}
#list ul li {
border-style: solid;
height: 50px;
list-style-type: none;
}
Here is a working demo: http://jsfiddle.net/kmbxawdd/1/
Yes, you can use flexible boxes:
#list {
display: flex; /* Magic begins */
border: 3px solid;
padding: 1em;
}
#list > li {
width: 0; /* Ignore the width of the content */
flex-grow: 1; /* Distribute remaining space equally */
overflow: hidden; /* Hide possible overflow */
height: 50px;
border-style: solid;
}
<ul id="list">
<li style="background-color:orange;">Lorem</li>
<li style="background-color:red;">Lorem</li>
<li style="background-color:black;">Lorem</li>
<li style="background-color:blue;">Lorem</li>
</ul>
JSFiddle Example
Flexbox is your friend.
div#list {
height: 800px; /*Whatever you want, really*/
width: 800px; /*Again, substitute this with whatever size you like*/
}
div#list ul {
height: 100%;
width: 100%;
display: flex;
flex-flow: row nowrap;
align-content: stretch;
list-style: none;
padding: 0;
margin: 0;
}
div#list ul li {
-webkit-flex: 0 1 100%;
flex: 0 1 100%;
}
You can try to set display to "table" on list and "table-cell" on li. But it will work as you expect only if all li elements will contain content with same width. And list itself must have explicitly defined width, of course.
Related
I'm trying to create a sidebar which has 2 boxes. Each box can contain any number of list items(could be hundreds of items), but it's likely that the first will contain only a few items, and the second will contain many more.
I have the following (created in ReactJS):
<div class="drawer">
<div class="drawerContainer">
<div class="sideboxWrapper">
<SideBox header="Box 1" />
<SideBox header="Box 2" />
</div>
</div>
</div>
Each SideBox generates the following structure:
<div class="sidebox">
<h2 class="boxheader">{header}</h2>
<div class="boxContent">
<ul class="sideboxList">
<li class="listItemText listItemTextCurrent">Item 1</li>
<li class="listItemText listItemTextCurrent">Item 2</li>
... more items ...
</ul>
</div>
</div>
So, first of all, I want the boxes to fill the sidebar, but not overflow it. If the boxes are short enough to both fit, then they should both take up as much space as they need, and any remaining space is left blank. If they don't both fit, then they should take up the available space, and the boxContent div should become scrollable.
.drawer {
flex: 0 0 240px;
height: 100%;
overflow-y: hidden;
padding: 10px 0;
}
.drawerContainer {
height: inherit;
overflow: hidden;
padding-bottom: 10px;
padding-top: 10px;
}
.sideboxWrapper {
display: flex;
flex-direction: column;
height: inherit;
overflow: hidden;
}
.sidebox {
margin: 10px;
padding: 0px;
flex-grow: 1;
flex-shrink: 1;
display: flex;
flex-direction: column;
}
.boxContent {
overflow-y: auto;
}
The problem I'm having is that when one of the lists is very long, the sideboxes just expand to fit it, even if that means going outside the sideboxWrapper (the overflow is hidden, so the part of the sidebox outside the sideboxWrapper can't be read). What I want to happen is that the flex layout arranges the sideboxes to fit inside the sideboxWrapper, and then the boxheaders are shown and the boxContent is resized (with scrollbars) to fit within the remaining space. So, a long list will have scrollbars.
How can I achieve this?
here is what could be your CSS , I added border so you can see where stands some of your boxes. Using flexbox on so many levels requires to follow clearly what you are doing and see where flex is avalaible and needed.
* {
box-sizing: border-box;
}
.drawer {
width: 240px;/* without a flex parent that works too */
height: 100vh;/* example for a full screen height */
overflow-y: hidden;
padding: 10px 0;
border: solid;
}
.drawerContainer {
height: 100%;
padding-bottom: 10px;
padding-top: 10px;
}
.sideboxWrapper {
display: flex;
flex-direction: column;
height: 100%;
border: solid green;
overflow: hidden;
}
.sidebox {
margin: 10px;
padding: 0px;
flex-basis: 50%;/* make it half */
display: flex;
flex-direction: column;
min-height: 0;/* what is needed */
}
.boxContent {
flex-grow: 1;
overflow-y: auto;
}
I' trying to make a horizontal menu with special conditions
these are the rules I have to stick with:
html + css
menu should resize to the width of the container (100% of container).
so the wider the container the bigger (height, width) the menu
menu elements are images with different width
every image(menu element) is close to the next and previous (no gaps in between)
all dimensions should be expressed in % (no fixed size)
the code:
<div id="menu-container">
<ul>
<li><img src="myImg01"></li>
<li><img src="myImg02"></li>
<li><img src="myImg03"></li>
</ul>
</div>
css
#menu-container{
width:100%;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
display: table;
}
li {
display: table-cell;
}
li img{
width:100%;
}
this works in firefox and safari
does not in chrome and similar... (it seems like all images are scaled in different %)
I've searched and did not found a similar issue
could you help please?
Will try to clarify.
I need that all images retain their aspect ratio even after scaling
you should add max-width in your div , and make display flex wrap
hay I hope this example will be helpful, so try like this:
CSS
#menu-container{
width:100%;
border: 1px solid red;
}
ul {
margin: 0;
padding: 0;
display: flex;
align-items: center;
flex-wrap: nowrap;
list-style-type: none;
}
li {
width: 10%;
height: 0;
padding-bottom: 10%;
background-repeat: no-repeat;
/*background-size: contain;*/
background-size: cover;
background-position: center center;
}
li a {
display: block;
width: 100%;
height: 0;
padding-bottom: 100%;
}
HTML
<div id="menu-container">
<ul>
<li style="background-image: url(https://static.scientificamerican.com/sciam/cache/file/4E0744CD-793A-4EF8-B550B54F7F2C4406_source.jpg);">
</li>
<li style="background-image: url(https://www.afd.fr/sites/afd/files/styles/visuel_principal/public/2019-01-07-16-19/mangrove%20couv.jpg);">
</li>
<li style="background-image: url(https://blog.nationalgeographic.org/wp-content/uploads/2020/05/May-11_Dorset-heathland_shutterstock_1332881306_sml-1140x450.jpg);">
</li>
</ul>
</div>
You can CSS grid.
#menu-container {
width:100%;
}
ul.menu {
display: grid;
grid-template-columns: 1fr 25% 2fr; // You can use percentages or the fr unit It represents a fraction of the available space in the grid container (works like Flexbox’s unitless values).
list-style-type: none;
margin: 0;
padding: 0;
}
This question already has answers here:
Align 3 unequal blocks left, center and right
(4 answers)
Closed 3 years ago.
I am creating simple navigation with flexbox CSS3 and I have a list with 3 items but those items have not specified width. Now I want to have the middle item to be placed in the center of the viewport. When I have that kind of situation my middle li is not centered on the viewport. Is there any way to center one item and other elements to be relative to this item?
See the differences between first and second navigation. On second navigation when there is one item it's properly centered to the viewport. I want to center the first one like second. Li element with class middle must be at the center of the viewport.
EDIT
Some of the answers did the typical moving first and last LI to the edges of the UL LIST. That's not the point, MIDDLE li must be at the center of the viewport and first and last LI should have only paddings and width: initial
ANSWER
I cannot add answer here so I paste 'codepen' link with answer which I want to get
https://codepen.io/freestyle09/pen/xxxvwPm
UPDATED CODE
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
nav {
border: 1px solid red;
display: flex;
justify-content: center;
}
ul {
display: flex;
justify-content: center;
list-style: none;
border: 1px solid green;
width: 1200px;
}
ul > li {
padding: 20px;
white-space: nowrap;
border: 1px solid blue;
}
li:not(.middle) {
flex-basis: 0%;
flex-grow: 1;
}
nav .test {
display: flex;
justify-content: center;
width: 800px;
border: 2px solid pink;
padding: 20px
}
<nav>
<ul>
<li><span>Lorem ipsum sit</span></li>
<li><span>Lorem ipsum sit</span></li>
<li class='middle'><span>Vey long string, very very very long string</span></li>
<li><span>About</span></li>
<li><span>About</span></li>
</ul>
</nav>
<nav>
<div class='test'>
<p>Vey long string, very very very long string</p>
</div>
</nav>
I'm not entirely sure I understand what you're trying to accomplish but this sounds like maybe what you're after?
Addendum, you just described the purpose of a table for tabular data. Hope this helps, cheers!
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
nav {
border: 1px solid red;
}
ul {
display: table;
width: 100%;
list-style: none;
align-items: center;
border: orange 3px dashed;
}
ul > li {
display: table-cell;
text-align: center;
padding: 20px;
border: green 1px dotted;
}
ul > li:nth-child(odd) {
width: 20%;
}
<nav>
<ul>
<li>Lorem ipsum sit</li>
<li class='middle'>Vey long string, very very very long string</li>
<li>About</li>
</ul>
</nav>
<nav>
<ul>
<li>Vey long string, very very very long string</li>
</ul>
</nav>
On way to approach this is to give the li.middle element a higher flex-grow priority and a lower flex-shrink priority than the other li elements.
The style flex is a shorthand for:
flex-grow
flex-shrink
flex-basis
It will take flex values such as these:
flex: 1 1 20%; // flex-grow priority of 1, flex-shrink priority of 1, pre-flex starting width of 20%
flex: 2 0 60%; // flex-grow priority of 2, will never shrink, pre-flex starting width of 60%
Using these two values above we can declare that:
one class of element has a default width of 20% and can both grow and shrink to fill the width available
another class of element has a default width of 60%, is twice as likely to grow wider than the other elements, but can never shrink to less than 60%
Working Example:
nav {
border: 1px solid red;
}
ul {
display: flex;
list-style: none;
justify-content: center;
border: 1px solid green;
margin-left: 0;
padding-left: 0;
}
ul > li {
padding: 20px;
}
li {
border: 1px solid blue;
}
li {
flex: 1 1 20%;
}
li.middle {
flex: 2 0 60%;
text-align: center;
}
<nav>
<ul>
<li>Lorem ipsum sit</li>
<li class="middle">Very long string, very very very long string</li>
<li>About</li>
</ul>
</nav>
<nav>
<ul>
<li class="middle">Very long string, very very very long string</li>
</ul>
</nav>
Adding the following properties to your style should fix your problem.
ul > li {
padding: 20px;
flex: 1;
text-align: center;
}
That will set all the li element sizes to be equal and align their text to the center of it.
On a simple flex-box layout, I am trying to align nav items to the end of the first (left) side-bar. My first thought was to recreate the aside main aside layout with :before element :after so the nav items would always align to the sidebar, but I can't seem to get the :before and :after elements to match the size of each aside. Here is an example of what I am trying to do
Flex Example
And here is the current code I am using
http://codepen.io/anon/pen/GoJEbX?editors=010
I wouldn't be using flex-wrapping rows here. It makes sense to start with flex-direction:column to get the full 100% height and then put the middle content (main and aside elements) in their own flex-container which can then grow as much as is required.
The horizontal layout is all flexbox.
Based on the original code the aside are 1/12th wide each (flex:1) while the main is 10/12ths (flex:10).
Therefore to line up the menu with the main, the menu itself needs to be shifted over the same amount (which means it's 11/12ths [flex:11] so the pseudo-element is just flex:1.
Adjust as required.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
height: 100%;
}
body {
min-height: 100%;
}
.wrapper {
display: flex;
flex-direction: column;
height: 100%;
}
nav {
display: flex;
}
nav:before {
content: '';
flex: 1;
background: plum;
/* for reference */
}
nav ul {
display: flex;
background: blue;
list-style-type: none;
flex: 11;
}
nav ul a {
display: block;
padding: 20px 20px 0 0;
color: white;
text-decoration: none;
}
.content {
flex: 1;
display: flex;
}
main {
background: red;
flex: 10;
}
aside {
background: green;
flex: 1;
}
footer {
background: yellow;
}
<div class="wrapper">
<header>
<nav>
<ul>
<li>Item 1
</li>
<li>Item 2
</li>
<li>Item 3
</li>
</ul>
</nav>
</header>
<div class="content">
<aside>Sidebar 1</aside>
<main>Main Content Area</main>
<aside>Sidebar 2</aside>
</div>
<footer>Footer</footer>
</div>
Codepen Demo
I am using flexbox to layout my things. I have 5 lis (so far, but that will change), with the following width: flex-basis:calc(100%/3). So there will be 3 li's in each row. The wrapper (ul) has a width of 70%.
So far so good. The problem is, when I add a margin to the li's. When I add a margin to the li's, there will only be 2 li's in each row with some extra space, but I need 3.
So I found 2 solutions that give me other problems:
One solution would be to add the margin to the li's, let's say 10px. Then subtract 20px (10 * 2) from the width and height of each li's. I can't do that, because I need the li's to be the size I set, and not smaller.
Another solution would be to set justify-content to either space-around or space-between. The problem with that is that I need the lis to be in columns and rows, (like a chart). And if I change justify-content, the li's wouldn't be in a chart like order.
Is there a way to add a margin to the li without affecting any other property's?
(I'm open to JavaScript/JQuery if that's the only choice.)
JSFiddle
Here's a code snippet:
body, html {
height:100%; margin: 0; padding:0;
}
#flexWrapper {
display: flex;
justify-content: center;
height: 100%;
align-items: center;
overflow: auto;
}
#flexContainer {
width: 70%;
background-color:yellow;
list-style-type: none;
padding: 0;
margin: auto;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
align-items: center;
align-content:flex-start;
}
li {
background-color: tomato; border: 1px solid black; height:50px;
box-sizing: border-box;
flex-basis:calc(100%/3);
margin:10px;
}
<div id="flexWrapper">
<ul id="flexContainer">
<li class="flex-item">1</li>
<li class="flex-item">2</li>
<li class="flex-item">3</li>
<li class="flex-item">4</li>
<li class="flex-item">5</li>
</ul>
</div>
Ok, so I finally got an answer that works! I have to give partial credit to #Syahrul for starting up the idea (in the comments).
So basically what I'll be doing is this. If we want to add 1.5% of a margin, we'll add (1.5 * 2) * 3 (1.5 * 2 because the margin is on both sides of every li. * 3 because we have 3li'sin every row.) to thewidthof the wrapper ('#flexContainer), so we have 79% of a width for #flexContainer.
Next, we'll subtract 3% (margin size (1.5 * 2)) from the width of the li. And that's flex-basis:calc(100%/3 - 3%).
And there you have it! Here's the updated JSFiddle
body, html {
height:100%; margin: 0; padding:0;
}
#flexWrapper {
display: flex;
justify-content: center;
height: 100%;
align-items: center;
overflow: auto;
}
#flexContainer {
width: 79%;
background-color:yellow;
list-style-type: none;
padding: 0;
margin: auto;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
align-items: center;
align-content:flex-start;
}
li {
background-color: tomato; border: 1px solid black; height:100px;
box-sizing: border-box;
flex-basis:calc(100%/3 - 3%);
margin:1.5%;
}
<div id="flexWrapper">
<ul id="flexContainer">
<li class="flex-item">1</li>
<li class="flex-item">2</li>
<li class="flex-item">3</li>
<li class="flex-item">4</li>
<li class="flex-item">5</li>
</ul>
</div>