Vertically align an image inside a div with responsive height

I have the following code which sets up a container which has a height that changes with the width when the browser is re-sized (to maintain a square aspect ratio).

HTML

<div class="responsive-container">
    <div class="dummy"></div>
    <div class="img-container">
        <IMG HERE>
    </div>
</div>

CSS

.responsive-container {
    position: relative;
    width: 100%;
    border: 1px solid black;
}

.dummy {
    padding-top: 100%; /* forces 1:1 aspect ratio */
}

.img-container {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
}

How can I vertically align the IMG inside the container? All my images have variable heights and the container can't have a fixed height/line height because it's responsive... Please help!


Here is a technique to align inline elements inside a parent, horizontally and vertically at the same time:

Vertical Alignment

1) In this approach, we create an inline-block (pseudo-)element as the first (or last) child of the parent, and set its height property to 100% to take all the height of its parent.

2) Also, adding vertical-align: middle keeps the inline(-block) elements at the middle of the line space. So, we add that CSS declaration to the first-child and our element (the image) both.

3) Finally, in order to remove the white space character between inline(-block) elements, we could set the font size of the parent to zero by font-size: 0; .

Note: I used Nicolas Gallagher's image replacement technique in the following.

What are the benefits?

  • The container (parent) can have dynamic dimensions.
  • There's no need to specify the dimensions of the image element explicitly.

  • We can easily use this approach to align a <div> element vertically as well; which may have a dynamic content (height and/or width). But note that you have to re-set the font-size property of the div to display the inside text. Online Demo .

  • <div class="container">
        <div id="element"> ... </div>
    </div>
    
    .container {
        height: 300px;
        text-align: center;  /* align the inline(-block) elements horizontally */
        font: 0/0 a;         /* remove the gap between inline(-block) elements */
    }
    
    .container:before {    /* create a full-height inline block pseudo=element */
        content: ' ';
        display: inline-block;
        vertical-align: middle;  /* vertical alignment of the inline element */
        height: 100%;
    }
    
    #element {
        display: inline-block;
        vertical-align: middle;  /* vertical alignment of the inline element */
        font: 16px/1 Arial sans-serif;        /* <-- reset the font property */
    }
    

    The output

    垂直对齐其容器中的元素

    Responsive Container

    This section is not going to answer the question as the OP already knows how to create a responsive container. However, I'll explain how it works.

    In order to make the height of a container element changes with its width (respecting the aspect ratio), we could use a percentage value for top/bottom padding property.

    A percentage value on top/bottom padding or margins is relative to the width of the containing block.

    For instance:

    .responsive-container {
      width: 60%;
    
      padding-top: 60%;    /* 1:1 Height is the same as the width */
      padding-top: 100%;   /* width:height = 60:100 or 3:5        */
      padding-top: 45%;    /* = 60% * 3/4 , width:height =  4:3   */
      padding-top: 33.75%; /* = 60% * 9/16, width:height = 16:9   */
    }
    

    Here is the Online Demo . Comment out the lines from the bottom and resize the panel to see the effect.

    Also, we could apply the padding property to a dummy child or :before / :after pseudo-element to achieve the same result. But note that in this case, the percentage value on padding is relative to the width of the .responsive-container itself.

    <div class="responsive-container">
      <div class="dummy"></div>
    </div>
    
    .responsive-container { width: 60%; }
    
    .responsive-container .dummy {
      padding-top: 100%;    /*  1:1 square */
      padding-top: 75%;     /*  w:h =  4:3 */
      padding-top: 56.25%;  /*  w:h = 16:9 */
    }
    

    Demo #1 .
    Demo #2 (Using :after pseudo-element)

    Adding the content

    Using padding-top property causes a huge space at the top or bottom of the content, inside the container.

    In order to fix that, we have wrap the content by a wrapper element, remove that element from document normal flow by using absolute positioning, and finally expand the wrapper (bu using top , right , bottom and left properties) to fill the entire space of its parent, the container.

    Here we go:

    .responsive-container {
      width: 60%;
      position: relative;
    }
    
    .responsive-container .wrapper {
      position: absolute;
      top: 0; right: 0; bottom: 0; left: 0;
    }
    

    Here is the Online Demo .


    Getting all together

    <div class="responsive-container">
      <div class="dummy"></div>
    
      <div class="img-container">
        <img src="http://placehold.it/150x150" alt="">
      </div>
    </div>
    
    .img-container {
      text-align:center; /* Align center inline elements */
      font: 0/0 a;       /* Hide the characters like spaces */
    }
    
    .img-container:before {
      content: ' ';
      display: inline-block;
      vertical-align: middle;
      height: 100%;
    }
    
    .img-container img {
      vertical-align: middle;
      display: inline-block;
    }
    

    Here is the WORKING DEMO .

    Obviously, you could avoid using ::before pseudo-element for browser compatibility , and create an element as the first child of the .img-container :

    <div class="img-container">
        <div class="centerer"></div>
        <img src="http://placehold.it/150x150" alt="">
    </div>
    
    .img-container .centerer {
      display: inline-block;
      vertical-align: middle;
      height: 100%;
    }
    

    UPDATED DEMO .

    Using max-* properties

    In order to keep the image inside of the box in lower width, you could set max-height and max-width property on the image:

    .img-container img {
        vertical-align: middle;
        display: inline-block;
        max-height: 100%;  /* <-- Set maximum height to 100% of its parent */
        max-width: 100%;   /* <-- Set maximum width to 100% of its parent */
    }
    

    Here is the UPDATED DEMO .


    With flexbox this is easy:

    FIDDLE

    Just add the following to the image container:

    .img-container {
        position: absolute;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        display: flex; /* add */
        justify-content: center; /* add to align horizontal */
        align-items: center; /* add to align vertical */
    }
    

    Use this css, as you already have the markup for it:

    .img-container {
        position: absolute;
        top: 50%;
        left: 50%;
    }
    
    .img-container > img {
      margin-top:-50%;
      margin-left:-50%;  
    }
    

    Here is a working JsBin: http://jsbin.com/ihilUnI/1/edit

    This solution only works for square images (because a percentage margin-top value depends on the width of the container, not the height). For random-size images, you can do the following:

    .img-container {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%); /* add browser-prefixes */
    }
    

    Working JsBin solution: http://jsbin.com/ihilUnI/2/edit

    链接地址: http://www.djcxy.com/p/41552.html

    上一篇: 如何将标签与CSS中“底部”对齐?

    下一篇: 将div内的图像与响应高度垂直对齐