Flexbox keep wrapping point while increasing item width - html

First of all, here is a codepen with the issue I am trying to solve.
This is a simplified version of the problem I have on an actual project. My goal is to keep the grid in the same format with 5 columns and to be able to increase the width of these cells so the content is always visible, but also so that it doesn't wrap before the first row of 5 columns is displayed. Whenever I try to increase the width of the cells the grid wraps and I lose the structure I want.
So, basically, increase width of items, but prevent wrapping, is it possible? It is fine if the content overflows the flex container itself, the goal is to add overflow-x to this grid.
.flex-container {
border: 1px solid silver;
display: flex;
width: 50%;
}
.wrap {
flex-wrap: wrap;
}
.wrap div {
background: gold;
}
.flex-item {
width: 160px;
border-bottom: 1px solid black;
border-right: 1px solid black;
line-height: 100px;
color: black;
font-weight: bold;
font-size: 2em;
text-align: center;
}
<div class="flex-container wrap">
<div class="flex-item">11111111111111</div>
<div class="flex-item">22222222222222</div>
<div class="flex-item">33333333333333</div>
<div class="flex-item">44444444444444</div>
<div class="flex-item">55555555555555</div>
<div class="flex-item">66666666666666</div>
<div class="flex-item">77777777777777</div>
<div class="flex-item">88888888888888</div>
<div class="flex-item">99999999999999</div>
<div class="flex-item">00000000000000</div>
</div>

From the comments, it does look like grid is the option you need, it won't allow content to be wrapping and justify content will stick it on the side if shorter thant the width of the container.
here is the snippet with grid:
/* flex turned into grid */
.flex-container {
border: 1px solid silver;
display: grid;
grid-template-columns:repeat(5,auto);
justify-content:start;
overflow:auto;
width: 80%;
}
.wrap {
}
.wrap div {
background: gold;
}
.flex-item {
border-bottom: 1px solid black;
border-right: 1px solid black;
line-height: 100px;
color: black;
font-weight: bold;
font-size: 2em;
text-align: center;
}
<div class="flex-container wrap">
<div class="flex-item">11111111111111</div>
<div class="flex-item">22222222222222</div>
<div class="flex-item">33333333333333</div>
<div class="flex-item">44444444444444</div>
<div class="flex-item">55555555555555</div>
<div class="flex-item">66666666666666</div>
<div class="flex-item">77777777777777</div>
<div class="flex-item">88888888888888</div>
<div class="flex-item">99999999999999</div>
<div class="flex-item">00000000000000</div>
</div>

I think, if it is allowable, that css grid may be a better candidate for the layout you are proposing...
.grid-container {
border: 1px solid silver;
display: grid;
width: 50%;
grid-template-columns: 20% 20% 20% 20% 20%; /* hard set five columns and no more */
}
.grid-container div {
background: gold;
}
.grid-item {
/* width: 160px; */
border-bottom: 1px solid black;
border-right: 1px solid black;
line-height: 100px;
color: black;
font-weight: bold;
font-size: 2em;
text-align: center;
overflow-x: hidden; /* overflow-x to hide overflow as discussed in question */
}
<div class="grid-container">
<div class="grid-item">11111111111111</div>
<div class="grid-item">22222222222222</div>
<div class="grid-item">33333333333333</div>
<div class="grid-item">44444444444444</div>
<div class="grid-item">55555555555555</div>
<div class="grid-item">66666666666666</div>
<div class="grid-item">77777777777777</div>
<div class="grid-item">88888888888888</div>
<div class="grid-item">99999999999999</div>
<div class="grid-item">00000000000000</div>
</div>

.flex-container {
display: flex;
flex-wrap: wrap;
background-color:red;
}
.flex-container > div {
background-color: #f1f1f1;
width: 100px;
margin: 10px;
text-align: center;
line-height: 75px;
font-size: 30px;
word-wrap: break-word;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div class="flex-container">
<div>11111111111111</div>
<div>22222222222222</div>
<div>33333333333333</div>
<div>44444444444444</div>
<div>55555555555555</div>
<div>66666666666666</div>
<div>77777777777777</div>
<div>88888888888888</div>
<div>99999999999999</div>
<div>00000000000000</div>
</div>
</body>

Related

Make a responsive layout using flex and css grid

I'm trying to do a responsive layout, I'm not good with css so I need help.
Here is the code:
.container {
outline: 1px solid black;
max-width: 490px;
margin: 0 auto;
}
.columns {
outline: 1px solid black;
display: inline-flex;
flex-wrap: wrap;
}
.map {
background-color: cyan;
width: 150px;
min-width: 150px;
height: 150px;
min-height: 150px;
margin-right: 20px;
}
.content {
outline: 1px solid black;
background-color: lightgray;
max-width: 320px;
}
.cards {
outline: 1px solid black;
display: inline-flex;
flex-wrap: wrap;
}
.card {
background-color: pink;
outline: 1px solid black;
width: 150px;
height: 70px;
display: inline-block;
}
.card.left {
margin-right: 20px;
}
.texts {
outline: 1px solid black;
display: inline-flex;
flex-wrap: wrap;
}
.text {
background-color: gold;
outline: 1px solid black;
width: 150px;
height: 200px;
display: inline-block;
}
.text.left {
margin-right: 20px;
}
<div class="container">
<div class="columns">
<div class="map"></div>
<div class="content">
<div class="cards">
<div class="card left">card #1</div>
<div class="card">card #2</div>
<div class="card left">card #3</div>
<div class="card">card #4</div>
</div>
<div class="texts">
<div class="text left">text #1</div>
<div class="text">text #2</div>
</div>
</div>
</div>
</div>
Basically there are two rows.
The first one contains an element with fixed width and height, and on the right four cards.
The second rows contains only two elements.
Each element of this layout has width 150px.
The code shown above works partially.
The first row is ok, the second one no because the gold elements should stay aligned with the cards so when cards are on the right of el1, contents should below the cards.
It is like if there were to be a hidden element (on the left side of contents) that has the same size as el1.
Also I would like everything to always be centered because now it is only if the window width is > 490px.
This is what I'd like to have:
How can I do that?

Flexbox - Two column in a row

I'm trying to use flexbox in order to create two columns of three row for the Products. I looked to other similar problem on StackOverflow but the answers given didn't work for me. Could you help me please ?
Here the HTML code:
Informations {
list-style-type: none;
margin: 0;
padding: 0;
border: 1px solid blue;
width: 100%;
display: flex;
justify-content: space-between;
}
.Information {
border: 1px solid blue;
margin: 0.5em;
padding: 0.5em;
}
Game {
list-style-type: none;
border: 1px solid red;
width: 100%;
display: flex;
}
.ProductContainer {
display: flex;
flex-flow: column wrap;
border: 1px solid black;
width: 90%;
}
.Product {
border: 1px solid red;
margin: 0.5em;
padding: 0.5em;
}
.UpgradeContainer {
border: 1px solid black;
width: 10%;
}
.Upgrade {
display: flex;
flex-flow: column wrap;
border: 1px solid red;
margin: 0.5em;
padding: 0.5em;
}
<!DOCTYPE world>
<html>
<head>
<title> World </title>
</head>
<body>
<Informations>
<div class="Information">Your World:</div>
<div class="Information">Your Money:</div>
<div class="Information">Your ID:</div>
</Informations>
<Game>
<div class="UpgradeContainer">
<div class="Upgrade">Unlocks</div>
<div class="Upgrade">Cash</div>
<div class="Upgrade">Angels</div>
<div class="Upgrade">Managers</div>
<div class="Upgrade">Investors</div>
</div>
<div class="ProductContainer">
<div class="Product">Product1</div>
<div class="Product">Product2</div>
<div class="Product">Product3</div>
<div class="Product">Product4</div>
<div class="Product">Product5</div>
<div class="Product">Product6</div>
</div>
</Game>
</body>
</html>
I basically want to have to the left my upgrades (Cash, angels...) and in the middle and right two column of three row of products.
Here is my code pen to see: https://codepen.io/Tameiki/pen/oNXpNVe
You can use the flex-wrap property together with setting the flex-basis on the child elements:
.ProductContainer{
display: flex;
flex-flow: wrap;
border: 1px solid black;
width: 90%;
}
.Product {
border: 1px solid red;
margin: 0.5em;
padding: 0.5em;
flex-basis: calc(50% - 2em - 5px); /* - Margins - Borders - 1px to mitigate subpixel rounding issues*/
}
<div class="ProductContainer">
<div class="Product">Product1</div>
<div class="Product">Product2</div>
<div class="Product">Product3</div>
<div class="Product">Product4</div>
<div class="Product">Product5</div>
<div class="Product">Product6</div>
</div>
Notice how I removed the flex-direction:column property: the child elements will attempt to fit in a single row, overflowing the container if necessary.
.ProductContainer{
display: flex;
/*flex-flow: wrap;*/
border: 1px solid black;
width: 90%;
}
.Product {
border: 1px solid red;
margin: 0.5em;
padding: 0.5em;
/*flex-basis: calc(50% - 2em - 5px); /* - Margins - Borders - 1px to mitigate subpixel rounding issues*/
}
<div class="ProductContainer">
<div class="Product">Product1</div>
<div class="Product">Product2</div>
<div class="Product">Product3</div>
<div class="Product">Product4</div>
<div class="Product">Product5</div>
<div class="Product">Product6</div>
</div>
flex-wrap is what makes them start a new line instead of overflowing:
.ProductContainer{
display: flex;
flex-flow: wrap;
border: 1px solid black;
width: 90%;
}
.Product {
border: 1px solid red;
margin: 0.5em;
padding: 0.5em;
/*flex-basis: calc(50% - 2em - 5px); /* - Margins - Borders - 1px to mitigate subpixel rounding issues*/
}
<div class="ProductContainer">
<div class="Product">Product1</div>
<div class="Product">Product2</div>
<div class="Product">Product3</div>
<div class="Product">Product4</div>
<div class="Product">Product5</div>
<div class="Product">Product6</div>
</div>
But how do we get only two of them per row? By telling each of the child elements to be half the row's width:
.ProductContainer{
display: flex;
flex-flow: wrap;
border: 1px solid black;
width: 90%;
}
.Product {
border: 1px solid red;
margin: 0.5em;
padding: 0.5em;
flex-basis: 50%; /*calc(50% - 2em - 5px); /* - Margins - Borders - 1px to mitigate subpixel rounding issues*/
}
<div class="ProductContainer">
<div class="Product">Product1</div>
<div class="Product">Product2</div>
<div class="Product">Product3</div>
<div class="Product">Product4</div>
<div class="Product">Product5</div>
<div class="Product">Product6</div>
</div>
Unfortunately, flex-basis applies to the inner width of an element - including paddings, but excluding margins and borders. Usually, Flexbox tries to shrink child elements to fit the row if possible, but flex-wrap disables this, so we will have to adjust manually. That gets you to the code at the top.

Center-align one element while right-aligning its only sibling using flexbox

I am trying to achieve this using flexbox:
I know how to do it by using a hidden element as in this fiddle:
.container {
display: flex;
justify-content: space-between;
border: 3px solid blue;
}
.box {
width: 100px;
height: 100px;
background: red;
}
.box:first-child {
visibility: hidden;
}
<div class="container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
But this seems like too hacky to be right.
Use the flex property that sets the flexible length on flexible items. That way, I'm telling the white-box to take all available space but the first white-box will be 50% larger than the normal white -box, that will take the place of what's left
.container {
display: flex;
border: 3px solid blue;
}
.box {
width: 100px;
height: 100px;
background: red;
}
.white-box {
background: white;
flex: 1;
}
.white-box:first-child {
flex: 1.5
}
<div class="container">
<div class="white-box"></div>
<div class="box"></div>
<div class="white-box"></div>
<div class="box"></div>
</div>
you can easily achieve this kind of layout by using CSS grid
.grid-container {
display: grid;
grid-template-columns: auto 100px 200px 100px;
border: 1px solid blue;
}
.grid-container > div {
text-align: center;
font-size: 30px;
padding: 20px 0px;
}
.red{
background-color: red;
}
<div class="grid-container">
<div>1</div>
<div class="red">2</div>
<div>3</div>
<div class="red">4</div>
</div>
Hope this will be helpful for you
you need to remove
.box:first-child {
visibility: hidden;
}

Background of div does not scroll with the contents

I have the following snippet of html that forms an X-Y scrollable listbox
* {
font-family: "consolas";
}
.listbox {
border: 1px solid black;
padding: 4px;
width: 150px;
height: 200px;
display: flex;
flex-direction: column;
}
.caption {
font-weight: bold;
background-color: #aaf;
padding: 10px;
}
.content {
flex-grow: 1;
overflow: scroll;
}
.item {
background-color: #ddd;
padding: 2px;
padding-left: 6px;
margin-top: 4px;
white-space: nowrap;
}
<div class="listbox">
<div class="caption">Caption</div>
<div class="content">
<div class="item">One</div>
<div class="item">Two</div>
<div class="item">Three (this has a longer bit)</div>
<div class="item">Four</div>
<div class="item">Five</div>
<div class="item">Six</div>
<div class="item">Seven</div>
<div class="item">Eight (so does this)</div>
<div class="item">Nine</div>
<div class="item">Ten</div>
</div>
</div>
It's working fine, with one problem, as the user scrolls from left to right, the background of the div seems to get left behind. It's as though the actual div only stretches the width of its parent, and the scrolling/overflow thing is "faked" somehow.
Why is this the case?
How do I address the problem? The behaviour I want is for all the items to appear to be the same width as the largest one.
Try adding a container <div class="items"> around the items set it to display:inline-block.
.items {
display: inline-block;
}
* {
font-family: "consolas";
}
.listbox {
border: 1px solid black;
padding: 4px;
width: 150px;
height: 200px;
display: flex;
flex-direction: column;
}
.caption {
font-weight: bold;
background-color: #aaf;
padding: 10px;
}
.content {
flex-grow: 1;
overflow: scroll;
}
.items {
display: inline-block;
}
.item {
background-color: #ddd;
padding: 2px;
padding-left: 6px;
margin-top: 4px;
white-space: nowrap;
}
<div class="listbox">
<div class="caption">Caption</div>
<div class="content">
<div class="items">
<div class="item">One</div>
<div class="item">Two</div>
<div class="item">Three (this has a longer bit)</div>
<div class="item">Four</div>
<div class="item">Five</div>
<div class="item">Six</div>
<div class="item">Seven</div>
<div class="item">Eight (so does this)</div>
<div class="item">Nine</div>
<div class="item">Ten</div>
</div>
</div>
</div>
Explanation: by default a block level element takes 100% width of the container no more than that, however an inline block will expand to content length if available e.g. in a scrollable container.
Also apply .items {min-width: 100%;} in case you want the background to grow full width even with less text in every row.

Chrome flexbox 100% height inside other 100% height flexbox overflows

I am trying to make a full height page using flexboxes, where the content also uses a flexbox. The page should look as follows example of what it should look like. The blue div is dynamic and could change in height and the red content should take up the remaining space of the content div. This works on both Firefox and IE, however on Chrome it overflows. Can somebody explain why it overflows on Chrome?
The HTML is as follows:
<body>
<div class="container">
<div class="navbar">Navbar</div>
<div class="content">
<div class="container">
<div class="fill"></div>
<div class="dynamic">Here is some dynamic content<br>Test</div>
</div>
</div>
</div>
</body>
And the CSS is:
body{
margin:0;
}
.container{
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
.navbar{
background-color: #ccc;
flex: none;
}
.content{
background-color: #333;
flex: auto;
padding: 10px;
}
.dynamic{
background-color: #0066ff;
flex: none;
}
.fill{
flex: auto;
background-color: #ff0000;
}
Here is an updated snippet.
Use flex:1 for the container that needs to adjust the height automatically.
body {
margin: 0;
}
.container1 {
display: flex;
flex-direction: column;
width: 100%;
height: 100vh;
}
.navbar {
background-color: #ccc;
}
.content {
flex: 1;
background-color: #ff0000;
border: 10px solid #333;
border-bottom: none;
}
.dynamic {
background-color: #0066ff;
border: 10px solid #333;
border-top: none;
}
<body>
<div class="container1">
<div class="navbar">Navbar</div>
<div class="content">
</div>
<div class="dynamic">Here is some dynamic content
<br>Test</div>
</div>
</body>