Flexbox adapt element width to not let white space - html

I want to achieve a multi-line flexbox container where element width can reduce if it's min-width is not reach to not let big whitespace when break line happen.
Here is an example on which i'm working on : https://codepen.io/BaptisteG/pen/dyyQodR
.container {
border: 5px solid rgb(111,41,97);
border-radius: .5em;
padding: 10px;
display: flex;
flex-wrap: wrap;
row-gap: 1em;
column-gap: 20px;
width: 500px;
}
.item {
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
flex: 1 1 content;
min-width: 100px;
max-width: min-content;
white-space:nowrap;
overflow:hidden;
}
A sketch of what i want to achieve :
sketch
I don't want element size to be increase to complete whitespace

Related

Align horizontal border line with header div

I have a header div that looks like this in css:
.page-header {
display: flex;
flex-direction: row;
justify-content: space-between;
align-content: stretch;
align-items: center;
padding: 5px 5px 5px 20px
margin-left: auto;
margin-right: auto;
width: 100%
height: 40px;
}
and a border div under it:
.horizontal-line {
border-bottom: 1px solid red;
margin: auto;
}
My problem is that I can't use padding on the border to make it align with the header or change the margin to fixed numbers, because then it doesn't center.
How would i go about fixing this so that the border adjust to the same width as the header?
Can it be done in CSS only? The reason I ask is that the JS is a template (not ideal I know) and there are other versions on the site using the same template (none of them are using the border div).
I've tried using max-width and that works really good on the large version of the site. Problem with that is that when the page is shrunk it doesn't dynamically adjust the max-width :(
Appreciate any help that I could get :)
Maybe if you can add a container you can do something like this:
You can also add horizontal-line div inside the container and make it full 100% width and get the same result.
.container {
width: 60%;
height: 300px;
background-color: white;
border-bottom: 2px solid black;
}
.page-header {
display: flex;
flex-direction: row;
justify-content: space-between;
align-content: stretch;
align-items: center;
padding: 5px 5px 5px 20px
margin-left: auto;
margin-right: auto;
width: 100%;
height: 200px;
background-color: yellow;
}
<div class="container">
<div class="page-header"></div>
</div>
or put % on max-width and then when you resize screen it will resize this is not pretty i would rather choose to use container around it.
.page-header {
display: flex;
flex-direction: row;
justify-content: space-between;
align-content: stretch;
align-items: center;
padding: 5px 5px 5px 20px
margin-left: auto;
margin-right: auto;
/* width: 100%; */
max-width: 50%;
height: 200px;
background-color: yellow;
}
.horizontal-line {
max-width: 50%;
margin-top: 50px;
border-bottom: 2px black solid;
}
<div class="page-header"></div>
<div class="horizontal-line"></div>

CSS grid with dynamic number of rows and adjustable width

I am trying to create a dynamic grid layout with two columns that is #red-container and #green-container. Each container or column should be resizable horizontally and the main container #container should be resizable vertically. Resizing the container should adjust the height of the child elements. The #red-container and #green-container have cells which are added dynamically to the container with the JavaScript function in a row-wise fashion. I have the following working implementation:
function addCell(color) {
let container = document.getElementById(color + "-container");
let cell = document.createElement("div");
cell.innerText = color;
container.appendChild(cell).className = "container-item";
}
#container {
border: 1px solid #ddd;
display: flex;
flex-grow: 1;
flex-direction: row;
height: 50vh;
resize: vertical;
overflow: auto;
}
#red-container {
flex-grow: 1;
display: grid;
grid-auto-flow: row;
margin: 10px;
resize: horizontal;
overflow: auto;
border: 1px solid red;
}
#green-container {
flex-grow: 1;
display: grid;
grid-auto-flow: row;
margin: 10px;
resize: horizontal;
overflow: auto;
border: 1px solid green;
}
.container-item {
padding: 10px;
border: 1px solid black;
}
<button onclick="addCell('red')">add red cell</button>
<button onclick="addCell('green')">add green cell</button>
<div id="container">
<div id="red-container"></div>
<div id="green-container"></div>
</div>
However, there are two problems with it:
The first time the user clicks add red cell it increases the width of #red-container.
adjusting the width of the red and green container is inconsistent and I am unable to adjust the width of the red container to less than 50% of the width.
Any ideas on how to fix these two problems? Additionally, any advice on writing the css in a more concise manner is welcome (#red-container and #green-container contain duplicate code).
Make only the red container resizable with an initial width equal to 50% and use flex-grow:1 on the green container
function addCell(color) {
let container = document.getElementById(color + "-container");
let cell = document.createElement("div");
cell.innerText = color;
container.appendChild(cell).className = "container-item";
}
#container {
border: 1px solid #ddd;
display: flex;
gap: 10px;
padding: 10px;
height: 50vh;
resize: vertical;
overflow: auto;
}
#green-container,
#red-container {
display: grid;
overflow: auto;
}
#red-container {
border: 1px solid red;
width: 50%;
resize: horizontal;
}
#green-container {
border: 1px solid green;
flex-grow: 1;
}
.container-item {
padding: 10px;
border: 1px solid black;
}
<button onclick="addCell('red')">add red cell</button>
<button onclick="addCell('green')">add green cell</button>
<div id="container">
<div id="red-container"></div>
<div id="green-container"></div>
</div>
do these two things to solve the problem:
make the #container with grid-template-columns: 1fr 1fr; so whatever it happens, the child will be always half-width.
because if you want to use flex, it only grows to 1, but does not always mean half precisely, so go for grid layout
for not making repetitive code just make the two selectors in one by using , (comma)
#red-container, #green-container
not important but can help:
adding box-sizing: border-box for solving extra problems if you add padding or something similar
also don't write grid-auto-flow: row because grid is by default row
also use gap instead of margin, gap makes the same value of px between element on a grid/flex layout.
if you are using margin, then if you write for example 10px as a value you will get 20px
here the correct code:
function addCell(color) {
let container = document.getElementById(color + "-container");
let cell = document.createElement("div");
cell.innerText = color;
container.appendChild(cell).className = "container-item";
}
* {
box-sizing: border-box;
}
#container {
border: 1px solid #ddd;
display: grid;
grid-template-columns: 1fr 1fr;
height: 50vh;
resize: vertical;
overflow: auto;
gap: 10px;
/* if you want like before, here in gap: write 20px */
padding: 10px;
}
#red-container,
#green-container {
display: grid;
resize: horizontal;
overflow: auto;
}
#red-container {
border: 1px solid red;
}
#green-container {
border: 1px solid green;
}
.container-item {
padding: 10px;
border: 1px solid black;
}
<button onclick="addCell('red')">add red cell</button>
<button onclick="addCell('green')">add green cell</button>
<div id="container">
<div id="red-container"></div>
<div id="green-container"></div>
</div>
if you didn't understand something, write me a comment here, I will answer to you
however here some documentations that can help you:
grid-template-columns: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns
box-sizing: https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing
gap: https://developer.mozilla.org/en-US/docs/Web/CSS/gap

How to set sibling element's width to flex item which contains long word

I'm trying to do this :
The flex-item img must define the flex-container width and the other flex-item (the div with "a" and "aaaaaaa...") must into the flex-container but must not make the flex-container grow.
Also, i don't want to fix a width of text flex-item in px because the image width is dynamic. How can i do that without using javascript ?
I made this code snippet according to my image to help :
.flex-container {
display: flex;
flex-direction: column;
border: 3px blue solid;
}
.random-image {
width: 50px;
height: 50px;
border: 3px red solid;
}
.first-text, .second-text {
border: 3px orange solid;
}
.second-text {
word-break: break-all;
}
<div class="flex-container">
<div class="random-image"></div>
<div class="first-text">a</div>
<div class="second-text">aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
</div>
Remove the fixed width on the image div and use width: min-content; on the flex-container as well as the random-image div. This should work nicely for you.
.flex-container {
display: flex;
flex-direction: column;
border: 3px blue solid;
width: min-content;
height: fit-content;
padding: 10px;
}
.random-image {
border: 3px red solid;
width: fit-content;
}
.first-text, .second-text {
border: 3px orange solid;
}
.second-text {
word-break: break-all;
}
.first-text {
width: fit-content;
margin: 1em auto 1em auto;
}
<div class="flex-container">
<div class="random-image"><img src="https://dummyimage.com/600x400/000/fff"></div>
<div class="first-text">a</div>
<div class="second-text">aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
</div>

Create divs with row size as 3 and column to be of size N

I want to display divs so that it can be horizontally scrolled. I have created a display flex container but I am not sure what else do I need to do so that the boxes are aligned to the left.
Here is the demo code
.container {
height: 95px;
border: 1px solid black;
display: flex;
flex-direction: column;
overflow-x: auto;
}
.box {
border: 1px solid black;
margin: 5px;
width: 100px;
}
The uncommented code works fine. The momement I comment the cols, I get extra spacing
The CSS align-content and justify-content properties allow you to choose where items in the flexbox appear. I suggest you look them up (for example on CSS tricks) to understand how they work. In this case setting align-content: flex-start; to the .container object will do the trick.
Is this what you wanted?: HERE
.container {
height: 95px;
border: 1px solid black;
display: flex;
/* flex-direction: column; */
overflow-x: auto;
}
.box {
border: 1px solid black;
margin: 5px;
flex: 0 0 33%;
}

flexbox: stretching the height of elements with flex-direction: row

I want to stretch two div elements (.sideline and .main-contents) to reach the bottom of the page and stay at a certain height from the footer.
The two divs are nested inside a div (.row-elements) with the flex-direction: row since I wanted them to be on the same row.
/* body {
display:flex;
flex-direction:column;
} */
.one-above-all {
display: flex;
flex-direction: column;
/* flex: 1 0 auto; */
/* min-height: 1100px; */
border: solid black 1px;
}
.top-block {
margin: 0 auto;
border: solid black 1px;
width: 300px;
height: 30px;
margin-top: -15px;
}
.headline {
border: solid black 1px;
width: 90%;
align-self: flex-end;
margin-top: 40px;
margin-right: 10px;
height: 160px;
display: flex;
box-sizing: border-box;
}
.row-elements {
display: flex;
flex-direction: row;
margin-top: 40px;
align-items: stretch;
/* min-height: 900px;
flex: 1 0 auto;
*/
}
.sideline {
width: 160px;
border: solid 1px;
margin-left: calc(10% - 10px);
box-sizing: border-box;
flex-shrink: 1
}
.main-contents {
border: solid 1px;
margin-left: 40px;
/* align-self: stretch; */
flex: 1 1 auto;
margin-right: 10px;
box-sizing: border-box;
}
.bottom-block {
align-self: flex-end;
margin-top: auto;
border: black solid 1px;
margin: auto;
width: 300px;
height: 30px;
margin-bottom: -10px;
/* margin-top: 880px; */
}
/* .stretch-test {
border:solid, 1px;
display: flex;
flex-direction: column;
flex: 1 0 auto;
} */
<div class="one-above-all">
<div class="top-block"></div>
<div class="headline"></div>
<!-- <div class="stretch-test"> -->
<div class="row-elements">
<div class="sideline"></div>
<div class="main-contents">jhjkdhfjksdhafjksdahfl</div>
<!--</div> -->
</div>
</div>
<div class="bottom-block">footer</div>
Codepen
The commented out code in the css is the things I have tried.
I tried to set the body as flex and give the row-elements class flex property of 1 0 auto which didn't work.
I tried nesting the row-elements class (which has the flex-direction of row) in another div with a flex-direction of column and setting .row-elements to flex:1 0 auto which also didn't work.
I tried totally removing the the row-elements class but the two divs won't come on the same row.
Any solution will be appreciated.
To stick the footer to the bottom, here are two methods:
Method #1: justify-content: space-between
Align the container vertically with flex-direction: column. Then pin the last element to the bottom with justify-content: space-between.
revised codepen
Method #2: auto margins
Also with the container in column-direction, apply margin-top: auto to the footer, which spaces it away from the other flex items. (Seems you're already familiar with this method.)
Here's a detailed explanation for both: Methods for Aligning Flex Items
Make sure to define a height for your container, unless you simply want content height. In my example I've used height: 100vh on body.