Using flexbox why two images with different proportions stretch differently - css

I want to make a flexbox grid for cards with one big image on left and two right images vertically aligned. Everything is fine and aligned for desktop at 1280px but when images stretch for responsive view, the image on the left is stretching more rapidly and cards are no more vertically aligned.
Here a codepen illustrating the problem:
https://codepen.io/actik/pen/xaZqmG
.wrap {
width: 100%;
max-width: 1280px;
margin: 0 auto;
}
.flex {
display: flex;
box-sizing: border-box;
align-items: flex-start;
}
.row {
flex-flow: row wrap;
}
.col {
flex-flow: column wrap;
}
.structure-100 {
flex: 1 100%;
}
.structure-50 {
flex: 1 50%;
}
.content {
color: #fff;
background-color: #aa0000;
width: 100%;
flex: 1 100%;
}
.element_left {
flex: 1 50%;
padding-right: 15px;
padding-bottom: 30px;
}
.element_right {
flex: 1 50%;
padding-left: 15px;
padding-bottom: 30px;
}
.content-text {
padding: 0 10px;
}
img {
max-width: 100%;
height: auto;
align-self: center;
}
<div class="wrap">
<div class="flex row structure-100">
<div class="flex col structure-50">
<div class="flex element_left">
<div class="content">
<img src="http://www.placebacon.net/625/875/" alt="">
<div class="content-text">
<h2>Card title</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus interdum lacus vitae aliquam ullamcorper.</p>
</div>
</div>
</div>
</div>
<div class="flex col structure-50">
<div class="flex element_right">
<div class="content">
<img src="http://www.placebacon.net/625/360" alt="">
<div class="content-text">
<h2>Card title</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus interdum lacus vitae aliquam ullamcorper.</p>
</div>
</div>
</div>
<div class="flex element_right">
<div class="content">
<img src="http://www.placebacon.net/625/360" alt="">
<div class="content-text">
<h2>Card title</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus interdum lacus vitae aliquam ullamcorper.</p>
</div>
</div>
</div>
</div>
</div>
</div>
I made a lot of different tests and can't understand this behavior, any tips welcome, thanks for your help !
Editing : Here the version at 1280px working (title cards are aligned at the bottom) and the second version when reducing width, bottom of the 2 images and title cards are no more aligned. I want the red part add space at his bottom if necessary but keep image and title aligned.
working version
not working
Big image is squashed.

As I understood from our talk in the comments, your issue that the left section with the 'big' image (the images aren't present in the snippet you provided, they're present in the CodePen demo that tou do provided its link) isn't stretching as supposed, and that because in yourCSS you gave the .flex class a rule of align-items: flex-start; which means that the element of the flex container should be placed on the top (vertical), thus, it doesn't let the element to stretch, instead, you just have to replace this line align-items: flex-start; with align-items: stretch; in the .flex class, so that class becomes:
.flex {
display: flex;
box-sizing: border-box;
align-items: stretch;
}
And here's a runnable snippet:
$gutter: 30px;
.wrap{
width: 100%;
max-width: 1280px;
margin: 0 auto;
}
.flex {
display: flex;
box-sizing: border-box;
align-items: stretch;
}
.row {
flex-flow: row wrap;
}
.col {
flex-flow: column wrap;
}
.structure-100 {
flex: 1 percentage(1/1);
}
.structure-50 {
flex: 1 percentage(1/2);
}
.content {
color: #fff;
background-color: #aa0000;
width: 100%;
flex: 1 100%;
}
.element_left .content {
display: flex;
flex-flow: column wrap;
}
.element_left {
flex: 1 percentage(1/2);
padding-right: $gutter / 2;
padding-bottom: $gutter;
}
.element_right {
flex: 1 percentage(1/2);
padding-left: $gutter / 2;
padding-bottom: $gutter;
}
.content-text {
padding: 0 10px;
}
.element_left .content .content-text {
flex-grow: 0;
margin-top: auto;
}
img {
max-width: 100%;
height: auto;
}
.element_left .content img {
width: 100%;
flex-grow: 1;
align-self: flex-start;
}
<div class="wrap">
<div class="flex row structure-100">
<div class="flex col structure-50">
<div class="flex element_left">
<div class="content">
<img src="http://www.placebacon.net/625/875/" alt="">
<div class="content-text">
<h2>Card title</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus interdum lacus vitae aliquam ullamcorper.</p>
</div>
</div>
</div>
</div>
<div class="flex col structure-50">
<div class="flex element_right">
<div class="content">
<img src="http://www.placebacon.net/625/360" alt="">
<div class="content-text">
<h2>Card title</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus interdum lacus vitae aliquam ullamcorper.</p>
</div>
</div>
</div>
<div class="flex element_right">
<div class="content">
<img src="http://www.placebacon.net/625/360" alt="">
<div class="content-text">
<h2>Card title</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus interdum lacus vitae aliquam ullamcorper.</p>
</div>
</div>
</div>
</div>
</div>
</div>
Hope I pushed you further.

Related

How to create an assymetric two-column layout?

I'm trying to create a two column layout, where the second column is moved downward a bit.
Currently I create a two column layout and translateY the second column, which is odd and doesn't play nicely with flow of other elements.
Is there any way to do this in a more natural way?
* {
box-sizing: border-box;
}
main {
display: flex;
flex-wrap: wrap;
width: 12.4em;
}
.box {
display: flex;
justify-content: center;
align-items: center;
width: 6em;
height: 6em;
margin: 0.1em;
background-color: black;
color: white;
}
.box:nth-of-type(2n) {
transform: translateY(50%);
}
.box--more {
cursor: pointer;
}
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Provident, ea.</p>
<main>
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box box--more">...</div>
</main>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Neque, corrupti?</p>
As #a-haworth and #paulie_d kindly mentioned, it can be solved quite easily with css-grids by filling the gap with a placeholder item:
main {
display: grid;
grid-template-columns: repeat(2, fit-content(1em));
grid-auto-rows: 1fr;
grid-gap: 0.1em;
}
main::before {
content: "";
grid-area: 1 / 2;
}
.box {
grid-row-end: span 2;
display: flex;
justify-content: center;
align-items: center;
width: 6em;
height: 6em;
background-color: black;
color: white;
}
.box--more {
cursor: pointer;
}
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Provident, ea.</p>
<main>
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box box--more">...</div>
</main>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Neque, corrupti?</p>

CSS Center text inside paragraph [duplicate]

This question already has answers here:
How can I center text (horizontally and vertically) inside a div block?
(27 answers)
Closed 2 years ago.
How to vertically center text inside p? Thank you.
enter image description here
Flexbox solution - the more modern solution:
https://jsfiddle.net/2zqeL6g8/
The HTML:
<div class="todo">
<div class="todo-left">
<p>TODO 1</p>
</div>
<div class="todo-right">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed rhoncus aliquam egestas. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed rhoncus aliquam egestas.</p>
</div>
</div>
The CSS:
.todo {
display: flex;
}
.todo-left {
background: #ccc;
padding: 0 15px;
flex: 0 0 100px;
display: flex;
align-items: center;
}
.todo-right {
background: #f5f5f5;
padding: 0 15px;
flex: 1;
display: flex;
align-items: center;
}
CSS table solution - older method, but works in older browsers ie8+:
https://jsfiddle.net/2zqeL6g8/2/
The HTML:
<div class="todo">
<div class="todo-row">
<div class="todo-cell-left">
<p>TODO 1</p>
</div>
<div class="todo-cell-right">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed rhoncus aliquam egestas. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed rhoncus aliquam egestas.</p>
</div>
</div>
</div>
The CSS:
.todo {
display: table;
border-collapse: collapsed;
width: 100%;
}
.todo-row {
display: table-row;
}
.todo-cell-left,
.todo-cell-right {
display: table-cell;
vertical-align: middle;
padding: 0 15px;
}
.todo-cell-left {
background: #ccc;
width: 100px;
}
.todo-cell-right {
background: #f5f5f5;
}
.todo {
display: flex;
}
.todo-left {
background: #ccc;
padding: 0 15px;
flex: 0 0 100px;
height:100px;
display: flex;
align-items: center;
}
.todo-right {
background: #f5f5f5;
padding: 0 15px;
flex: 1;
display: flex;
align-items: center;
}
<div class="todo">
<div class="todo-left">
<p>TODO 1</p>
</div>
<div class="todo-right">
<p>Lorem ipsum dolor sit .</p>
</div>
</div>

Flex item element to fill space of parent

I have 2 cards 50/50 split using flex. The flex items both have equal heights, but I'd like a child element of the item to fill the height of the parent. In the pen, this would mean the blue background color would expand to the height of its parent.
This question is very close but the background-clip: padding-box; doesn't solve the issue for me.
Online demo here: Code pen
.wrapper {
max-width: 70%;
margin: auto;
}
.cards-group {
display: flex;
.card {
flex: 1;
border: 1px solid #0074d9;
}
.card + .card {
margin-left: 30px;
}
}
.card-image {
img {
display: block;
border-radius: 3px;
margin-left: auto;
max-width: 90%;
}
} // .card-image
.card-section {
padding: 20px;
background-color: #7fdbff;
mix-blend-mode: multiply;
border-radius: 3px;
margin-top: -50px;
} // .card-section
<div class="wrapper">
<div class="cards-group">
<div class="card">
<div class="card-image">
<img src="https://via.placeholder.com/350x150" alt="">
</div><!-- .card-image -->
<div class="card-section">
<h3 class="card-title">Title</h3>
<div class="card-text">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean sagittis sagittis pellentesque.</p>
<button type="button" class="card-button" onclick="location.href=''">Link</button>
</div><!-- .card-section -->
</div>
</div><!-- .card -->
<div class="card">
<div class="card-image">
<img src="https://via.placeholder.com/350x150" alt="">
</div><!-- .card-image -->
<div class="card-section">
<h3 class="card-title">Title</h3>
<div class="card-text">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean sagittis sagittis pellentesque.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean sagittis sagittis pellentesque.</p>
<button type="button" class="card-button" onclick="location.href=''">Link</button>
</div><!-- .card-section -->
</div>
</div>
<!-- .card -->
</div>
</div>
You can do that by adding display: flex; on .card :
.card {
display: flex;
flex-direction: column;
flex: 1;
border: 1px solid #0074d9;
}
And then telling your .card-section to take the remaining space with flex: 1 :
.card-section {
padding: 20px;
background-color: #7fdbff;
mix-blend-mode: multiply;
border-radius: 3px;
margin-top: -50px;
flex: 1;
}
.wrapper {
max-width: 70%;
margin: auto;
}
.cards-group {
display: flex;
}
.cards-group .card {
display: flex;
flex-direction: column;
flex: 1;
border: 1px solid #0074d9;
}
.cards-group .card + .card {
margin-left: 30px;
}
.card-image img {
display: block;
border-radius: 3px;
margin-left: auto;
max-width: 90%;
}
.card-section {
padding: 20px;
background-color: #7fdbff;
mix-blend-mode: multiply;
border-radius: 3px;
margin-top: -50px;
flex: 1;
}
<div class="wrapper">
<div class="cards-group">
<div class="card">
<div class="card-image">
<img src="https://via.placeholder.com/350x150" alt="">
</div>
<!-- .card-image -->
<div class="card-section">
<h3 class="card-title">Title</h3>
<div class="card-text">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean sagittis sagittis pellentesque.</p>
<button type="button" class="card-button" onclick="location.href=''">Link</button>
</div>
<!-- .card-section -->
</div>
</div>
<!-- .card -->
<div class="card">
<div class="card-image">
<img src="https://via.placeholder.com/350x150" alt="">
</div>
<!-- .card-image -->
<div class="card-section">
<h3 class="card-title">Title</h3>
<div class="card-text">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean sagittis sagittis pellentesque.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean sagittis sagittis pellentesque.</p>
<button type="button" class="card-button" onclick="location.href=''">Link</button>
</div>
<!-- .card-section -->
</div>
</div>
<!-- .card -->
</div>
</div>

How to align same height divs

I've this code
.row {
width: 600px;
}
.row div {
display: inline-block;
width: 50%;
float: left;
}
.text {
background-color: lightblue;
}
<div class="row">
<div class="image">
<img src="http://placehold.it/250x150">
</div>
<div class="text">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Debitis incidunt.</p>
</div>
</div>
I want my div .text to have the same height as the image.
I want it responsive no I can't set a height to .text
Thanks for your help !
One option is with Flexbox
body, html {
margin: 0;
padding: 0;
}
.row {
width: 600px;
display: flex;;
}
.text {
background-color: lightblue;
}
img {
vertical-align: top;
}
<div class="row">
<div class="image"><img src="http://placehold.it/250x150">
</div>
<div class="text">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Debitis incidunt.</p>
</div>
</div>
Other one is CSS table
body, html {
margin: 0;
padding: 0;
}
.row {
width: 600px;
display: table;
}
.text {
background-color: lightblue;
display: table-cell;
vertical-align: top;
}
.image {
display: table-cell;
vertical-align: top;
}
img {
vertical-align: top;
}
<div class="row">
<div class="image"><img src="http://placehold.it/250x150">
</div>
<div class="text">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Debitis incidunt.</p>
</div>
</div>
Here is one way using display-table:
.row {
width: 600px;
display: table;
}
.row > div {
width: 50%;
display: table-cell;
vertical-align: top; /* or 'middle' or 'bottom' etc. */
}
.text {
background-color: lightblue;
}
.image img {
display: block;
}
<div class="row">
<div class="image">
<img src="http://placehold.it/250x150">
</div>
<div class="text">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Debitis incidunt.</p>
</div>
</div>
Here is one solution which just uses height:auto; :
.row {
width: 600px;
height: auto;
background-color: lightblue;
}
.image, .text {
display: inline-block;
width: 49%;
}
.image {
background-color: white;
}
.text, .image img {
vertical-align:top;
}
<div class="row">
<div class="image">
<img src="http://placehold.it/250x150">
</div>
<div class="text">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Debitis incidunt.</p>
</div>
</div>

How to make flexbox items with custom widths jump to available space

I'm trying to achieve Pinterest-like layout, but with items of different percentage widths. Expected behaviour is pretty much like Javascript masonry plugin.
My flexbox code for some reason does not nake flexbox items jump side-by-side to another, event, when exact space is available.
Illustration of what I'm trying to achieve
demo on jsfiddle
https://jsfiddle.net/31v7et9f/1/
html
<div class="masonry">
<div class="item-1-4">item 25%</div>
<div class="item-1-1">item 100%</div>
<div class="item-3-4">item 75%</div>
<div class="item-1-2">item 50%</div>
<div class="item-1-2">item 50%</div>
<div class="item-1-1">item 100%</div>
</div>
css
* {box-sizing: border-box;}
/* parent */
.masonry {
display: flex;
flex-flow: column;
}
/* childs */
.masonry > div {
background: gray;
outline: solid 1px black;
height: 100px;
}
/* child sizes */
.item-1-1 {width: 100%;}
.item-3-4 {width: 75%;}
.item-1-2 {width: 50%;}
.item-1-4 {width: 25%;}
Flexbox items are by default layed out in the order they appear in the html. So, using your html and using flex-flow: row wrap; you'll get your 2 50%s side by side, but not your 75% and 25%.
/* parent */
.masonry {
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
}
You could rearrange your html (do some math in javascript to determine which order they should be in to tile).
<div class="masonry">
<div class="item-1-1">item 100%</div>
<div class="item-1-4">item 25%</div>
<div class="item-3-4">item 75%</div>
<div class="item-1-2">item 50%</div>
<div class="item-1-2">item 50%</div>
<div class="item-1-1">item 100%</div>
</div>
You could also use order to group items that should be able to tile, though it's not perfect
/* child sizes */
.item-1-1 {
width: 100%;
-webkit-order: 1;
order: 1;
}
.item-3-4 {
width: 75%;
-webkit-order: 2;
order: 2;
}
.item-1-2 {
width: 50%;
-webkit-order: 3;
order:3;
}
.item-1-4 {
width: 25%;
-webkit-order: 2;
order:2;
}
https://jsfiddle.net/31v7et9f/2/
We can use flex-wrap: wrap; align-items: flex-stat; in parent flex class and child we can use flex: 1 auto; so that it consider available space and align automatically.
.fill-height-or-more {
min-height: 100%;
display: flex;
flex-wrap: wrap;
align-items: flex-stat;
}
.fill-height-or-more
div {
flex: 1 auto;
display: flex;
flex-direction: column;
justify-content: center;
}
.some-area
div {
padding: 1rem;
}
.some-area
div:nth-child(1) {
background: rgba(136, 204, 102, 1);
}
.some-area
div:nth-child(2) {
background: rgba(121, 181, 210, 1);
}
.some-area
div:nth-child(3) {
background: rgba(140, 191, 217, 1);
}
.some-area
div:nth-child(4) {
background: rgba(159, 202, 223, 1);
}
.some-area
div:nth-child(5) {
background: rgba(179, 213, 230, 1);
}
.some-area
div h1, .some-area
div h2 {
margin: 0 0 0.2rem 0;
}
.some-area
div p {
margin: 0;
}
html, body {
height: 100%;
}
<section class="some-area fill-height-or-more">
<div>
<h1>Boxes That Fill Height (or more)</h1>
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
</div>
<div>
<h2>Two</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Error ut.</p>
</div>
<div>
<h2>Three</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Error ut.</p>
</div>
<div>
<h2>Four</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Error ut.</p>
</div>
<div>
<h2>Five</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Error ut.</p>
</div>
</section>

Resources