css flex shrink container width to fit its items - html

I'm displaying a list of same sized items in a flex div. I've aligned them to the left. However I'd like the list to be centred as a whole. Any suggestions about how to do this?
Please try to snipped below.
$('button').click(function(){
$('.list').toggleClass('hack')
});
.item {
width: 40px;
height: 40px;
background-color: skyblue;
border: 1px solid black;
}
.list-container {
width: 100px;
background-color: grey;
flex-direction: row;
display: flex;
}
.spacer {
flex: 1;
}
.list.hack {
width: 84px;
}
.list {
display: inline-flex;
flex-direction: row;
flex-wrap: wrap;
background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='list-container'>
<div class='spacer'></div>
<div class='list'>
<div class='item'></div><div class='item'></div>
<div class='item'></div><div class='item'></div>
<div class='item'></div>
</div>
<div class='spacer'></div>
</div>
<button>Toggle fixed list width (hack)</button>

I believe the best way is to insert the "item" elements to a new div, setting:
<div style="margin:0 auto;width: 85px;">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
and also applying .item{float:left;}

It's not enough when you set justify-content: center; to .list?
Then if you need to make the standalone item to be aligned to left, you can set its margin-right: 42px; (to compensate the space next to it)

You can do the same without using flex
HTML
<div class='list'>
<div class='item'>item 1</div><div class='item'>item 2</div>
<div class='item'>item 3</div><div class='item'>item 4</div>
<div class='item'>item 5</div>
</div>
CSS
.list{
display:inline-block;
background-color: grey;
width:100px;
clear:both;
justify-content: center;
}
.list .item{
float:left;
width:48%;
background-color: skyblue;
height: 40px;
border: 1px solid black;
}
.list .item:last-child{
margin-left:25%;
}
Click here for JSFiddle sample

Related

CSS: What are the behavior rules for a "width: auto" container with inline-flex?

I was trying to create a list / table view with dynamic width using flexbox, and encountered a behavior I couldn't really wrap my head around. The result I'm trying to achieve is a width that fits the content of the list, at its' widest point.
.main {
width: auto;
background: rgb(233, 148, 148);
display: inline-flex;
flex-wrap: wrap;
}
.container {
display: flex;
width: 100%;
}
.label,
.value {
flex: 1;
padding: 4px;
}
.label {
text-align: end;
border-right: 2px solid red;
}
.value {
text-align: start;
}
<div>
<div class="main">
<div class="container">
<div class="label">Some Label</div>
<div class="value">Some value</div>
</div>
<div class="container">
<div class="label">Some label 2</div>
<div class="value">Other val</div>
</div>
<div class="container">
<div class="label">Third label</div>
<div class="value">
<div>N/A</div>
</div>
</div>
</div>
</div>
What it boils down to, is that the width seems to be determined by the total characters count, and not the widest point, as I would expect. You can edit the HTML and remove the N/A, for example, and the width will decrease.
When I switch to display: inline-block with white-space: nowrap, the width is as expected, but the "columns" are not aligned.
.main {
width: auto;
background: rgb(233, 148, 148);
display: inline-block;
white-space: nowrap;
}
.container {
display: flex;
width: 100%;
}
.label,
.value {
flex: 1;
padding: 4px;
}
.label {
text-align: end;
border-right: 2px solid red;
}
.value {
text-align: start;
}
<div>
<div class="main">
<div class="container">
<div class="label">Some Label</div>
<div class="value">Some value</div>
</div>
<div class="container">
<div class="label">Some label 2</div>
<div class="value">Other val</div>
</div>
<div class="container">
<div class="label">Third label</div>
<div class="value">
<div>N/A</div>
</div>
</div>
</div>
</div>
What causes the large width to occur when the display is inline-flex? Is there a way to get the behavior I'm trying to achieve? I know it can probably be resolved with display: grid, but I'm looking for a simpler solution.
I know it can probably be resolved with display: grid, but I'm looking for a simpler solution.
It might be difficult if you do not handle the grid-layout fine enough yet, but it looks not that much complicated if you use the grid system ;)
For the width, look at max-content.
simple example:
.main {
width: max-content;
background: rgb(233, 148, 148);
}
.container {
display: grid;
grid-template-columns: repeat(2, 1fr);
}
.label,
.value {
padding: 4px;
}
.label {
text-align: end;
border-right: 2px solid red;
}
.value {
text-align: start;
}
<div>
<div class="main">
<div class="container">
<div class="label">Some Label</div>
<div class="value">Some value</div>
</div>
<div class="container">
<div class="label">Some label 2</div>
<div class="value">Other val</div>
</div>
<div class="container">
<div class="label">Third label</div>
<div class="value">
<div>N/A</div>
</div>
</div>
</div>
</div>
In the past ,before flex & grid , display would use the table-layout.
.main {
display:table;
background: rgb(233, 148, 148);
}
.container {
display: table-row;
}
.label, .value {
padding: 4px;
display:table-cell;
}
.label {
text-align: end;
border-right: 2px solid red;
}
.value {
text-align: start;
}
<div>
<div class="main">
<div class="container">
<div class="label">Some Label</div>
<div class="value">Some value</div>
</div>
<div class="container">
<div class="label">Some label 2</div>
<div class="value">Other val</div>
</div>
<div class="container">
<div class="label">Third label</div>
<div class="value">
<div>N/A</div>
</div>
</div>
</div>
</div>

Creating a layout with Flexbox

hey I'm new in Flexbox and I'm trying to get it as best as I can. However i faces a problem with some heights and orders, maybe some here could help out.
Note: Don't suggest using Grid/tables please.
this is what I have right now:
this is what I want to get:
html:
<div class="movie-container">
<div class="upper-container">
<div class="image">Image</div>
<div class="title">Title</div>
<div class="more">More</div>
</div>
<div class="lower-container">
<div class="runtime">Runtime</div>
<div class="description">Description</div>
<div class="director">Director</div>
</div>
</div>
css:
.movie-container{
display:flex;
flex-flow: column wrap;
}
.upper-container {
display: flex;
width:80%;
margin:0 auto;
flex-flow: raw wrap;
}
.upper-container div {
border: 1px solid black;
padding: 10px;
}
.lower-container {
display: flex;
width:80%;
margin:0 auto;
flex-flow: column wrap;
}
.lower-container div {
border: 1px solid black;
padding: 10px;
}
.image {
flex: 1;
}
.title {
flex: 3;
}
.more {
flex: 0.1;
}
.runtime{
}
.description{
}
.director{
}
Maybe other stuff need to be added beside flexbox I'm not sure, that's why I ask here. Any solution will be helpful!
If you change your HTML structure slightly you can accomplish this fairly easily:
<div class="movie-container">
<div class="upper-container">
<div class="image">Image</div>
<div class="side-container">
<div class="title">Title</div>
<div class="more">More</div>
<div class="runtime">Runtime</div>
<div class="description">Description</div>
</div>
</div>
<div class="lower-container">
<div class="director">Director</div>
</div>
</div>
JSFiddle
Flex isn't very good at stretching across multiple rows / columns like tables or Grid is, while you state you don't want that solution it is typically a better option in cases like this.
I find it easiest to work with flexbox on a row-by-row basis instead of using wrapping (although you can certainly do that too).
As a starting point, I think this snippet is what you're going for?
div {
flex: 1 1 auto;
}
.box {
border: 1px solid black;
}
.flex {
display: flex;
}
.image {
width: 120px;
flex: 0 0 auto;
}
.more {
flex: 0 0 auto;
}
<div class="flex upper">
<div class="box flex image">Image</div>
<div class="upper-detail">
<div class="flex title-container">
<div class="box title">Title</div>
<div class="box more">More</div>
</div>
<div class="box runetime">Runtime</div>
<div class="box director">Director</div>
</div>
</div>
<div class="box description">Description</div>
<div class="box other">Other stuff...</div>
Hope this helps.
.upper-container{
display: flex;
height: 200px;
}
.upper-left{
background: #ddd;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
.upper-right{
flex: 3;
display: flex;
flex-direction: column;
height: 100%;
}
.title-more, .runtime, .director{
flex: 1;
border: 1px solid #222;
display: flex;
align-items: center;
}
.lower-container{
border: 1px solid #222;
padding: 10px;
}
.title-more{
justify-content: space-between;
}
.more-button{
height: 30px;
width: 100px;
border: 1px solid #333;
margin-right: 5px;
display: flex;
align-items: center;
justify-content: center;
}
<div class="movie-container">
<div class="upper-container">
<div class="upper-left">
Image
</div>
<div class="upper-right">
<div class="title-more">
<div class="title-container">
Title
</div>
<div class="more-button">
More
</div>
</div>
<div class="runtime">Runtime</div>
<div class="director">Director</div>
</div>
</div>
<div class="lower-container">
Description
</div>
</div>
The key is to add some divs and remove some others:
.movie-container *{padding:.5em;}
.upper-container {
display: flex;
padding:0;
}
.image {
border: 1px solid;
flex: 1 1 25%;
}
.tmrd{flex: 1 1 75%;padding:0}
.title-more {
display: flex;
padding:0;
}
.title{flex: 1 1 75%;border: 1px solid;}
.more{flex: 1 1 25%;border: 1px solid;}
.runtime,.description,.director{border: 1px solid;}
<div class="movie-container">
<div class="upper-container">
<div class="image">Image</div>
<div class="tmrd">
<div class="title-more">
<div class="title">Title</div>
<div class="more">More</div>
</div>
<div class="runtime">Runtime</div>
<div class="description">Description</div>
</div>
</div>
<div class="director">Director</div>
</div>

Align bottom not works in flex box

I am trying to align the footer at the bottom, leave the space at the top. but not works. any one help me to know the correct way?
.parent {
border: 1px solid red;
display: flex;
}
.child {
border: 1px solid green;
min-height: 100px;
flex: 1;
align-items:bottom;
}
.footer{
background:#808080;
}
<div class="parent">
<div class="child">
<div class="footer">Footer</div>
</div>
<div class="child">
<div class="footer">Footer</div>
</div>
<div class="child">
<div class="footer">Footer-will be in bottom!!</div>
</div>
</div>
First of all, to align items to the bottom the correct way is align-items: flex-end;
I also declared display:flex; on .child, and gave it a width.
.parent {
border: 1px solid red;
display: flex;
}
.child {
border: 1px solid green;
min-height: 100px;
display: flex;
width: 33.333%;
align-items: flex-end;
}
.footer{
background:#808080;
width: 100%;
}
<div class="parent">
<div class="child">
<div class="footer">Footer</div>
</div>
<div class="child">
<div class="footer">Footer</div>
</div>
<div class="child">
<div class="footer">Footer-will be in bottom!!</div>
</div>
</div>
In this example your .child also needs to have display: flex and .footer needs align-items: bottom.
Why? This is actually multiple nested flex layouts.
As per the code you have provided. This can be a possible solution.
.parent {
border: 1px solid red;
display: flex;
}
.child {
border: 1px solid green;
min-height: 100px;
flex: 1;
display: inline-flex;
align-items: flex-end;
flex-direction: row;
}
.footer {
display: inline-block;
width: 100%;
background:#808080;
}
<div class="parent">
<div class="child">
<div class="footer">Footer</div>
</div>
<div class="child">
<div class="footer">Footer</div>
</div>
<div class="child">
<div class="footer">Footer-will be in bottom!!</div>
</div>
</div>
But in a more optimized way. Let me show you another sample:
.parent {
border: 1px solid red;
display: flex;
}
.child {
flex: 1;
border: 1px solid green;
min-height: 100px;
display: flex;
flex-direction: column;
}
.content {
flex: 1;
}
.footer{
background:#808080;
}
<div class="parent">
<div class="child">
<div class="content">Content</div>
<div class="footer">Footer</div>
</div>
<div class="child">
<div class="content">Content</div>
<div class="footer">Footer</div>
</div>
<div class="child">
<div class="content">Content</div>
<div class="footer">Footer-will be in bottom!!</div>
</div>
</div>
If you don't want to change the HTML tags and use the same as in the question, you can go with the first solution. Otherwise, the second one will serve better.
Remove line-height from the .child and add height for the .parent.
Updated :
.parent {
border: 1px solid red;
display: flex;
align-items: flex-end;
height: 100px;
}
.child {
border: 1px solid green;
flex: 1;
align-items:bottom;
}
.footer{
background:#808080;
}
<div class="parent">
<div class="child">
<div class="footer">Footer</div>
</div>
<div class="child">
<div class="footer">Footer</div>
</div>
<div class="child">
<div class="footer">Footer-will be in bottom!!</div>
</div>
</div>

Split last tab width 50% and all other Tabs should fit in other 50% width

Need to split all tabs in such a way that. Last tab width will be 50% width and rest all tabs must fit in 50%. For now I gave fixed width: 16.65%. Would like to avoid it as there could 2 or 3 tabs excluding last tab.
Can this be achieved using display: flex ?
* {
margin: 0;
}
.wrapper {
overflow: hidden
}
.wrapper .tab {
float: left;
width: 16.65%;
text-align: center;
background: #ccc;
}
.wrapper .last-tab {
width: 50%;
background: #999
}
<div class="wrapper">
<div class="tab">Tab 1</div>
<div class="tab">Tab 2</div>
<div class="tab">Tab 3</div>
<div class="tab last-tab">Last Tab</div>
</div>
You can do it like this:
* {
margin: 0;
}
.wrapper {
display: flex; /* displays children inline */
overflow: hidden;
}
.wrapper > .tab {
flex: 1; /* enables growing of flex-items so they can fill flex-containers width / this is the shorthand way, but you can also use: flex: 1 1 auto; (i.e. flex-grow, flex-shrink, flex-basis) */
/*float: left;*/
/*width: 16.65%;*/
text-align: center;
background: #ccc;
}
.wrapper > .last-tab {
/*width: 50%;*/
flex: 0 1 50%; /* adjusted to take half of the wrappers width (i.e. initial width is set to 50%) */
background: #999;
}
<div class="wrapper">
<div class="tab">Tab 1</div>
<div class="tab">Tab 2</div>
<div class="tab">Tab 3</div>
<div class="tab last-tab">Last Tab</div>
</div>
If you want to do it pure flexbox way without the use of the width property.
try this
* {
margin: 0;
}
.wrapper {
overflow: hidden;
display: flex;
width: 100%;
}
.wrapper .tab {
width: calc(50%/3);
text-align: center;
background: #ccc;
}
.wrapper .last-tab {
width: 50%;
background: #999
}
<div class="wrapper">
<div class="tab">Tab 1</div>
<div class="tab">Tab 2</div>
<div class="tab">Tab 3</div>
<div class="tab last-tab">Last Tab</div>
</div>
Take 2 blocks of 50-50%. Then you can easily divide inner divs as per your requirement.
Hope this helps you :)
* {
margin: 0;
}
.wrapper {
/*overflow: hidden*/
display:flex;
}
.wrapper .tab-container {
/*float: left;*/
display:flex;
width: 50%;
background: #ccc;
}
.wrapper .tab {
/*float: left;*/
display:flex;
width: 33.33%;
text-align: center;
}
.wrapper .last-tab {
width: 50%;
background: #999;
text-align: center;
}
<div class="wrapper">
<div class="tab-container">
<div class="tab">Tab 1</div>
<div class="tab">Tab 2</div>
<div class="tab">Tab 3</div>
</div>
<div class="last-tab">Last Tab</div>
</div>

How to float center but still keep the propities of left float

So I want to float some div's center, orignally I was using float: left which gave me this look http://i.imgur.com/wfHacch.png after reading other answers I see that I can not do that, one of the suggestions made was to use margin: 0 auto; when I used this it made everything simply stack in a line down the center, as per this image http://i.imgur.com/xyixrdj.png
I am trying to force the floating div's to be stacked uniformly centered. Which would also adjust to the stack down the line in lower screensizes,
How best am I to do this?
So here is my CSS at the moment
.container {
overflow: hidden;
width: 100%;
height: 100%;
}
.item {
float: left;
max-width: 500px;
width: 100%;
padding: 10px;
height: 100%;
}
button {
width: 33%;
height: 100%;
padding: 20px;
background: orange;
border: 1;
border-radius: 10px;
border: 1px;
border-radius: 02px;
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
transition: all 0.3s cubic-bezier(.25,.8,.25,1);
}
And my HTML
<div class="container orders">
<div class="item">
<button class="ready">
/*content*/
</button>
</div>
</div
You should use inline-block
div {
display: inline-block
}
By default divs are block elements.
You can use flexbox: https://jsfiddle.net/BradChelly/m9d3jepz/
.container {
width: 80%;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
}
.item {
width: 30%;
height: 100px;
margin-bottom: 20px;
border:1px solid red;
}
#media only screen and (max-width: 500px) {
.item {
width: 45%;
}
}
#media only screen and (max-width: 300px) {
.item {
width: 100%;
}
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
I don't know what your code is but If I were you I would try wrap those div's in another div with display: inline-block and clearfix. And then give parent text-align: center. End code should look something like that:
.parent{
text-align: center;
}
.parent .container{
display: inline-block;
width: 340px;
zoom: 1;
}
.parent .container:after{
content: "";
display: table;
clear: both;
}
.parent .container:before{
content: "";
display: table;
}
.parent .container .element{
display: block;
float: left;
width: 100px;
bordeR: 1px solid #000000;
height: 50px;
margin: 5px
}
<div class="parent">
<div class="container">
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
</div>
</div>
if you want center a div so you have to remove float left you can add text-align center i parent div and add display inline-block in child div like this
.parent{
width:100%;
float:left;
text-align:center;
}
.child{
width:100px;
background:#f00;
display:inline-block;
}
<div class="parent">
<div class="child">Some text here</div>
<div class="child">Some text here</div>
<div class="child">Some text here</div>
<div class="child">Some text here</div>
</div>