Flexbox make columns equal heights - css

I am trying to get 3 columns in a row and be the same height.
I am using the HTML/CSS below. I can't figure out why the boxes arent the same height.
.container {
text-align: center;
display: block;
width: 100%;
}
.grid {
width: 100%;
height: 100%;
}
.row {
display: flex;
height: 100%;
flex-direction: row;
}
.col {
background: #444;
padding: 2em;
flex: 1;
height: 100%;
border: 1px solid blue;
}
<div class="container">
<div class="data">
<div class="grid">
<div class="row">
<div class="col">
<p>col 1</p>
</div>
<div class="col">
<p>col </br>2</p>
</div>
<div class="col">
<p>col 3</p>
</div>
</div>
</div>
</div>
</div>
How can I make the boxes all the same height. thanks

Simply, remove the height: 100% from .col.
flex: 1; will do the job.
.row {
display: flex;
}
.col {
flex: 1;
background: #444;
padding: 2em;
border: 1px solid blue;
text-align: center;
}
<div class="container">
<div class="data">
<div class="grid">
<div class="row">
<div class="col">
<p>col 1</p>
</div>
<div class="col">
<p>col </br>2</p>
</div>
<div class="col">
<p>col 3</p>
</div>
</div>
</div>
</div>
</div>

Related

Keep left margin of a div inline with another div when resizing

the problem that I'm having is that when I resize the browser the left margins of both the and my card divs aren't aligning. Is there some sort of css property or maybe some JS that will make them stay aligned when resizing?
here's my sandbox
https://codesandbox.io/s/stupefied-christian-tosys?file=/src/styles.css:0-
Add the .filter margin margin: 0 80px; to your .row. and then remove justify-content: center;. It will loose the centered. But will be align on the left. To aviod the overflow from the body, you can set width: calc(100% - 160px);to your .row:
/* ADDED BELOW */
margin: 0 80px;
justify-content: unset;
width: calc(100% - 160px);
After if you want to keep your card more center, either you use justify-content: space-between; on row, either you use margin: 10px auto; on your card.
DEMO:
body {
margin: 0 auto;
max-width: 1200px;
}
.row {
display: flex;
justify-content: center;
width: 100%;
flex-wrap: wrap;
/*ADDED BELOW */
margin: 0 80px;
justify-content: unset;
width: calc(100% - 160px);
}
.filter {
display: flex;
margin: 0 80px;
}
.filter select {
display: inline;
width: 15rem;
margin: 10px;
border-radius: 5px;
}
.card {
width: 15rem;
margin: 10px;
border-radius: 5px;
border: 1px solid rgba(0, 0, 0, 0.125);
}
.info {
padding: 15px;
}
.img-container {
padding-top: 0;
position: relative;
}
.card img {
width: 100%;
object-fit: cover;
}
.price {
font-weight: bold;
}
<div id="root">
<div class="App">
<div class="filter-container">
<div class="product-listing-wrap">
<div class="filter">
<select class="custom-select" id="priceGroup">
<option value="1">Under $50</option>
<option value="2">$50 to $100</option>
<option value="3">$100 to $250</option>
<option value="4">Over $250</option>
</select>
</div>
<div class="row" style="
margin: 0 80px;
padding: 10px 0;
width: calc(100% - 160px);
">
<div class="card">
<div class="img-container"><img src="https://images.pexels.com/photos/593171/pexels-photo-593171.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" alt="1"></div>
<div class="info">
<p class="info-title"><span><a>placeholder...</a></span></p>
</div>
</div>
<div class="card">
<div class="img-container"><img src="https://images.pexels.com/photos/593171/pexels-photo-593171.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" alt="2"></div>
<div class="info">
<p class="info-title"><span><a>placeholder...</a></span></p>
</div>
</div>
<div class="card">
<div class="img-container"><img src="https://images.pexels.com/photos/593171/pexels-photo-593171.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" alt="3"></div>
<div class="info">
<p class="info-title"><span><a>placeholder...</a></span></p>
</div>
</div>
<div class="card">
<div class="img-container"><img src="https://images.pexels.com/photos/593171/pexels-photo-593171.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" alt="4"></div>
<div class="info">
<p class="info-title"><span><a>placeholder...</a></span></p>
</div>
</div>
<div class="card">
<div class="img-container"><img src="https://images.pexels.com/photos/593171/pexels-photo-593171.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" alt="5"></div>
<div class="info">
<p class="info-title"><span><a>placeholder...</a></span></p>
</div>
</div>
<div class="card">
<div class="img-container"><img src="https://images.pexels.com/photos/593171/pexels-photo-593171.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" alt="6"></div>
<div class="info">
<p class="info-title"><span><a>placeholder...</a></span></p>
</div>
</div>
<div class="card">
<div class="img-container"><img src="https://images.pexels.com/photos/593171/pexels-photo-593171.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" alt="7"></div>
<div class="info">
<p class="info-title"><span><a>placeholder...</a></span></p>
</div>
</div>
<div class="card">
<div class="img-container"><img src="https://images.pexels.com/photos/593171/pexels-photo-593171.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" alt="8"></div>
<div class="info">
<p class="info-title"><span><a>placeholder...</a></span></p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
try it:
.row {
display: flex;
justify-content: space-between;
margin: 0 80px;
max-width: 1040px;
flex-flow: wrap;
}

Display items in one line with scroll CSS

I am trying to display images in a single line horizontal with scroll but I can't figure how to I would appreciate it if anyone could help me.
CSS
.img {
max-width: 400px;
position: relative;
}
.animal {
float: left;
background-color: #fff;
}
.image-grid{
flex-wrap: wrap;
width: 1400px;
margin: 0 auto;
}
.pet-photo {
padding: 10px;
display: block;
box-sizing: border-box;
flex-basis: 100%;
float: left;
padding: 20px;
width: 200px;
height: 300px;
display: block;
}
js
<div class ="image-grid">
<div class="animal">
<img class="pet-photo " src="${pet.photo}" >
<div class="olay" onclick="location.href='${pet.href}';" style="cursor: pointer;">
<div id="mydiv">
<h2 class="pet-name">${pet.name}
<h1 class="species">${pet.species}
</div>
<div></div></div>
</div>
</div>
That's all thank you for reading :) really appreciate it.
solution is display: flex; with flex-wrap: nowrap;
.container-items {
overflow: auto;
width: 100%;
}
.items {
display: flex;
flex-wrap: nowrap;
}
.items .item {
min-width: 150px;
text-align: center;
padding: 5px;
}
.items .item h2,
.items .item h3 {
margin: 0;
}
.items .item img {
width: 100%;
}
<div class ="container-items">
<div class ="items">
<div class="item">
<img src="https://cdn.mos.cms.futurecdn.net/otjbibjaAbiifyN9uVaZyL-320-80.jpg">
<h2>here title</h2>
<h3 class="species">here text</h3>
</div>
<div class="item">
<img src="https://cdn.mos.cms.futurecdn.net/otjbibjaAbiifyN9uVaZyL-320-80.jpg">
<h2>here title</h2>
<h3>here text</h3>
</div>
<div class="item">
<img src="https://cdn.mos.cms.futurecdn.net/otjbibjaAbiifyN9uVaZyL-320-80.jpg">
<h2>here title</h2>
<h3 class="species">here text</h3>
</div>
<div class="item">
<img src="https://cdn.mos.cms.futurecdn.net/otjbibjaAbiifyN9uVaZyL-320-80.jpg">
<h2>here title</h2>
<h3 class="species">here text</h3>
</div>
<div class="item">
<img src="https://cdn.mos.cms.futurecdn.net/otjbibjaAbiifyN9uVaZyL-320-80.jpg">
<h2>here title</h2>
<h3 class="species">here text</h3>
</div>
<div class="item">
<img src="https://cdn.mos.cms.futurecdn.net/otjbibjaAbiifyN9uVaZyL-320-80.jpg">
<h2>here title</h2>
<h3 class="species">here text</h3>
</div>
<div class="item">
<img src="https://cdn.mos.cms.futurecdn.net/otjbibjaAbiifyN9uVaZyL-320-80.jpg">
<h2>here title</h2>
<h3 class="species">here text</h3>
</div>
</div>
</div>

How to make div expand with content using flex?

I have this HTML and CSS:
.container {
width: 100%;
}
.group {
display: flex;
justify-content: space-between;
min-width: 214px;
background: #eee;
}
.abbr {
/* some styling */
}
.name {
/* some styling */
}
<div class="container">
<div class="group">
<div class="abbr">
<p>MS</p>
</div>
<div>
<p class="name">Mark Smith</p>
</div>
</div>
</div>
Now, if I use just min-width, the whole div stretches as the entire width of the container. If I just use width, it won't expand if the name is longer than Mark Smith (rather it will go to the next line).
This is what I wanted to achieve:
How do I achieve this in flexbox?
What you're looking for is to apply width: fit-content to .group.
Then you can adjust the offset between the abbreviation and name with min-width on the .abbr.
This can be seen in the following:
.group {
display: flex;
width: fit-content;
background: #eee;
margin: 10px 0;
}
.group > div {
margin: 0 10px;
}
.abbr {
min-width: 50px;
}
<div class="container">
<div class="group">
<div class="abbr">
<p>MS</p>
</div>
<div>
<p class="name">Mark Smith</p>
</div>
</div>
<div class="group">
<div class="abbr">
<p>MS</p>
</div>
<div>
<p class="name">A Really Really Long Name</p>
</div>
</div>
</div>
I use inline-block on .container so that it won't take up the whole line.
.container {
display: inline-block;
}
.group {
display: flex;
background: #eee;
}
.abbr {
padding: 0 7px;
}
.name {
padding: 0 7px;
}
<div class="container">
<div class="group">
<div class="abbr">
<p>MS</p>
</div>
<div>
<p class="name">Mark Smith</p>
</div>
</div>
</div><br/><br/>
<div class="container">
<div class="group">
<div class="abbr">
<p>MR</p>
</div>
<div>
<p class="name">Loooooooooooooooong Name</p>
</div>
</div>
</div>
Another solution is to use a third element that consume all the remaining space and set the background color on the text content only:
.container {
margin: 0 0 5px 0;
}
.group {
display: flex;
}
.abbr {
padding: 0 7px;
background: #eee;
}
.name {
padding: 0 7px;
background: #eee;
flex: 0 0 auto;
}
.blank-space{
flex: 1 1 auto;
}
<div class="container">
<div class="group">
<div class="abbr">
<p>MS</p>
</div>
<div class="name">
<p>Mark Smith</p>
</div>
<div class="blank-space"></div>
</div>
</div>
<div class="container">
<div class="group">
<div class="abbr">
<p>MR</p>
</div>
<div class="name">
<p>Loooooooooooooooong Name</p>
</div>
<div class="blank-space"></div>
</div>
</div>

Flexbox: row with inline-flex + fixed item width (fixing flex-basis bug): not working inside column layout

I want to get a table in CSS with a sticky header (only body scrolls) on Y, and whole table scrolls on X.
According to Michael_B comment on my previous question here there is a flexbox bug and I have to use inline-flex on row + width on cells to make sure my row grows correctly.
This leads me to this result:
html, body {
width: 100%;
min-height: 100vh;
margin: 0;
padding: 0;
}
body {
display: flex;
align-items: center;
justify-content: center;
}
.table {
border: solid black;
width: 60vw;
height: 80vh;
overflow-x: auto;
display: flex;
flex-direction: column;
}
.header {
border: solid cyan;
flex: 0;
}
.body {
flex: 1;
overflow-y: auto;
border: solid yellow;
display: inline-block;
}
.row {
border: solid red;
display: inline-flex;
flex-direction: row;
align-items: center;
}
.cell {
border: solid green;
width: 400px;
height: 50px;
}
<div class="table">
<div class="header">
<div class="row">
<div class="cell">
cell 1
</div>
<div class="cell">
cell 2
</div>
<div class="cell">
cell 3
</div>
</div>
</div>
<div class="body">
<div class="row">
<div class="cell">
cell 1
</div>
<div class="cell">
cell 2
</div>
<div class="cell">
cell 3
</div>
</div>
<div class="row">
<div class="cell">
cell 1
</div>
<div class="cell">
cell 2
</div>
<div class="cell">
cell 3
</div>
</div>
<div class="row">
<div class="cell">
cell 1
</div>
<div class="cell">
cell 2
</div>
<div class="cell">
cell 3
</div>
</div>
</div>
</div>
JsFiddle
As you can see it's not exactly what I want. It seems my rows do not grow according to their content size even with inline-flex, and this happens only when using a flex column layout on the table.
html, body {
width: 100%;
min-height: 100vh;
margin: 0;
padding: 0;
}
body {
display: flex;
align-items: center;
justify-content: center;
}
.table {
border: solid black;
width: 60vw;
height: 80vh;
overflow-x: auto;
}
.header {
border: solid cyan;
flex: 0;
display: inline-block;
height: 50px;
}
.body {
flex: 1;
overflow-y: auto;
border: solid yellow;
display: inline-block;
height: calc(100% - 50px - 16px);
}
.row {
border: solid red;
display: inline-flex;
flex-direction: row;
align-items: center;
}
.cell {
border: solid green;
width: 400px;
height: 50px;
}
By removing flex column, using inline-block and calc computations, I almost get the behavior I want, except I'd like the scrollY scrollbar to always stay visible
<div class="table">
<div class="header">
<div class="row">
<div class="cell">
cell 1
</div>
<div class="cell">
cell 2
</div>
<div class="cell">
cell 3
</div>
</div>
</div>
<div class="body">
<div class="row">
<div class="cell">
cell 1
</div>
<div class="cell">
cell 2
</div>
<div class="cell">
cell 3
</div>
</div>
<div class="row">
<div class="cell">
cell 1
</div>
<div class="cell">
cell 2
</div>
<div class="cell">
cell 3
</div>
</div>
<div class="row">
<div class="cell">
cell 1
</div>
<div class="cell">
cell 2
</div>
<div class="cell">
cell 3
</div>
</div>
</div>
</div>
JsFiddle
Anyone knows how I could achieve the table layout I want? I'm open for no flexbox solution but I don't want a JS based solution for now.

Maintain ratio of container and children while resize

I have modular grid of cards with and without image, based on flexbox.
Normally cards without image are 50% of the width, cards with image are 100% of the width, and those cards without image that doesn't have a pair are also 100%.
----------------
[[ txt ][ img ]] – card with an image
----------------
[ txt ][ txt ] – 2 cards without image
----------------
[ txt ] – card without image
----------------
[[ txt ][ img ]] – card with an image
----------------
Is it possible to maintain ratio of the cards and its content while resize, and also maintain modularity with css?
Here's the code
that let me maintain ratio, but when I try to apply this technique to cards children everything breakes
<div class="wrapper">
<div class="card">
<div class="card-text">
</div>
<div class="card-image">
</div>
</div>
</div>
.wrapper
display: flex
flex-wrap: wrap
justify-content: space-between
width: 620px
.card
height: 0
padding-bottom: 50%
display: flex
flex-direction: row
justify-content: space-between
flex: 1 1 300px
.has-card-image .card-text,
.has-card-image .card-image
height: 300px
width: 300px
I can see one way this could be done w/o script.
Either as in this case, using px values, or e.g. using vw, and the reason is that the card-text and card-image needs to know the wrapper's width to be able to size according to the expected output (which mean percent can't be used).
Fiddle demo
Stack snippet
.wrapper {
display: flex;
flex-wrap: wrap;
width: 600px;
}
.card {
display: flex;
flex: 1 300px;
}
.card .card-text,
.card .card-image {
height: 100px;
width: 300px;
}
.card .card-text:only-child {
flex: 1 300px;
}
/* demo styles */
.card .card-text, .card .card-image {
border: 1px solid;
box-sizing: border-box;
}
.card .card-text::before {
content: 'text';
}
.card .card-image::before {
content: 'image';
}
<div class="wrapper">
<div class="card">
<div class="card-text">
</div>
<div class="card-image">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
<div class="card-image">
</div>
</div>
</div>
If you need the margin, you'll need an extra wrapper
Fiddle demo
Stack snippet
.wrapper {
width: 620px;
overflow: hidden;
}
.inner {
display: flex;
flex-wrap: wrap;
margin-left: -20px;
}
.card {
display: flex;
flex: 1 300px;
}
.card .card-text,
.card .card-image {
height: 100px;
width: 300px;
margin-left: 20px;
}
.card .card-text:only-child {
flex: 1 300px;
}
/* demo styles */
.card .card-text,
.card .card-image {
border: 1px solid;
box-sizing: border-box;
}
.card .card-text::before {
content: 'text';
}
.card .card-image::before {
content: 'image';
}
<div class="wrapper">
<div class="inner">
<div class="card">
<div class="card-text">
</div>
<div class="card-image">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
<div class="card-image">
</div>
</div>
</div>
</div>
Updated
Here is a version using vw and margin, and is responsive.
Note, the make up for margin set on the wrapper can also be set on each item, though I found it simpler like this.
Fiddle demo
Stack snippet
.wrapper {
width: calc(80vw + 20px); /* 20px extra for margin */
margin: 0 auto;
overflow: hidden;
}
.inner {
display: flex;
flex-wrap: wrap;
margin-left: -20px;
}
.card {
display: flex;
flex: 1 40vw;
}
.card .card-text,
.card .card-image {
height: 100px;
width: 40vw;
margin-left: 20px;
}
.card .card-text:only-child {
flex: 1 40vw;
}
/* demo styles */
.card .card-text,
.card .card-image {
border: 1px solid;
box-sizing: border-box;
}
.card .card-text::before {
content: 'text';
}
.card .card-image::before {
content: 'image';
}
<div class="wrapper">
<div class="inner">
<div class="card">
<div class="card-text">
</div>
<div class="card-image">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
<div class="card-image">
</div>
</div>
</div>
</div>

Resources