CSS grid or flexbox for aligning image and text - html

I want to make sure the image and the text in the columns are aligned to the bottom of the image and the top of the text. Does anybody know how to achieve this without explicitly setting the height of .c-grid__content to 200px?
Right now I'm using flexbox. Maybe css-grid is the answer?
Please take a look at this codepen: https://codepen.io/simoncoudeville/pen/VMZmVa?editors=1100#0.
p {
margin-bottom: 10px;
font-family: sans-serif;
}
img {
max-width: 100%;
margin-bottom: 10px;
}
.c-grid {
padding: 40px 20px;
display: flex;
}
.c-grid__item {
flex-basis: 100%;
margin: 0 20px;
display: flex;
flex-wrap: wrap;
flex-direction: column;
justify-content: flex-end;
}
.c-grid__picture {
width: 100%;
}
.c-grid__content {
display: flex;
flex-direction: column;
}
<div class="c-grid">
<article class="c-grid__item">
<div class="c-grid__picture">
<img src="http://via.placeholder.com/400x200">
</div>
<div class="c-grid__content">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolore ratione commodi corrupti itaque sed architecto!</p>
</div>
</article>
<article class="c-grid__item">
<div class="c-grid__picture">
<img src="http://via.placeholder.com/400x600">
</div>
<div class="c-grid__content">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolore ratione commodi corrupti itaque sed architecto! Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
</div>
</article>
<article class="c-grid__item">
<div class="c-grid__picture">
<img src="http://via.placeholder.com/400x400">
</div>
<div class="c-grid__content">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolore ratione commodi corrupti itaque sed architecto! </p>
</div>
</article>
</div>

Align-items: baseline on the flexbox container seems to do the trick in this case. See the solution here: https://codepen.io/simoncoudeville/pen/yzOvmN?editors=1100

Looking at your codepen, this doesn't appear to require responsive design. If I am correct in that assumption, why not use a table that separates the images and text by rows, vertically aligning the top row at the bottom and the bottom row at the top?
It would limit the important CSS to just a few lines:
.c-grid__picture {
vertical-align: baseline;
}
.c-grid__content {
vertical-align: top;
}
Here is an example in JSFiddle

I was able to achieve this setting the flex-basis of the .c-grid__content to 0.
.c-grid__content {
...
flex-basis: 0;
}
https://codepen.io/antibland/pen/WZrXpw?editors=1100

Related

Set equal height columns using flexbox

I know a solution to create equal height columns using display:table like:
.row {
display: table;
width: 100%;
}
.col{
display: table-cell;
}
but my case is a bit different, since I am using flexbox and row class has display:flex:
.row {
display: flex;
display: ms-flex;
flex-wrap: wrap;
}
and all cols have .large-4 class:
.large-4 {
width: 25%;
max-width: 25%;
flex: 0 0 30%;
}
I can't use flex:1 for .large-4 as well because it varies in different viewport.
here is a snippet of html:
<div class="row">
<div class="large-4">
<div class="card">
<img src="https://picsum.photos/200/200" alt="author">
<div class="card-content">
<h1 class="card-title">Title</h1>
<p class="grey-text mgb-05">2012-09-05, by Basir Payenda</p>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae quas eligendi id est iste
distinctio
optio vel aliquam provident, ipsa reprehenderit in corrupti quia ratione quisquam amet veniam totam
veritatis.
</p>
</div>
</div>
</div>
<div class="large-4">
<div class="card">
<img src="https://picsum.photos/200/200" alt="author">
<div class="card-content">
<h1 class="card-title">Title</h1>
<p class="grey-text mgb-0">2012-09-05, by Basir Payenda</p>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit.
</p>
</div>
</div>
</div>
<div class="large-4">
<div class="card">
<img src="https://picsum.photos/200/200" alt="author">
<div class="card-content">
<h1 class="card-title">Title</h1>
<p class="grey-text mgb-05">2012-09-05, by Basir Payenda</p>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae quas eligendi id est iste
distinctio.
</p>
</div>
</div>
</div>
</div>
code-pen link can be found here! how to I acheive equal height columns using flexbox? or any other better solution. thanks
You need to add display: flex to the .large-4 element:
.large-4 {
width: 25%;
max-width: 25%;
flex: 0 0 30%;
display: flex;
}
You'll notice when you inspect your elements using the inspector tool, large-4 elements are actually all the same height. It's the content inside that is not. So by making the parent element flex, it will make the children elements fill the space.
You already have equal-height columns, but inside them is a container that is contracting to its content. Expand that container.
.card {
height: 100%;
}

Can css be used to collapse whitespace around inline elements with varying line heights?

Suppose one is designing a box to frame some content, and wants that box to always have consistent space between its borders and text inside of it, regardless of the text's line-height. Is there a solution aside from custom negative margin on each box?
In theory this should actually be the "responsibility" of the content (in this case, the text), assuming our box is some kind of component allowing transclusion (e.g. web component slots), so I'd be especially interested in any way to style an inline element so that its line-height-generated top and bottom spaces collapse, regardless of line-height value (intentionally not calling them margins to not confuse them with the margin css property).
Here as an runnable example of the issue - the space between the magenta border and the inner text varies due to line height, and if the magenta border wasn't there, it would appear that each box has different padding.
This has probably been answered, but unfortunately since the terms are so generic it's hard to research (though I did try).
.foo {
max-width: 200px;
border: 2px solid blue;
padding: 20px;
line-height: 2;
display: inline-block;
vertical-align: top;
}
.foo>* {
border: 1px solid magenta;
}
.baz {
line-height: 1;
}
.bar {
line-height: 3;
}
<div class="foo">
<div>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Adipisci impedit porro fuga ab magnam.</div>
</div>
<div class="foo">
<div class="baz">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Adipisci impedit porro fuga ab magnam.</div>
</div>
<div class="foo">
<div class="bar">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Adipisci impedit porro fuga ab magnam.</div>
</div>
One idea that may solve half the issue is to change the line-height of the text to a smaller value than the container. Doing so, the height of the text will be smaller than the linebox and you can align it to the top. For this you need to consider an extra container.
.foo {
max-width: 200px;
border: 2px solid blue;
padding: 20px;
line-height: 2;
display: inline-block;
vertical-align: top;
}
.foo>* {
border: 1px solid magenta;
}
.baz {
line-height: 1;
}
.bar {
line-height: 3;
}
span {
line-height:1;
vertical-align:top;
}
<div class="foo">
<div><span>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Adipisci impedit porro fuga ab magnam.</span></div>
</div>
<div class="foo">
<div class="baz"><span>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Adipisci impedit porro fuga ab magnam.</span></div>
</div>
<div class="foo">
<div class="bar"><span>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Adipisci impedit porro fuga ab magnam.</span></div>
</div>
As you can see the text will always be aligned on the top whataver the line-height but the issue remains on the bottom. It's like we moved the issue to only one side.
Here is a related answer to better understand the alignment trick : https://stackoverflow.com/a/54190413/8620333

Make flex item take 100% width of new line

I have HTML structure like:
<div class="container">
<div class="btn-1"></div>
<div class="btn-2"></div>
<div class="btn-3"></div>
<div class="text">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. A veritatis harum illum assumenda odio ut, quos, ipsam molestias et sint nemo, saepe! Soluta a, quasi sequi, ut corrupti eius molestias.
</div>
</div>
btn-1 should be aligned to the top left, all other buttons (btn-2, btn-3...) should be aligned to the top right.
The text after all these buttons should be 100% width.
Quick mockup:
I figured out the first part (buttons) with:
.container {
display: flex;
justify-content: flex-end;
}
.btn-1 {
/* align first button to the left */
margin-right: auto;
}
Bu not matter what I do, the text doesn't flow to the next line...
Here's my JSFiddle https://jsfiddle.net/an0o7taq/
Thanks for any help!
You need to add flex-wrap: wrap to the container.
By default, flex containers are set to flex-wrap: nowrap, forcing items to remain on a single line.
revised jsfiddle
Spec reference:
5.2. Flex Line Wrapping: the flex-wrap property
You need more container with different flex flows and styles. Tip: learn most important flex props: align-items, flex-flow, justify-content. They all apply to the direct children of the container. So when you want your layout you need more container with different flex flows.
This guide helped me a lot. They also have great examples:
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
.container {
display: flex;
flex-flow: column nowrap;
}
.header {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
}
.header-left, .header-right {
display: flex;
flex-flow: row nowrap;
}
.btn {
width: 40px;
height: 40px;
border: 1px solid #ddd;
background-color: #eee;
}
.text {
width: 100%;
}
<div class="container">
<div class="header">
<div class="header-left">
<div class="btn">btn1</div>
</div>
<div class="header-right">
<div class="btn">btn2</div>
<div class="btn">btn3</div>
</div>
</div>
<div class="text">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. A veritatis harum illum assumenda odio ut, quos, ipsam molestias et sint nemo, saepe! Soluta a, quasi sequi, ut corrupti eius molestias.
</div>
</div>

Hover property not working for div from different containers

I have two different boxes when want to be able to change the properties of one box as I hover somewhere else.
I figured that if I have both boxes in the same container it works as you can see on my snippet here.
Here my html and css:
.first {
color: blue;
background: black;
width: 299px;
}
.first:hover + .second {
background: red;
color: white;
}
.second {
color: red;
background: black;
width: 300px;
margin-left: 10px;
}
.container {
display: flex;
}
<div class="container">
<div class="first">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nam delectus quo corporis, n
</div>
<div class="second">
Lorem ipsum dolor sit amet, consectetur adipisicing e et magnam rem, doloribus libero quas numquam esse in culpa!
</div>
</div>
But how can I do the same thing if the boxes are not in the same container?
Thanks in advance.
If you use display: inline-block you can remove the use of the container but because you are using display: flex on the container class you won't have the advantage of the child items (the first and second divs) stretching to fill the height of the container. You could use a fixed height to keep them at an equal height.
.first{
color: blue;
background: black;
width: 299px;
display: inline-block;
}
.first:hover + .second {
background: red;
color: white;
}
.second{
color: red;
display: inline-block;
background: black;
width: 300px;
margin-left: 10px;
}
<div class="first">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nam delectus quo corporis, n
</div>
<div class="second">
Lorem ipsum dolor sit amet, consectetur adipisicing e et magnam rem, doloribus libero quas numquam esse in culpa!
</div>
(post edited)
Use Jquery : Create a new class with a background color, it will be added with Jquery and removed when your mouse left the div.
Code : (don't forget to add jquery)
$('div.one').hover(function(){
$('div.two').toggleClass('three');
});
Check this :
https://jsfiddle.net/wnszbhj3/1/

Make HTML table-row snap to height of largest image in table-cell

In this fiddle: http://jsfiddle.net/tvqdrwp9/3/
I want the images (which could be any size), to stretch the height of all the adjacent table-cells to match. There will only be 2 rows, with 2 cells each. One cell contains an image, the other text. I want the text cells to match the height of the adjacent image. I have overflow:hidden on the cells, so image overflowing horizontally is not an issue.
The text in boxes 2 and 3 should be vertically aligned in the middle, and the rows should be dictated by the heights of the images in boxes (cells) 1 and 4.
I can't understand why I am still getting a red line at the bottom of each image.
.about-boxes {
display: table;
max-width: 600px;
}
.about-box-row {
display: table-row;
height: 100%;
}
.about-box {
display: table-cell;
vertical-align: middle;
width: 50%;
overflow: hidden;
}
.about-box img {
width: auto;
height: 100%;
}
.about-box-1,
.about-box-4 {
background: red;
}
.about-box-2,
.about-box-3 {
background: #CCC;
color: #000;
}
<div class="about-boxes">
<div class="about-box-row">
<div class="about-box about-box-1">
<img src="http://dummyimage.com/300x180/000/fff">
</div>
<div class="about-box about-box-2">
<h2>Text</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Perspiciatis velit repellat voluptate eum est re- iciendis eius recusandae molestiae iusto, dolor quis- quam voluptas.</p>
</div>
</div>
<div class="about-box-row">
<div class="about-box about-box-3">
<h2>Text</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisic- ing elit. Perspiciatis velit repellat voluptate eum est reiciendis eius recusandae molestiae iusto, dolor quisquam voluptas.</p>
</div>
<div class="about-box about-box-4">
<img src="http://dummyimage.com/320x360/000/fff">
</div>
</div>
</div>
You can either use display: block or vertical-align: middle on the image to correct the alignment of it.
.about-box img {
width: auto;
height: 100%;
display: block;
}
Or..
.about-box img {
width: auto;
height: 100%;
vertical-align: middle;
}
Both work.