From my research in this problem, I've learned CSS grids appear to capable of quite complex behaviour. My scenario is simpler and I was expecting to have 4 evenly spaced panel boxes with code below. My question is why the horizontal gap is not centred in the middle vertically? I worked through trail&error to test various combinations of alignment, justification and grid specs but could not find a solution. What do I need to add to my code to have the gap centred vertically on the page?
.main-container {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-gap: 20px;
height: 100vh;
align-items: stretch;
margin: 0;
padding: 0;
justify-content: space-between;
}
.container {
border: 3px solid black;
display: flex;
position: relative;
flex-direction: column;
margin: 0;
padding: 0;
}
.shared {
justify-content: center;
border: none;
}
.sub-container {
border: 3px solid black;
align-items: stretch;
height: 100%;
margin: 0;
padding: 0;
}
<div class="main-container">
<div class="container" id="A">
<h1>Section A</h1>
<p id="A-values">A Values</p>
</div>
<div class="container" id="B">
<h1>Section B</h1>
<p id="B-values">B Values</p>
</div>
<div class="container" id="C">
<h1>Section C</h1>
<p id="C-values">C Values</p>
</div>
<div class="container shared" id="D">
<div class="sub-container">
<h2>SubSection D1</h2>
<p id="D1-values">D1 Values</p>
</div>
<div class="sub-container">
<h2>SubSection D2</h2>
<p id="D2-values">D2 Values</p>
</div>
<div class="sub-container">
<h2>SubSection D3</h2>
<p id="D3-values">D3 Values</p>
</div>
</div>
</div>
By default, the height is set to match the longest item on a row, the height on the bottom row is different to the top simply because there's more content in one of it's columns.
Try setting the rows as you have the columns, add grid-template-rows: repeat(2, 1fr); to the main-container class
Related
Is there any way to get a behaviour similar to this shown on drawing?
I mean of course manually we can specify grid-row: span x, but grid-row: span auto seems doesn't work. I need all grid items to be the same size, but when one item has to resize (due to text overflow) i need to set the grid-row: span 2, and when it's getting bigger - respectively higher number.
To acheive something like this I need to write .js or can it be done with css only?
Here is code sandbox
let items = document.querySelectorAll('.item')
items.forEach(item => {
if(item.scrollHeight>item.clientHeight){
let itemSpan = Math.round(item.scrollHeight/40) + 1 // (height = 30) + (gap = 10) 40 =>
item.style.cssText = `--n : ${itemSpan}`
}
})
.container {
width: 200px;
margin: 15vw auto;
}
.grid {
width: 100%;
background-color: chartreuse;
display: grid;
justify-items: center;
grid-template-columns: 1fr 1fr;
grid-auto-rows: 30px;
grid-auto-flow: row;
grid-gap: 10px;
word-break: break-all;
}
.item {
background-color: gold;
min-height: 30px;
width: 50px;
padding: 5px;
grid-row: auto / span var(--n); /* var(--n) is calculated with js */
box-sizing: border-box;
}
<div class="container">
<div class="grid">
<div class="item">1</div>
<div class="item ">2 Lorem ipsum dolor sit amet consectetur adipisicing </div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5 t amet consectetur adipisi</div>
<div class="item">6 lorem</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9 t amet consectetur adipisi </div>
</div>
</div>
Sometimes good to review the fundamentals:
HTML is for structure.
CSS is for presentation.
JavaScript is for behavior.
Your problem falls within 3 ("item has to resize (due to text overflow)")
You can add min-height to ".item" class to set same size of grid items.
.item{
min-height:100px;
}
.App {
font-family: sans-serif;
text-align: center;
}
.container {
width: 200px;
height: 200px;
}
.grid {
width: 100%;
background-color: chartreuse;
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 10px;
grid-auto-flow: dense;
}
.item {
background-color: brown;
height: 30px;
min-height:100px;
}
.large {
height: fit-content;
word-break: break-all;
grid-row: span auto;
}
<div class="App">
<div class="container">
<div class="grid">
<div class="item"> </div>
<div class="item large">
asdasdasdasdasdsadasdasdasdasdasdasd{" "}
</div>
<div class="item"> </div>
<div class="item"> </div>
<div class="item"> </div>
<div class="item"> </div>
</div>
</div>
</div>
This question already has answers here:
How to disable equal height columns in Flexbox?
(4 answers)
Closed 1 year ago.
I have 2 divs both with the same class and when I add content to one the height of the other also changes.
function addContent() {
document.getElementsByClassName('list')[1].innerHTML += "<h1>test</h1>"
}
.container {
width: 79%;
margin: 0 auto;
}
.bansContainer {
display: flex;
margin: 25px 0;
overflow: auto;
justify-content: space-between;
}
.list {
background-color: #436935;
}
<div class="container">
<div class="bansContainer">
<div class="list">
<h1>
left
</h1>
</div>
<div>
<h1 class="list">
right
</h1>
<button onclick=addContent()>Click</button>
</div>
</div>
</div>
How can I change/update it in a way that only the height of the div with content being added changes?
function addContent() {
document.getElementsByClassName('list')[1].innerHTML += "<h1>test</h1>"
}
.container {
width: 79%;
margin: 0 auto;
}
.bansContainer {
display: flex;
margin: 25px 0;
overflow: auto;
justify-content: space-between;
}
.list {
background-color: #436935;
align-self: flex-start;
}
<div class="container">
<div class="bansContainer">
<div class="list">
<h1>
left
</h1>
</div>
<div>
<h1 class="list">
right
</h1>
<button onclick=addContent()>Click</button>
</div>
</div>
</div>
It is because you haven't specified height on the first column and it's continuing to adapt the height of its parent div aka bansContainer. So here are two approaches. One is you add align-self: flex-start; or you specify a height on the column.
function addContent() {
document.getElementsByClassName('list')[1].innerHTML += "<h1>test</h1>"
}
.container {
width: 79%;
margin: 0 auto;
}
.bansContainer {
display: flex;
margin: 25px 0;
overflow: auto;
justify-content: space-between;
}
.list {
background-color: #436935;
/*align-self: flex-start;*/
}
.n-h {
height: fit-content;
}
<div class="container">
<div class="bansContainer">
<div class="list n-h">
<h1>
left
</h1>
</div>
<div>
<h1 class="list">
right
</h1>
<button onclick=addContent()>Click</button>
</div>
</div>
</div>
I have this div with three inner divs.
ONE - I am div TWO - I am div THREE - I am div
But in mobile it can only fit two divs in a row horizontally, I need divs after 2nd to step down.
Like this:
ONE - I am div TWO - I am div
THREE - I am div
How do I do this?
I am using flex.
Edit
I have added HTML code.
I am using React and other UI component and I tried to minimize it in HTML. It's something like this right now.
<div class="parent">
<div class="child">
<span>ONE</span>
<p>I am div</p>
</div>
<div class="child">
<p>TWO</p>
<p>I am div</p>
</div>
<div class="child">
<span>THREE</span>
<p>I am div</p>
</div>
<div>
.parent {
display: flex;
justify-content: space-around;
margin-bottom: 3rem;
white-space: nowrap;
}
.child {
display: flex;
align-items: center;
margin-left: 1rem;
margin-right: 1rem;
}
You can use flex-wrap to continue on the next line. justify-content will center the div
.outer {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
/* Styles below are for demonstration purposes */
.inner {
height: 50px;
width: 300px;
}
.red {
background: red;
}
.green {
background: green;
}
.blue {
background: blue;
}
<div class="outer">
<div class="inner red">A</div>
<div class="inner green">B</div>
<div class="inner blue">C</div>
</div>
This will work for responsive layout, and it also permits them to fit in one line, if the screen size allows it. You can use media query to set it for mobile only.
.outer{
display: flex;
flex-flow: wrap;
text-align: center;
}
.inner{
flex-grow: 1;
}
My playground fiddle:
https://jsfiddle.net/r6h8m3qs/1/
All the solutions make assumptions on the amount of COLUMNS e.g. grid-template-columns: repeat(1fr, 7) or they make assumptions on the ITEMS-width: grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
In my case:
only the width of the container is set (eg 50vw).
I then want to fit as many columns with the with of the WIDEST ELEMENT.
I don't know how many elements I will have.
I don't know how wide the WIDEST ELEMENT will be.
Is there a dynamic solution to get something like the SECOND example in my jsfiddle ?
<div class="container2">
<div class="item2">123</div>
<div class="item2">123456</div>
<div class="item2">1</div>
<div class="item2">2</div>
<div class="item2">3</div>
<div class="item2">12</div>
<div class="item2">23</div>
<div class="item2">56</div>
<div class="item2">89</div>
<div class="item2">4</div>
</div>
.container2 {
resize: both;
overflow: auto;
width: 50vw;
border: 2px dashed black;
display: grid;
grid-gap: 1em;
grid-template-columns: repeat(auto-fill, minmax(7ex, 1fr));
}
.item2 {
display: inline;
background-color: pink;
}
<h3>
Desired result: Without knowing item2-width and amount of cols
</h3>
<div class="container2">
<div class="item2">123</div>
<div class="item2">123456</div>
<div class="item2">1</div>
<div class="item2">2</div>
<div class="item2">3</div>
<div class="item2">12</div>
<div class="item2">23</div>
<div class="item2">56</div>
<div class="item2">89</div>
<div class="item2">4</div>
</div>
(resize handle in the corner of div.container2)
I am trying to write a code is CSS and normal javascript but it won't work. Here is my code (HTML and CSS).
.wrapper{
height: 100%;
margin: 1.5rem 0 0 0;
display: flex;
}
.first{
vertical-align: top;
display: inline-block;
margin-right: 2rem;
flex: 1;
}
.second{
vertical-align:top;
display: inline-block;
flex: 1;
}
<div class="wrapper">
<div class="first">
<div class="times">
<div><h1>TIMES</h1><br></div>
<div class="space">
<h2>TIMES</h2>
<p>GESLOTEN</p>
</div>
<div class="space">
<h2>Dinsdag - Zaterdag</h2>
<p>09:30 UUR - 18:00 UUR</p>
</div>
</div>
</div>
<div class="second">
<div class="welcome">
<div><h1>WELKOM</h1></div>
<div><p>TEKST</p></div>
</div>
</div>
</div>
I have tried everything, at least I think I have.
The problem is that I can't fix this in CSS but I tried Java.
Still no success. Can someone please explain why I can't get it the same height.
It's a school project and I need to make a website from scratch.
Here is my full website source code: https://codepen.io/crosso_7/pen/VERrvQ
Both first and second divs are actually the same height - I just copied your snippet and applied a border around each div to see the issue and both divs are equal.
.wrapper{
height: 100%;
margin: 1.5rem 0 0 0;
display: flex;
}
.first{
vertical-align: top;
display: inline-block;
margin-right: 2rem;
flex: 1;
border: solid 1px blue;
}
.second{
vertical-align:top;
display: inline-block;
flex: 1;
border: solid 1px red;
}
<div class="wrapper">
<div class="first">
<div class="times">
<div><h1>TIMES</h1><br></div>
<div class="space">
<h2>TIMES</h2>
<p>GESLOTEN</p>
</div>
<div class="space">
<h2>Dinsdag - Zaterdag</h2>
<p>09:30 UUR - 18:00 UUR</p>
</div>
</div>
</div>
<div class="second">
<div class="welcome">
<div><h1>WELKOM</h1></div>
<div><p>TEKST</p></div>
</div>
</div>
</div>
You can do it using flexbox. Something like this code snippet.
.wrapper {
display: flex;
justify-content: space-between;
}
.wrapper div {
background: #000;
color: #fff;
flex: 1;
margin: 10px;
justify-content: center;
}
<div class='wrapper'>
<div>
<h1>1</h1>
<h2>asasasa</h2>
</div>
<div>2</div>
</div>
Is the first div the one thats higher? It's probably created by the padding from first div content vs seconds less content.
May have to set first and second div with a px or % height which are the same to make it equal.
Try using the code below in your .first and .second divs
flex: 1;
display: flex;