1

I have a parent with a width of 'col-9'. I have two images that can have different height and widths. How can I get the images to fill the width of the parent and have equal heights? The height of the images should determine height of parent.

I have used Flex and figured out the aspect ratio (its width divided by its height) but was hoping for a more simpler way as the images constantly change..

I am using Bootstrap 4.

enter image description here

EDIT

This is what I have that works but I want to not have to work out the aspect ratio for flex every time.

<div class="col-9">
    <div class="d-flex w-100">
        <img src="https://via.placeholder.com/400x600" alt="" class="" style="flex:.666667;">
        <img src="https://via.placeholder.com/300x600" alt="" class="" style="flex:.5;">
    </div>
</div>
col_hol
  • 25
  • 6

3 Answers3

0
<div class="col-md-9">
    <div class="image-wrapper" style="display: flex;">
        <img src="https://via.placeholder.com/400x600" alt="" style="margin-right: 10px;">
        <img src="https://via.placeholder.com/300x600" alt="">
    </div>
</div>
Razu Ahmed
  • 128
  • 4
  • 1
    The parent needs to have a flexible height. Width is always 9 columns. I need all of the image to show, no clipping. – col_hol Mar 19 '20 at 04:21
  • This answer could be improved by adding some explanation of what you did and why it worked. – Sean Mar 19 '20 at 20:50
0

I prefer to use flexbox in this cases.

You can do it like this:

.parent {
  display: flex;
  flex-flow: row;
}
.child {
  background: #ddd;
}
.child img {
  width: 100%;
  height: 100%;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"/>

<div class="col-9">
  <div class="parent">
    <div class="child">
      <img src="https://cdn.pixabay.com/photo/2014/06/03/19/38/board-361516_1280.jpg"/>
    </div>
    <div class="child">
      <img src="https://cdn.pixabay.com/photo/2016/09/04/11/51/checklist-1643781_1280.png"/>
    </div>
  </div>
</div>
S J
  • 440
  • 3
  • 12
0

I had to solve the same task. I had to place several images with different aspect ratios to fullfill the thole width of the page (or container). And I want them all to have the same height: enter image description here

TL;TR

I found 2 pure CSS solutions for this task:

  1. Based on padding and margin properties behaviour for making a constant aspect ratio of elements Source: https://wellcaffeinated.net/articles/2012/12/10/very-simple-css-only-proportional-resizing-of-elements

Define the width of an element as a percentage (eg: 100%) of the parent’s width, then define the element’s padding-top (or -bottom) as a percentage so that the height is the aspect ratio you need.

  1. Using flexbox for responsive equal height images preserving aspect ratio of images Source: https://codepen.io/blimpage/pen/obWdgp

Set the flex property of each image's wrapper div to the image's aspect ratio (its width divided by its height)

Both solutins assume you need to know the sizes of images to build proper CSS. You can use server side scripts, e.g. PHP for this. There are functions or libraries for this. E.g., there is a getimagesize() function for PHP. (See https://www.php.net/manual/ru/function.getimagesize.php) If need to place only several images, you can look up there sizes and hardcode it to the PHP script, that outputs the resulting HTML. I will use this method for simplicity. Another approach is to use calc() function in CSS.


Details

Solution 1. A pure CSS with padding attribute Some explanations below. Variables description:

  • W - is a page/container width.
  • H - is a block with images width. It's the same for any image.
  • w0[i], h0[i] - is an original size of an i-th image.
  • w[i], h[i] - is dispayed size of an i-th image.
  • h[i]=H

Let's calculate ratios

W=SUM(w[i]), as images fullfill the width.

Let's divide it by H=h[i]: W/H=SUM(w[i]/h[i])

Let's calculate an aspect ratio for an i-the image r[i]=w[i]/h[i]=w0[i]/h0[i], as it has to be a constant for that image

So we get W/H=SUM(r[i]) or H=W/SUM(r[i])

It's an aspect ratio for the whole container: R=W/H=SUM(r[i])

So we can get H=W/R

An example of PHP code:

<?php
//Image sizes
$arImages = [
    ['NAME' => '11.png', 'W' => 1000, 'H' => 1000],
    ['NAME' => '12.png', 'W' => 1000, 'H' => 2000],
    ['NAME' => '21.png', 'W' => 2000, 'H' => 1000],
];

?>
<!DOCTYPE html>
<html>

<head>

    <?php
    $r = 0;
    //Loop through all images
    foreach ($arImages as $image) {
        $w = $image['W'];
        $h = $image['H'];
        $r += $w / $h;
    } ///Loop through all images
    //The band height as a percentage of the window width
    $hBand = (1 / $r) * 100;
    ?>


    <style>
        .page {
            width: 100%;
        }

        .sh-band {
            border: 1px solid blue;
            padding: 0;
        }

        .sh-band-resizer {
            width: 100%;
            padding-top: <?= $hBand ?>%;
            position: relative;
        }

        .sh-element {
            position: absolute;
            top: 0;
            left: 0;
            bottom: 0;
            right: 0;
        }

        .sh-element img {
            width: auto;
            height: 100%;
        }
    </style>
</head>

<body>
    <div class="page">
        <?
        /**
         * Proportional scaling with padding-top CSS
         */
        ?>
        <div class="sh-band" style="">
            <div class="sh-band-resizer">
                <div class="sh-element"><?php
                    //Loop through all images
                    foreach ($arImages as $image) {
                        ?><img src="/sh-gallery/images/<?= $image['NAME'] ?>"><?php
                    } // /Loop through all images
              ?></div>
            </div>
        </div>
    </div>
</body>

</html>

HTML + CSS, produced by this code for sample images from the @s-j answer:

<html><head>
    <style>
        .page {
            width: 100%;
        }

        .sh-band {
            border: 1px solid blue;
            padding: 0;
        }

        .sh-band-resizer {
            width: 100%;
            padding-top: 48.191461696405%;
            position: relative;
        }

        .sh-element {
            position: absolute;
            top: 0;
            left: 0;
            bottom: 0;
            right: 0;
        }

        .sh-element img {
            width: auto;
            height: 100%;
        }
    </style>
</head>

<body>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"/>

<div class="col-9">
    <div class="page">
        <div class="sh-band" style="">
            <div class="sh-band-resizer">
                <div class="sh-element"><img src="https://i.stack.imgur.com/tDEmT.jpg"><img src="https://i.stack.imgur.com/WSp0o.jpg"></div>
            </div>
        </div>
    </div>
</div>
    
</body></html>

Solution 2. A flexbox variant You still need to know image sizes on the server side for building inline CSS. The key idea is to set the flex property of each image's wrapper div to the image's aspect ratio, i.e its width divided by its height. If you specify only 1 parameter to flex propery, is interpreted as flex: 1 0; (See https://developer.mozilla.org/en-US/docs/Web/CSS/flex ) So the flex-grow wil be set to image's aspect, flex-shrink to 1, flex-basis to 0; (See The difference between flex-basis auto and 0 (zero) about "zero" flex-basis) At first it shrinks images to minimal size (zero) and then stretches their width according to their aspect ratios to fulfil the full flex container width.

Explanations. Variables description:

  • W - is a page/container width.
  • H - is a block with images width. It's the same for any image.
  • w0[i], h0[i] - is an original size of an i-th image.
  • w[i], h[i] - is displayed size of an i-th image.
  • r[i]=w0[i]/h0[i]=w[i]/h[i] - an image's aspect ratio
  • h[i]=H - images has to be with the same height

To determine actual width of the certain image we have to sum all the flex-grow factors.

R=SUM(r[i])

Then we can calculate an individual width and using constant aspect ratio we get w[i]=r[i]*W/R=(w[i]/h[i])*W/R

Thus h[i]=W/R

We can see that h[i] is constant for all the images, depends only on W/R. Additionally we are using images aspect ratio saving by setting to auto the img height property.

(See https://css-tricks.com/flex-grow-is-weird/ )

A PHP sample:

<?php
//Image sizes
$arImages = [

    ['NAME' => '11.png', 'W' => 1000, 'H' => 1000],
    ['NAME' => '12.png', 'W' => 1000, 'H' => 2000],
    ['NAME' => '21.png', 'W' => 2000, 'H' => 1000],    
];
?>
<!DOCTYPE html>
<html>

<head>
    <style>
        .page {
            width: 100%;
        }

        .sh-band {
            border: 1px solid blue;
            display: flex;
        }

        .sh-element img {
            width: 100%;
            height: auto;
            vertical-align: middle;
        }
    </style>
</head>

<body>
    <div class="page">
        <?
        /**
         * Proportional scaling with flex
         */
        ?>
        <div class="sh-band">
            <?php
            //Loop through all images
            foreach ($arImages as $image) {
            ?>
                <div class="sh-element" style="flex: <?= $image['W'] / $image['H'] ?>">
                    <img src="/sh-gallery/images/<?= $image['NAME'] ?>">
                </div>
            <?php
            } // /Loop through all images
            ?>
        </div>
    </div>
</body>

</html>

A Bootstrap result code:

        .page {
            width: 100%;
        }

        .sh-band {
            border: 1px solid blue;
            display: flex;
        }

        .sh-element img {
            width: 100%;
            height: auto;
            vertical-align: middle;
        }
<html>
<head>
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"/>
</head>


<body>

<div class="col-9">
    <div class="page">
        <div class="sh-band">
            <div class="sh-element" style="flex: 1.319587628866">
                <img src="https://i.stack.imgur.com/tDEmT.jpg">
            </div>
            <div class="sh-element" style="flex: 0.75546875">
                <img src="https://i.stack.imgur.com/WSp0o.jpg">
            </div>
        </div>      
    </div>

</div>
    
</body>
</html>
Sergey Beloglazov
  • 342
  • 1
  • 3
  • 14