NZJames
NZJames

Reputation: 5055

Flex layout and responsive design panels

I'm trying to design a re-usable component to display product information for web - which I've mocked up in fixed width divs but now need to make it responsive - I've been using flex layout.

Created a fiddle to demonstrate the problem

https://jsfiddle.net/0sz523Lj/5/

The component consists of an image for the entire container, then a left aligned opacity panel over part of the photo, which contains the product details. The main photo height should determine the height of the opacity panel as the main photo will stretch to fill 100% width, and obviously the height adjusts to keep the photo in proportion. Once the screen has been resized, the opacity panel should now take up the height of the photo and the content scaled to fit.

This panel consists of product name at the top, a blurb description, a thumbnail photo, price and a couple of buttons to find out more or buy.

All except the blurb are really fixed sizes - possibly the product name can be split over two lines or a single line but the blurb is the main thing. Currently if you make the screen bigger, then the main image gets larger, the opacity panel is fixed width and so only changes it's height, but you then end up with huge amounts of white space under the blurb as it's not enough to fill the opacity panel. If you shrink the screen, the blurb doesnt fit in the height of the container and the opacity container overflows over the picture height.

I'm wondering what the best way to do this responsively would be - only two thoughts come to mind. One is to change the font size based on screen size, so the blurb fits in the same fixed portion of the left hand container. This doesn't feel right. The only other option is to make the opacity panel itself change width depending on the screen size.

Effectively you want the code to fit in the title, thumbnail, cost and buy buttons, and then say based on how you resize your screen - which determines the height of the opacity panel, it then adjusts the width of the opacity panel to make the content fit perfectly.

How can I make this fully responsive?

HTML code for reference

<div class="image-container">
                <img src="https://images-na.ssl-images-amazon.com/images/I/71U%2B5KVElqL._SL1500_.jpg" width="100%" vspace="0" />
                <div class="image-buy-container-left">
                    <div class="image-container-title">
                        <p>Product name will go here</p>
                    </div>
                    <div class="image-container-blurb">
                        <p>Lorem ipsum lorem ipsum lorem ipsum lorem ipsum 
                        lorem ipsum lorem ipsum lorem ipsum lorem ipsum 
                        lorem ipsum lorem ipsum lorem ipsum lorem ipsum 
                        lorem ipsum lorem ipsum lorem ipsum lorem ipsum 
                            <br /><br />
                            lorem ipsum lorem ipsum lorem ipsum lorem ipsum 
                            lorem ipsum lorem ipsum lorem ipsum lorem ipsum 
                            lorem ipsum lorem ipsum lorem ipsum lorem ipsum 
                            lorem ipsum lorem ipsum lorem ipsum lorem ipsum 
                        </p>
                    </div>
                    <div class="image-container-thumbborder">
                        <div class="image-container-thumb">
                            <img src="https://us.coca-cola.com/content/dam/coke2016/page-properties-images/Coke_PageProperties.jpg" width=100% />
                        </div>
                    </div>
                    <div class="image-container-portion">
                        250ml bottle
                    </div>
                    <div class="image-container-portiondescription">
                        (Two serves)
                    </div>
                    <div class="image-container-price">
                        £13.00
                    </div>
                    <div class="image-buy-container-buttons">                        
                        <div class="image-container-button home-content__buttons ">
                            <a href="/ProductDetails.html" class="btn btn--stroke">
                                Discover
                            </a>
                        </div>
                    </div>
                </div>
            </div>

Upvotes: 2

Views: 498

Answers (1)

BugsArePeopleToo
BugsArePeopleToo

Reputation: 2996

I have changed the HTML by removing unnecessary divs, and making a few parts more semantic. I also removed absolute positioning and changed the main product image to a background on the main container. Now the left content can sit naturally in place.

One approach for total flexibility is to have the left container scroll any content that overflows when the screen is short. This is achieved with overflow-y: scroll.

Read the comments in the CSS that clarify what each line is doing. My answer runs well at most screen sizes but as with all things this flexible, adjustments will be needed at extreme screen sizes or aspect ratios.

* { box-sizing: border-box; } /* makes dealing with padding/width ez */
body { margin: 0; }

.image-container {
  display: flex;
  width: 100vw; /* fullscreen width */
  height: 100vh; /* fullscreen height */
  background-image: url('https://images-na.ssl-images-amazon.com/images/I/71U%2B5KVElqL._SL1500_.jpg'); /* main product image as a background */
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center center;
}

.image-buy-container-left {
  background: rgba(0,0,0,0.8);
  flex: 0 0 370px;
  display: flex;
  flex-direction: column;
  justify-content: space-between; /*helps when the screen gets taller than the content */
  padding: 20px; /* padding for the entire left container, no need for padding on every item inside */
  text-align: center; /* text align is inherited so only need it on the container, not on every item inside */
  overflow-y: auto; /* overflow if screen is shorter than content */
}

.image-container-title {
  margin: 0 0 1vw; /* margin based on screen width */
  font-size: 5vw; /* size based on the screen width gives a scalable font size */
  letter-spacing: .4vw; /* letter-spacing based on width */
  line-height: 1.125; /* always use realtive value for line-height if the size will change */
  color: #fff;
}

.image-container-blurb {
  color: #aaa;
  line-height: 1.2;
  font-size: 0.8rem;
}

.image-container-thumb {
  display: block;
  flex: 0 0 auto;
  margin: 2vw auto;
  width: 40%;
  height: auto;
}

.image-container-portion {
  color: #ccc;
  line-height: 1.3;
  font-size: 1.15rem;
}

.image-container-portiondescription {
  color: #aaa;
  line-height: 1.3;
  font-size: .9rem;
}

.image-container-price {
  color: #ddd;
  line-height: 1.3;
  font-size: 1.2rem;
  margin: 10px 0 20px;
}

.image-buy-container-buttons {
  width: 100%;
  display: flex;
  flex-direction: column;
}

.home-content__buttons .btn {
  border-color: #225;
  color: #ccc;
  background: #114 !important;
  margin: 0;
  height: 70px;
  line-height: 70px;
  vertical-align: middle;
  letter-spacing: .25rem;
  -webkit-transition: all 0.5s ease-in-out;
  transition: all 0.5s ease-in-out;
}

.home-content__buttons .btn:last-child {
  margin-right: 0;
}

.home-content__buttons .btn:hover,
.home-content__buttons .btn:focus {
  background: #ddd !important;
  border-color: #888;
  color: #333;
}

.btn,
button,
input[type="submit"],
input[type="reset"],
input[type="button"] {
  display: inline-block;
  font-family: "montserrat-medium", sans-serif;
  font-size: 1.2rem;
  text-transform: uppercase;
  letter-spacing: .3rem;
  height: 5.4rem;
  line-height: calc(5.4rem - .4rem);
  padding: 0 3rem;
  margin: 0 .3rem 1.2rem 0;
  color: #000000;
  text-decoration: none;
  text-align: center;
  white-space: nowrap;
  cursor: pointer;
  -webkit-transition: all 0.3s ease-in-out;
  transition: all 0.3s ease-in-out;
  background-color: #c5c5c5;
  border: .2rem solid #c5c5c5;
}

.btn:hover,
button:hover,
input[type="submit"]:hover,
input[type="reset"]:hover,
input[type="button"]:hover,
.btn:focus,
button:focus,
input[type="submit"]:focus,
input[type="reset"]:focus,
input[type="button"]:focus {
  background-color: #b8b8b8;
  border-color: #b8b8b8;
  color: #000000;
  outline: 0;
}


/* button primary
 * ------------------------------------------------- */

.btn.btn--primary,
button.btn--primary,
input[type="submit"].btn--primary,
input[type="reset"].btn--primary,
input[type="button"].btn--primary {
  background: #39b54a;
  border-color: #39b54a;
  color: #FFFFFF;
}

.btn.btn--primary:hover,
button.btn--primary:hover,
input[type="submit"].btn--primary:hover,
input[type="reset"].btn--primary:hover,
input[type="button"].btn--primary:hover,
.btn.btn--primary:focus,
button.btn--primary:focus,
input[type="submit"].btn--primary:focus,
input[type="reset"].btn--primary:focus,
input[type="button"].btn--primary:focus {
  background: #33a242;
  border-color: #33a242;
}


/* button modifiers
 * ------------------------------------------------- */

.btn.full-width,
button.full-width {
  width: 100%;
  margin-right: 0;
}

.btn--medium,
button.btn--medium {
  height: 5.7rem !important;
  line-height: calc(5.7rem - .4rem) !important;
}

.btn--large,
button.btn--large {
  height: 6rem !important;
  line-height: calc(6rem - .4rem) !important;
}

.btn--stroke,
button.btn--stroke {
  background: transparent !important;
  border: 0.2rem solid #39b54a;
  color: #39b54a;
}

.btn--stroke:hover,
button.btn--stroke:hover {
  border: 0.2rem solid #000000;
  color: #000000;
}

.btn--pill,
button.btn--pill {
  padding-left: 3rem !important;
  padding-right: 3rem !important;
  border-radius: 1000px !important;
}

button::-moz-focus-inner,
input::-moz-focus-inner {
  border: 0;
  padding: 0;
}
<div class="image-container">
  <div class="image-buy-container-left">
    <h2 class="image-container-title">
      Product name will go here
    </h2>
    <div class="image-container-blurb">
      <p>Lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum</p>
       <p>lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum
      </p>
    </div>
    <img class="image-container-thumb" src="https://us.coca-cola.com/content/dam/coke2016/page-properties-images/Coke_PageProperties.jpg" width=100% />
    <div class="image-container-portion">
      250ml bottle
    </div>
    <div class="image-container-portiondescription">
      (Two serves)
    </div>
    <div class="image-container-price">
      £13.00
    </div>
    <div class="image-buy-container-buttons image-container-button home-content__buttons">
        <a class="btn btn--stroke" href="/ProductDetails.html">
          Discover
        </a>
    </div>
  </div>
</div>

Upvotes: 1

Related Questions