Create a two column layout that fits to content with Flexbox - html

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

Related

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>

Reversing order of divs depending on width

I'm currently working on a menu consisting of two parts (see image). On mobile, I'd like to show these menu items stacked from top to bottom, but starting with the bottom menu and ending with the top menu. Is there any (clean) way to do this with CSS or will I have to create two menus and show the correct one depending on page width?
EDIT: To clarify, the image is just to show an example of what I mean. I'm wondering in a more general sense if it's possible to somehow reverse the divs in CSS (without absolute positioning etc).
EDIT 2: Apologies for not adding any code. Here's a small pen that shows the situation: https://codepen.io/anon/pen/GWwrMW
<div class="nav">
<ul class="nav__top">
<li>Sub Item 1</li>
<li>Sub Item 2</li>
</ul>
<ul class="nav__primary">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
.nav__top,
.nav__primary {
list-style: none;
margin: 0 0 20px 0;
text-align: right;
li {
display: inline-block;
padding: 10px;
background-color: #ccc;
}
}
On mobile, I want the sub items to be displayed underneath the main items.
You can do this with flex and flex-direction: column-reverse, or for more control, using the order property on flex children. But with your example, flex-direction: column-reverse would work.
.nav__top li,
.nav__primary li {
display: inline-block;
padding: 10px;
background-color: #ccc;
}
#media (max-width: 420px) {
.nav {
display: flex;
flex-direction: column-reverse;
}
.nav li {
display: list-item;
}
}
<div class="nav">
<ul class="nav__top">
<li>Sub Item 1</li>
<li>Sub Item 2</li>
</ul>
<ul class="nav__primary">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
This added CSS will reverse the order in the second menu:
.nav__primary {
display: flex;
flex-direction: row-reverse;
}
You can put it in a media query.
https://codepen.io/anon/pen/ryQjdg
ADDITION: I overread the wish of it to be stacked horizontally. In this case you need
.nav__primary {
display: flex;
flex-direction: column-reverse;
}
If you want responsive nav bar you have to use media queries. Something like this
#media screen and (max-width: 600px){
ul.topnav li {float: none;}}
This will work if your menu was built by list.
Figured it out. Since I only need to support mobile browsers I can use Flexbox:
.nav {
display: flex;
flex-direction: column-reverse;
}

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!

HTML center list items on second line

With a simple html list like in the example below, how do I get the list items to center when it goes onto a second line?
<div class="container">
<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 4</li>
<li>Item 5</li>
<li>Item 6</li>
</ul>
</div>
.container{max-width:500px;}
li{display:block;float:left;background:grey;}
http://jsfiddle.net/hzazvwte/
When the container is shrunk and the menu items start dropping into the line below, I would like them to be centered. How can I achieve this?
You have to remove float, set text-align: center; to the container, inline-block to items, reset margin / padding and eliminate white spacing between elements.
.container {
max-width: 500px;
margin: 0 auto;
text-align: center;
}
ul {
margin: 0;
padding: 0;
}
li {
display: inline-block;
/* float: left; */
background: grey;
margin: 0;
}
Fiddle: http://jsfiddle.net/hzazvwte/4/
Do you mean the text in the li items?
.container{max-width:300px;}
li{
display:block;
float:left;
background:grey;
width: 100px;
text-align: center;
}

CSS Distribute li over 2 rows, unlimited items

I want my li's to be distributed over 2 rows like this:
item 1 item 3 item 5 item 7 item 9 ....
item 2 item 4 item 6 item 8 ......
My CSS is really bad so I have no clue on how to achieve this and can't find anything on this... I tried some stuff with even and odd items, but I can't figure out how to force even items below odd items.
You can use flexbox to achieve this ordering. Support is pretty good (http://caniuse.com/#feat=flexbox) but you will need to provide fallbacks for older versions of IE.
ul {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 100px;
list-style-type: none;
margin: 0;
padding: 0;
width:200px;
}
li {
color: #000000;
height: 50px;
margin: 0;
padding: 0;
width: 100px;
}
<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>
</ul>
You can use :nth-child selector to select odd elements in that list items.
Here is an example:
CSS
ul {
position: relative;
white-space: nowrap;
}
li {
display: inline-block;
list-style-type: none;
padding: 0px 5px;
}
li:nth-child(2n) {
top: 100%;
position: absolute;
margin-left: -36px; /* Changes as per the width of the first element */
}
Working Fiddle