get image and caption into one flex item? - css

AI want to put an image and its caption into one flex-item and have several such flex-items in one flex-container. I want the image to be above its caption. But what happens is that each caption is beside its image. How do I get them one above the other?
I tried putting the captions into another flex-container below the images. But when the screen size is less wide, the images stack, then the captions stack instead of being image, then its caption, image, then its caption.
<div class="flex-item-popup" id="popup">
<div class="close"><i class="fa fa-2x fa-times-circle"></i></div>
<h2></h2>
<div class='text'></div>
<div class="videos"></div>
<div class="flex-container images"></div>
<div class="flex-container captions"></div>
</div>
css:
#popup {
width: 90%;
height: auto;
padding: 20px;
border-radius: 10px;
background-color: black;
color: white;
}
#popup .close {
/*position: absolute;
right: 10px;
top: 10px;*/
float: right;
color: white;
opacity: 1;
}
#popup .close:hover {
opacity: .7 !important;
}
.images, .captions {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
align-content: flex-start;
align-items: flex-start;
}
.images {
margin-top: 20px;
}
.images .flex-item, .captions .flex-item {
display: flex;
flex-grow: 0;
flex-shrink: 0;
flex-basis: 300px;
}

Look into <figure> and <figcaption> HTML5 tags. I am pretty certain that is going to help you and it is what you are looking for.
Here is updated fiddle link.
And the SO code snippet here...
.flex-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-content: flex-start;
align-items: center;
}
.flex-item {
/*width: 350px;
height: null;*/
flex-grow: 1;
flex-shrink: 0;
flex-basis: 200px;
justify-content: flex-start;
display: flex;
padding-left: 20px;
}
.flex-item img {
cursor: pointer;
}
<div class="flex-container images">
<div class="flex-item">
<figure>
<img src="http://newsinteractive.post-gazette.com/hbcu/morehouse/img/grads.jpg" />
<!--<div style="clear: both;"></div>-->
<figcaption>Our grads.</figcaption>
</figure>
</div>
<div class="flex-item">
<figure>
<img src="http://newsinteractive.post-gazette.com/hbcu/morehouse/img/building.jpg" />
<figcaption>A building</figcaption>
</figure>
</div>
<div class="flex-item">
<figure>
<img src="http://newsinteractive.post-gazette.com/hbcu/morehouse/img/campus.jpg" />
<figcaption>The campus.</figcaption>
</figure>
</div>
<div class="flex-item">
<figure>
<img src="http://newsinteractive.post-gazette.com/hbcu/morehouse/img/trio.jpg" />
<figcaption>Three people</figcaption>
</figure>
</div>
</div>
Hope this helps

Related

CSS image as large as possible within square with caption no gap

I'm 99% sure about this but thought i'd ask to see if anyone knew of any clever solutions.
Basically I wish to place an image in a 1/1 aspect containing element, and then for that image to be as as as it possibly can be, eg, landscape images always touch the left and right sides and portrait ones touch the top and bottom.
I then want a line of caption text underneath the image.
My question is, is there any way to get that size of image but without (for landscape images) the large gap between the photo and the caption?
My example image below shows the problem (please note the image is not full left to right edge here like I want).
Anyone know of any clever options to achieve this?
<figure class="photo-1 landscape">
<div class="image-wrapper gallery">
<a href="https://farm66.staticflickr.com/65535/48808899778_bb1d4d1272_b.jpg" data-pswp-width="4032" data-pswp-height="3024" target="_blank">
<img src="https://farm66.staticflickr.com/65535/48808899778_bb1d4d1272_m.jpg">
</a>
</div>
<figcaption>Hersheypark</figcaption>
</figure>
figure {
display: flex;
flex-direction: column;
gap: 0.5rem;
.image-wrapper {
aspect-ratio: 1/1;
}
a {
display: block;
}
img {
display: block;
max-width: 100%;
max-height: 100%;
}
&.landscape {
a {
min-width: 100%;
}
img {
width: 100%;
}
}
&.portrait {
a {
min-height: 100%;
}
img {
height: 100%;
}
}
figcaption {
text-align: center;
color: hsl(var(--color-secondary));
font-size: var(--fs--1);
}
}
This is what I got so far.
body {
background-color: #F8F9F9;
}
.container {
display: flex;
gap: 20px;
}
.card {
display: flex;
flex-direction: column;
flex-basis: 0;
flex-grow: 1;
gap: 10px;
}
.image {
display: flex;
align-items: center;
background-color: #ffffff;
overflow: hidden;
}
.image.hor {
flex-direction: row;
}
.image.ver {
flex-direction: column;
aspect-ratio: 1/1;
}
.image img {
flex-grow: 1;
max-width: 100%;
max-height: 100%;
}
.caption {
padding: 5px 10px;
font-size: 14px;
text-align: center;
background-color: #ffffff;
}
<div class="container">
<div class="card">
<div class="image hor">
<img src="https://dummyimage.com/100x50/000/fff" />
</div>
<div class="caption">
Landscape image (small)
</div>
</div>
<div class="card">
<div class="image hor">
<img src="https://dummyimage.com/1000x500/000/fff" />
</div>
<div class="caption">
Landscape image (large)
</div>
</div>
<div class="card">
<div class="image ver">
<img src="https://dummyimage.com/50x100/000/fff" />
</div>
<div class="caption">
Portrait image (small)
</div>
</div>
<div class="card">
<div class="image ver">
<img src="https://dummyimage.com/500x1000/000/fff" />
</div>
<div class="caption">
Portrait image (large)
</div>
</div>
</div>

how avoid figcaption wrapping with media query

i'm working now with media query and once i reach the breakpoint of 768px the text goes
all below the images, not following them.
I would like the text to follow the images and to be under each one once it reach the 768px breakpoint.
any suggestion to avoid this problem?
thanks.
img {
width: 100%;
height: 100%;
object-fit: contain;
}
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
margin-top: 200px;
grid-gap: 20px;
justify-content: center;
align-content: center;
}
#media (max-width: 768px) {
/* navbar */
* {
margin: 0;
box-sizing: border-box;
}
.nav-links, .search{
display: none;
}
.logo {
height: 64px;
width: 126px;
filter: invert(100%);
padding: 1px;
}
/* contenuto1 */
.grid {
display: flex;
flex-wrap: wrap;
margin-top: 100px;
grid-gap: 150px;
}
<div class="titolo-grid">
<h2>In evidenza</h2>
</div>
<div class="grid-container">
<div class="grid">
<img src="1w.webp" class="img"/>
<img src="2w.webp" class="img"/>
<img src="3w.webp" class="img"/>
<figcaption class="caption">I riflessi fluidi dell'autunno</figcaption>
<figcaption class="caption">Maglieria</figcaption>
<figcaption class="caption">Scarpe Made In Italy</figcaption>
</div>
</div>
I suggest you do not use a grid unless you know how to manipulate it. I suggest you use display flex because it's easier to manipulate and more simple.
and to put text under each image, you must understand the importance of HTML structure for that. so put each image with its text in a container, then style them according to that.
I used display flex here:
img {
width: 100%;
min-width: 300px;
height: 100%;
object-fit: contain;
}
.grid {
display: flex;
/* grid-template-columns: repeat(3, 1fr); */
margin-top: 200px;
grid-gap: 20px;
justify-content: center;
align-content: center;
flex-direction: row;
}
.container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
#media only screen and (max-width: 768px) {
/* navbar */
* {
margin: 0;
box-sizing: border-box;
}
.nav-links, .search{
display: none;
}
.logo {
height: 64px;
width: 126px;
filter: invert(100%);
padding: 1px;
}
.grid {
flex-direction: column;
}
img {
width: 80%;
min-width: 200px;
}
/* contenuto1 */
/* .grid {
display: flex;
flex-wrap: wrap;
margin-top: 100px;
grid-gap: 150px;
} */
}
<div class="titolo-grid">
<h2>In evidenza</h2>
</div>
<div class="grid-container">
<div class="grid">
<div class="img1 container" >
<img src="1w.webp" class="img"/>
<figcaption class="caption">I riflessi fluidi dell'autunno</figcaption>
</div>
<div class="img2 container" >
<img src="2w.webp" class="img"/>
<figcaption class="caption">Maglieria</figcaption>
</div>
<div class="img3 container" >
<img src="3w.webp" class="img"/>
<figcaption class="caption">Scarpe Made In Italy</figcaption>
</div>
</div>
</div>
Put <img> and <figcaption> inside <figure>:
<figure>
<img src="1w.webp" class="img"/>
<figcaption class="caption">I riflessi fluidi dell'autunno</figcaption>
</figure>
<figure>
<img src="2w.webp" class="img"/>
<figcaption class="caption">Maglieria</figcaption>
</figure>
Try this:
.grid-container {
display: flex;
flex-wrap: wrap;
flex-direction:row;
margin-top: 100px;
}
img {
width: 100%;
object-fit: contain;
}
.grid{
width:31%;
margin:1%;
}
#media (max-width: 768px) {
/* navbar */
* {
margin: 0;
box-sizing: border-box;
}
.nav-links, .search{
display: none;
}
.logo {
height: 64px;
width: 126px;
filter: invert(100%);
padding: 1px;
}
.grid{
width:100%;
}
.caption{
margin:10px auto 25px;
}
}
<div class="titolo-grid">
<h2>In evidenza</h2>
</div>
<div class="grid-container">
<div class="grid">
<img src="1w.webp" class="img"/>
<figcaption class="caption">I riflessi fluidi dell'autunno</figcaption>
</div>
<div class="grid">
<img src="2w.webp" class="img"/>
<figcaption class="caption">Maglieria</figcaption>
</div>
<div class="grid">
<img src="3w.webp" class="img"/>
<figcaption class="caption">Scarpe Made In Italy</figcaption>
</div>
</div>
you need to put img and figcaption inside the grid element and use Flex instead of Grid some codes:

kepp text in the middle and position 3 images in the middle with text below it

I am trying to position a text in the middle while having 3 images in a row with text below each other and the last text and image next to each other as shown below. I have been trying to use flexbox. If someone can be kind enough to help I would appreciate it. thank you the design and code are at the bottom.
here is my code
<div class="wrapper">
<div class="title">
<h2>Become a Pro with our camp</h2>
</div>
<section>
<img src="img/diet-icon.png" alt="diet">
<h2>Diet</h2>
<p>Eat what the pros eat.</p>
</section>
<section>
<img src="img/training.png" alt="workout">
<h2>Workout</h2>
<p>Workout how the pros do.</p>
</section>
<section>
<img src="img/basketball-training.jpg" alt="basketball training">
<h2>Basketball Training</h2>
<p>Train like how the pros train.</p>
</section>
<section class="section-champ">
<h2>The beginning towards winning the championship starts here</h2>
<img src="img/championship-img.jpg" alt="championship" class="champ">
</section>
</div>
.wrapper {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
flex-wrap: wrap;
}
.wrapper div h2 {
text-align: center;
font-weight: bold;
font-family: sans-serif;
margin-top: 13px;
padding-bottom: 20px;
width: 100%;
}
.wrapper section {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin-bottom: 25px;
}
.wrapper section img {
width: 50px;
}
.wrapper .section h2 {
text-align: center;
font-family: sans-serif;
}
.wrapper section .champ {
width: 300px;
}
This should get you there. That is if I am understanding the question correctly. Codepen example https://codepen.io/nickberens360/pen/RwxLKMd
<div class="wrapper">
<div class="title">
<h2>Become a Pro with our camp</h2>
</div>
<div class="stuff">
<section class="icon-group">
<img src="img/diet-icon.png" alt="diet">
<h2>Diet</h2>
<p>Eat what the pros eat.</p>
</section>
<section class="icon-group">
<img src="img/training.png" alt="workout">
<h2>Workout</h2>
<p>Workout how the pros do.</p>
</section>
<section class="icon-group">
<img src="img/basketball-training.jpg" alt="basketball training">
<h2>Basketball Training</h2>
<p>Train like how the pros train.</p>
</section>
</div>
<section class="section-champ stuff">
<h2>The beginning towards winning the championship starts here</h2>
<img src="img/championship-img.jpg" alt="championship" class="champ">
</section>
</div>
<style>
.wrapper {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
flex-wrap: wrap;
}
.stuff {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.icon-group {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
flex-wrap: wrap;
padding: 0 12px;
border: 1px solid red
}
</style>
[1]: https://codepen.io/nickberens360/pen/RwxLKMd
You need to wrap your images/titles sections in a div with flex box.
Below is an example of how the markup and css would look.
HTML:
<div class="wrapper">
<h1>Become a pro at our camp</h1>
<div class="img-wrapper">
<div class="img 1">
<img src="./food.png"/>
<h5>Diet</h5>
<p>Eat what the pros eat</p>
</div>
<div class="img 2">
<img src="./dumbbell.png"/>
<h5>Workout</h5>
<p>Workout how the pros do.</p>
</div>
<div class="img 3">
<img src="./basketball.png"/>
<h5>Basketball Training</h5>
<p>Train like the pros train.</p>
</div>
</div>
</div>
CSS:
* {
padding: 0;
margin: 0;
}
.wrapper {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-family: 'Helvetica';
}
.img-wrapper {
margin-top: 2vw;
width: 100%;
display: flex;
justify-content: center;
gap: 2vw;
}
ion-icon {
font-size: 5vw;
}
h5 {
font-size: 1vw;
}
.img {
display: flex;
flex-direction: column;
align-items: center;
gap: .5vw;
}
You can find a codepen example of this working here

Scale images inside divs with text

For a personal project with Angular, Angular Material and Flex-Layout I am trying to achieve a similar layout used by Bring! App:
Having images of different size (not all squared) I would like to center them proportionally and allow some text under them.
I have the following template and scss styles:
<div fxLayout="row" fxLayoutGap="5px" class="cards-container">
<div class="item-card">
<div class="image">
<img src="../../../../assets/icons/apple.png" alt="Mela" />
</div>
<span class="item-name">Mela</span>
<span class="description">12</span>
</div>
<div class="item-card">
<div class="image">
<img src="../../../../assets/icons/milk.png" alt="Latte" />
</div>
<span class="item-name">Latte</span>
<span class="description">1 description comes here, must be hidden if long text</span>
</div>
</div>
//---------------------------------------------------
.cards-container {
flex-wrap: wrap;
.item-card {
display: flex;
flex-direction: column;
justify-items: end;
color: white;
width: 7em;
height: 7em;
text-align: center;
background-color: darkslategray;
margin: 5px 0;
img {
width: 40%; // TODO: how to scale?
height: 40%;
}
.text-container {
display: flex;
flex-direction: column;
.item-name {
display: inline-block;
font-size: 1.1em;
}
.description {
width: 99%;
font-size: 0.8em;
text-align: center;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
display: inline-block;
}
}
}
}
However the images do not scale down to keep the proportions with the others images, especially if narrow and long.
It all seems to look fine but it looks like your HTML code is missing the .text-container div and class.
<div class="item-card">
<div class="image">
<img src="../../../../assets/icons/apple.png" alt="Mela" />
</div>
<span class="item-name">Mela</span>
<span class="description">12</span>
</div>
should be
<div class="item-card">
<div class="image">
<img src="../../../../assets/icons/apple.png" alt="Mela" />
</div>
<div class="text-container">
<span class="item-name">Mela</span>
<span class="description">12</span>
</div>
</div>
Now for the text-overflow: ellipsis; this doesn't work on multi-lines unless you implement some JavaScript or something.
If there is any change to your code, I'd make the images a background-image instead. There could be other ways without this, but it's what I use to make sure the container is responsive with the image always responsive and centred.
For Example: https://codepen.io/StudioKonKon/pen/wRjOzr (Includes SCSS)
.image {
background-position: center center;
background-size: contain;
background-repeat: no-repeat;
font-size: 0;
}
.image-mela {
background-image: url("https://via.placeholder.com/150x175");
}
.image-latte {
background-image: url("https://via.placeholder.com/200x50");
}
.image-long {
background-image: url("https://via.placeholder.com/50x100");
}
.cards-container {
width: 100%;
margin: auto;
display: flex;
flex-wrap: wrap;
}
.cards-container .item-card {
display: flex;
flex-direction: column;
justify-items: end;
color: white;
width: 7em;
height: 7em;
text-align: center;
background-color: darkslategray;
margin: 5px;
padding: 0.5em;
box-sizing: border-box;
overflow: hidden;
}
.cards-container .item-card .image {
display: block;
margin: auto;
width: 40%;
height: 40%;
}
.cards-container .item-card .text-container {
display: flex;
flex-direction: column;
}
.cards-container .item-card .text-container .item-name {
display: inline-block;
font-size: 1.1em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.cards-container .item-card .text-container .description {
font-size: 0.8em;
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
}
<div fxLayout="row" fxLayoutGap="5px" class="cards-container">
<div class="item-card">
<div class="image image-mela">Mela</div>
<div class="text-container">
<span class="item-name">Mela</span>
<span class="description">12</span>
</div>
</div>
<div class="item-card">
<div class="image image-latte">Latte</div>
<div class="text-container">
<span class="item-name">Latte</span>
<span class="description">1 description comes here, must be hidden if long text</span>
</div>
</div>
<div class="item-card">
<div class="image image-long">Long Image</div>
<div class="text-container">
<span class="item-name">Long Image Text</span>
<span class="description">must be hidden if long text</span>
</div>
</div>
</div>
Have you tried:
img {
width: 40%;
height: auto;
}
It should leave the image proportions consistent.
It is simple. I think it will solve the problem. :)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>item</title>
<style type="text/css" media="screen">
.item-single{
width: 100px;
background-color: #e7e7e7;
height: 100px;
text-align: center;
}
.item-single span{
display: block;
border: 1px solid #000; /* just to show the alignment */
}
.item-single img{
width: 50%; /* you can scale it down using width */
border:1px solid #000; /* just to show the alignment */
display: block;
margin: auto;
}
</style>
</head>
<body>
<div class="item-single">
<img src="http://sugamparajuli.com.np/wp-content/uploads/2019/01/banana.png">
<span class="item-name">Mela</span>
<span class="description">12</span>
</div>
</body>
</html>
This is the result.
item-image

align-content: center not working in Chrome

I am trying to vertically align divs with flexbox, by using the align-content: center. It works fine in Firefox and IE, but it does not vertically align in Chrome. In Chrome the divs stays on top.
<div class="products-wrapper">
<div class="product">
<img src="images/temporary.jpg" alt="Temporary">
<h3>Title</h3>
<p>Text.</p>
</div>
<div class="product">
<img src="images/temporary.jpg" alt="Temporary">
<h3>Title</h3>
<p>Text.</p>
</div>
<div class="product">
<img src="images/temporary.jpg" alt="Temporary">
<h3>Title</h3>
<p>Text.</p>
</div>
</div>
And CSS:
.products-wrapper {
width: 100%;
min-height: 100vh;
/* FLEX */
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-content: center;
}
.product {
max-width: 250px;
padding: 10px;
}
.product img {
display: block;
margin: 0 auto;
max-height: 250px;
max-width: 250px;
}
I have also been trying align-items: center; which centers the divs vertically, but it will not be a straight line with the images and text if I have different amount of text for example.
Anyone with a solution how to vertically center divs (straight), which works in all browsers?
Image example:
Edit: If you don't need the height to be dynamic, align-items: center; will work with (for example) max-height: 400px; on the .product div. Not really what I wanted though.
In order to achieve what you want you'll need to use align-items: flex-start, this way all items will be aligned to the top of their line. And to center vertically you're looking for the align-items: center property which aligns the items in the flex container along the cross axis, which in your case you'll have to use in an outer wrapper to make sure the products div is centered in the page.
The align-content: center property comes into play only when there is more than one line (wrapped content).
A better explanation about the difference between those two properties is in the answer to this stackoverflow question
.outer-wrapper {
width: 100%;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.products-wrapper {
width: 100%;
/* FLEX */
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
background-color: gray;
align-items: flex-start;
}
.product {
max-width: 250px;
padding: 10px;
background-color: red;
margin: 5px;
}
.product img {
display: block;
margin: 0 auto;
max-height: 250px;
max-width: 250px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div class="outer-wrapper">
<div class="products-wrapper">
<div class="product">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/7/71/St._Bernard_puppy.jpg/120px-St._Bernard_puppy.jpg" alt="Temporary">
<h3>Title</h3>
<p>Text.</p>
</div>
<div class="product">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/7/71/St._Bernard_puppy.jpg/120px-St._Bernard_puppy.jpg" alt="Temporary">
<h3>Title</h3>
<p>Text.</p>
</div>
<div class="product">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/7/71/St._Bernard_puppy.jpg/120px-St._Bernard_puppy.jpg" alt="Temporary">
<h3>Title</h3>
<p>Text.</p>
</div>
</div>
</div>
</body>
</html>
Make the .product element, flex container. This so you can align the content inside them.
.product {
max-width: 250px;
padding: 10px;
display: flex;
justify-content: center;
flex-direction: column;
}
Hope this helps :)
.products-wrapper {
width: 100%;
min-height: 100vh;
/* FLEX */
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-content: center;
}
.product {
max-width: 250px;
padding: 10px;
display: flex;
justify-content: center;
flex-direction: column;
}
.product img {
display: block;
margin: 0 auto;
max-height: 250px;
max-width: 250px;
}
<div class="products-wrapper">
<div class="product">
<img src="images/temporary.jpg" alt="Temporary">
<h3>Title</h3>
<p>Text.</p>
</div>
<div class="product">
<img src="images/temporary.jpg" alt="Temporary">
<h3>Title</h3>
<p>Text.</p>
</div>
<div class="product">
<img src="images/temporary.jpg" alt="Temporary">
<h3>Title</h3>
<p>Text.</p>
</div>
</div>

Resources