HTML CSS flexible growing lists - html

I'm trying to build a react components, which renders 2 lists. Both lists can dynamically get bigger or smaller.
I've got 100% space vertically. If both lists are big, than every list should take 50% height.
If any list isn't big enough to take the whole 50% height space, than the other one should grow.
I can't find a working solution so far. I think flex-grow and shrink is a good way to do it, but it doesnt work for me.
.container {
display: flex;
flex-direction: column;
flex: 1 1;
overflow-y: hidden;
}
.list_1 {
display: flex;
flex-direction: column;
flex: 1 1 auto;
overflow-y: auto;
}
.list_2 {
display: flex;
flex-direction: column;
flex: 1 1 auto;
overflow-y: auto;
}
<div class="container">
<div class="list_1">
<li>Item 1a</li>
<li>Item 1b</li>
<li>Item 1c</li>
</div>
<div classs="list_2">
<li>Item 2a</li>
<li>Item 2b</li>
<li>Item 2c</li>
</div>
</div>
I tried so many thinks from documentations but nothing works..

As you can see in the following snippet, I have given flex: 1 to both .list-1 and .list-2.
So when the second list grow, the first one shrinked.
If both has equal items, both will have 50% width also.
Please check and try updating your code with this solution.
.container {
display: flex;
flex-direction: column;
border: 1px solid blue;
height: 300px;
}
.list_1, .list_2 {
flex: 1;
border: 1px solid #ddd;
}
<div class="container">
<div class="list_1">
<ul>
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ul>
</div>
<div class="list_2">
<ul>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ul>
</div>
</div>

Related

Set space-between between flex list items [duplicate]

This question already has answers here:
How can I align one item right with flexbox?
(5 answers)
In CSS Flexbox, why are there no "justify-items" and "justify-self" properties?
(6 answers)
Closed 2 years ago.
I've got a navigation which looks sort like a this one under, and li items inside are flex items. This menu is rendered from the outside, and I'm not able to wrap any of the items inside the dedicated container.
What I'm trying to achieve is to set space-between between the last item and the other ones on the left. I've tried to do it with a margin-left on the last child, but it's not a nicest solution.
Is there a CSS option to "wrap" the last item somehow, so there's always space between that one and the ones on the left?
.container {
max-width: 1000px;
background-color: lightblue;
}
ul {
display: flex;
justify-content: space-between;
}
.last {
background: red;
}
<div class="container">
<ul>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li class="last">Last Item</li>
</ul>
</div>
Using margin-left on the last element is a good solution. However, you can improve your implementation by using the :last-child selector:
ul li:last-child {
margin-left: 10px;
}
Instead of manually assigning the last class to the last child.
EDIT: If you mean you want your last child to be aligned all the way to the right. You can separate them into different lists, and use justify-content: space-between:
.container {
max-width: 1000px;
background-color: lightblue;
display: flex;
justify-content: space-between;
}
ul {
display: flex;
}
ul li {
width: 3rem;
}
.right li {
background-color: red;
}
<div class="container">
<ul class="left">
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ul>
<ul class="right">
<li>Item</li>
</ul>
</div>

How to create a three-column responsive layout with icons and text?

I tried creating a three-column layout like below (click on the image to see it larger) :
It's basically an unordered list. I used display: flex on the ul element and FontAwesome to display those icons.
ul class="goals-list">
<li><i class="fas fa-sun goals-icon"></i>Development of wind and solar power for the community. </li>
...
...
...
</ul>
As you can see the columns don't align well. The second column "Paving the community's roads", "Free Wifi", and "Doctors without borders visits" don't align at the same level.
I need a layout that aligns like a grid:
item1 item2 item3
item4 item5 item6
As the screen size is getting smaller I want them to wrap and automatically adjust like so:
item1 item2
item3 item4
item5 item6
mobile portait:
item1
item2
item3
item4
item5
item6
I also want a little bit of space between the icons and the text. I would like to know how would you approach this problem. If you would be able to give me some ideas I would be grateful.
The problem is I don't know where to start. I'm not even sure if using an unordered list is the right way to approach this problem.
The reason I have three columns is because I have a max-width: 1200px set for the container and that allows three columns to fit on the screen, but I think three columns look great on large 1920×1080 screens.
You can do it using below css:
.goals-list{
display: flex;
align-items: center;
justify-content: space-between;
}
li{
list-style-type: none;
display: flex;
align-items: center;
width: 33.33%;
word-break: break-all;
}
#media only screen and (max-width: 991px){
li{
width: 50%;
}
}
#media only screen and (max-width: 767px){
li{
width: 100%;
}
}
ul {
display: flex;
list-style: none;
flex-wrap: wrap;
margin: 0;
padding: 0;
}
li {
flex: 0 0 33.33333%;
}
#media (max-width: 1200px) {
li {
flex: 0 0 50%;
}
}
#media (max-width: 780px) {
li {
flex: 0 0 100%;
}
}
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
</ul>
You can do this with css without using media queries.
ul {
display: flex;
flex-wrap: wrap;
}
ul li {
flex: 1 0 400px;
}
The 400px in the flex property sets that the element should be at least 400px (the actual property is flex-basis) this makes that if the available size is too small for 3 columns it will automatically make 2 columns of 500px (if the screen is 1000px).
You can use grid layout and CSS variables.
* {
margin: 0;
padding: 0;
}
.goals-list {
--column-num: 3;
display: grid;
grid-template-columns: repeat(var(--column-num), 1fr);
list-style: none;
}
li {
height: 100px;
background: red;
border: 3px solid black;
box-sizing: border-box;
}
#media (max-width: 1200px) {
.goals-list {
--column-num: 2;
}
}
#media (max-width: 780px) {
.goals-list {
--column-num: 1;
}
}
<ul class="goals-list">
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
</ul>

Flexbox element not scrolling overflow

I'm currently trying to make a sidebar layout work. I feel like I'm nearly there but the last bit is just not working.
html,body {
width: 100%;
height: 100%;
}
#wrapper {
display: flex;
width: 100%;
height: 100%;
}
.sidebar {
height: 100%;
position: fixed;
width: 200px;
background: red;
overflow: auto;
flex-direction: column;
display: flex;
}
ul {
padding: 0;
margin: 0;
}
.menu {
flex: 1;
background: rgb(150,0,0);
}
.users {
overflow: auto;
max-height: 240px;
min-height: 100px;
}
<div id="wrapper">
<div class="sidebar">
<ul class="menu">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
<li>item 5</li>
</ul>
<ul class="users">
<li>user 1</li>
<li>user 2</li>
<li>user 3</li>
</ul>
</div>
<div class="content">
</div>
</div>
Here is a fiddle of the layout which works better to see the issue than the above snippet:
https://jsfiddle.net/ybp4og8w/1/
All works great except when the height of the window gets really small, smaller than the menu items list. The content at the bottom disappears off screen. Ideally I'd like to have the user list sticky at the bottom (which is correct right now but I've also had this issue when messing with the code), not overlap the menu items when the height gets small but instead make the sidebar become scroll-able.
Any tips on how to achieve this?
I see your jsfiddle and apply this code in #sidebar
overflow-y:scroll;
May be this helpful.
Thanks!

Create a two column layout that fits to content with Flexbox

I have a two column layout. Column 1 is a heading. Column 2 is a list.
I want the columns to fit to content. (e.g. Column 1 should be as wide as it's contents)
I also want the list to be horizontal.
I want to use Flexbox, so I can change items in the list and have the layout adapt accordingly.
E.g. So it looks like this:
How can I do this?
Here is my code (Codepen is here):
<div class="wrapper">
<nav class="topics">
<span class="unit unit-header">Topics: </span>
<ul id="list" class="list unit">
<li>All</li>
<li>Topic 1</li>
<li>Topic 2</li>
<li>Topic 3</li>
<li>Topic 4</li>
<li>Topic 5</li>
<li>Topic 5</li>
</ul>
</nav>
</div>
.wrapper {
width: 960px;
margin: auto;
padding-top:20px;
}
.topics {
display: flex;
}
.unit {
flex: 1 auto;
}
.list {
display:flex;
}
.list li {
flex: 1 auto;
}
If I add the following code, it works:
.unit-header {
display: table;
padding-right: 5%;
}
However, mixing table with flex-box seems a bit hacky to me. Is there a better way?
Have you tried using this instead?
.unit-header {
flex: 0 1 auto;
}
The above shorthand property means:
flex-grow: 0
flex-shrink: 1
flex-basis: auto

Remove unnecessary space in CSS3 columns

I'm experimenting with the latest columns feature in CSS3. Each ul has varying heights, and I want them to have equal margins above and below. At the moment, because one ul is much longer than the rest, it is pushing the second row down. Is it possible for the longest ul to not force so much space beneath it?
http://jsfiddle.net/t5ng3/
CSS:
.wrapper {
background-color: grey;
max-width: 600px;
-webkit-column-width: 50%;
}
ul {
background-color: orange;
display: inline-block;
vertical-align: top;
width: 20%;
}
HTML:
<div class="wrapper">
<ul>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ul>
<ul>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ul>
<ul>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ul>
<ul>
<li>Item</li>
<li>Item</li>
</ul>
<ul>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ul>
</div>
That's because of white space, which will cause normally a 4px offset, inorder to solve this, there are various ways, the cheap one is to use margin-left: -4px; but this will fail if the font-size > 100%, another way is to use font-size: 0; on the parent element, and the last one is to take out the indentation/white space from the source by sticking up the ul elements..
Demo
You can also float your elements to the left but for this it will be better if you wrap them inside a container div/section element.
Now I am not sure whether you are aware of this or not but you might like to have a look at column-count property which will do a similar job without breaking yourself the ul elements..
The "columns" you're seeing are purely the result of your lists being inline-block, not because you're using column-width. The column-width property does not appear to work as you would expect with a percentage value.
If you want exactly 2 columns, then you would use column-count: 2 rather than column-width: 50%.
http://jsfiddle.net/t5ng3/12/
.wrapper {
background-color: grey;
max-width: 600px;
-webkit-columns: 2;
-moz-columns: 2;
columns: 2;
}
ul {
background-color: orange;
}
If the child elements should not be split across columns, then the break-inside property is what you're looking for rather than trying to use display: inline-block.
ul {
background-color: orange;
-webkit-column-break-inside: avoid; /* old name */
page-break-inside: avoid; /* Firefox uses non-standard property */
break-inside: avoid;
}
You may wish to remove the top margin on the first element:
ul:first-child {
margin-top: 0;
}
It is happening because there is space between </ul> and <ul>. inline-block elements leave space.
Removeing space i.e. writing </ul><ul> will resolve your problem.
Updated fiddle.