Search code examples
htmlcssreactjsimagereact-bootstrap

3 background images, each taking 1/3 of banner, how to crop each's width responsively while fixing height


Sorry in advance if this is a silly question; I'm not too great with CSS.

I'm working on react-bootstrap code that defines an image banner with three images that each take up 1/3 of the width:

var bannerStyle = {
    backgroundImage: `url(${picture1}), url(${picture2}), url(${picture3})`,
    backgroundSize: "33.333333%",
    backgroundPosition: "top left, top center, top right",
};
return (
    <div className="inner-banner text-center" style={bannerStyle}>
        <div className="container">
            <div className="box"></div>
        </div>
    </div>
);

enter image description here

As you can see, the three display their full width, even if that results in their heights being mismatched and not taking up the full height of the banner. This effect becomes worse as the window is resized. I want to, instead, make these images all occupy the fixed height of the banner div, and maintain their 1/3 of backgroundSize by dynamically cropping their width - ideally while keeping them centred.

I've been looking around for how to do this, but can't find something that addresses this specific use case. Is there a way to accomplish this using the backgroundImage method or will I have to re-implement this?


Solution

  • Try using a grid. For it to work, you need to wrap the three images in a container, which would be your banner. This container than needs the following css:

    .banner-container {
      width: 100%;
      display: grid;
      grid-template-columns: 1fr 1fr 1fr;
      grid-template-rows: 1fr;
    }
    

    So you don't need the property backgroundSize anymore, as the grid-template-columns define that every child should get 1 fraction of the parents width. In your case 100 / 3 = 33,33.

    EDIT: Here is an example with jsx code. I put the pictures in an array (obviously, they're all null now, you have to replace picture with the real value) and map over it. Around all I wrap a container which acts as the parent and needs the grid styles:

    import React from "react";
    
    export default () => {
      const pictures = [picture1, picture2, picture3];
      const bannerContainer = {
        width: "100%",
        display: "grid",
        gridTemplateColumns: "1fr 1fr 1fr",
        gridTemplateRows: "1fr"
      };
    
      return (
        <div className="banner-container" style={bannerContainer}>
          {pictures.map(picture => (
            <div
              className="inner-banner text-center"
              style={{
                backgroundImage: `url(${picture})`,
                backgroundPosition: "top left, top center, top right"
              }}>
              <div className="container">
                <div className="box"></div>
              </div>
            </div>
          ))}
        </div>
      );
    };
    

    I created this pen for you to play around.