Search code examples
htmlcss

Make div's sizing behave as image


How can I make a div's sizing properties behave exactly like they do for image tags, if the div's background is an image?

The idea is to duplicate the way an image tag behaves in this code snippet:

div{
  background-color: #2DBCFF;
  text-align:center;
  box-sizing: border-box;
  font-size:0;
}
img{
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  vertical-align: middle;
}
<div style="width:300px; height: 150px; line-height: 150px;"><!-- <<<CSS props controlled
 and changed with JS

--><img src="https://i.sstatic.net/o23xS.jpg"><!--

--></div>


NOTE :

the div's height and width properties are changed with JS

FOR CLARITY :

I want the CSS properties width, height, max-width, and max-height properties behave the same as if the div tag was an image tag. (aspect ratio preserved, size of div is based on image, etc...)


Solution

  • There was a lot of modification done to this faux img (.imgDiv), the reason why it's harder than it should be is because img is a replaced element and div is not, this article will explain the differences (author's second language is English, but the grammatical errors do not hinder comprehension.)

    Example 1. & 2. The following are the original img (.control) and .imgDiv:

    // Example 1. `.control`: `position: relative` was added for demo purposes.
    
      .control {
        position: relative;
        max-width: 100%;
        max-height: 100%;
        width: auto;
        height: auto;
        vertical-align: middle;
      }
    
      .imgDiv {
        position: relative;
        display: inline-block;
        width: 100%;
        height: 100%;
        vertical-align: middle;
        background-image: url(https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png);
        background-repeat: no-repeat;
        background-size: contain; 
        background-position: center;
      }
    

    In short, if you want to mimic a replaced element, you should use a replaced element. What determines a replaced element's dimensions is not itself, but what it has (ie content of an img would be a png file), a non-replaced element is not determined by it's content (ie div). So I figured a video element would be a more suitable img replacement.

    Example 3. & 4. A quick breakdown:

     // Do not copy this code, I broke it into pieces so you don't have to scroll
    
     <div class="case" style="width:300px; height: 150px; line-height: 150px;">
    
      <video id="vid1"
    
         poster="https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png" 
    
         width="300" height="150"></video>
    
    </div>
    
    // Do not copy this code, I broke it into pieces so you don't have to scroll
    
    <video id="vid2"
    
       poster="https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png"
    
       src="https://glpjt.s3.amazonaws.com/so/av/vs8s3.mp4" 
    
       width="100%" height="auto">
    
    </video> 
    
    • Attributes:
      • poster: This attribute accepts a path to an image then displays the image until the video element plays. Without going any further, we can see that thevideo element can stand in for img easily.
      • controls: They are removed since we are only interested in the image aspects of the video element.
      • src: I assigned this attribute a small video (86.6KB). I don't think we need it, I just added it in for testing.
      • width and height: A video element by itself can be responsive just by setting width to 100% and height to auto.

    Plunker

    Snippet

    <!doctype html>
    <html>
    
    <head>
      <meta charset="utf-8">
      <title>35522592</title>
      <style>
        body {
          counter-reset: exp;
        }
        span.txt:before {
          counter-increment: exp;
          content: "Example " counter(exp)". ";
        }
        .box {
          position: relative;
          display: inline-table;
          min-width: 300px;
          min-height: 150px;
          margin: 5% auto;
        }
        .case {
          position: relative;
          background-color: #2DBCFF;
          text-align: center;
          box-sizing: border-box;
          font-size: 0;
          margin: 20px;
        }
        .control {
          position: relative;
          max-width: 100%;
          max-height: 100%;
          width: auto;
          height: auto;
          vertical-align: middle;
        }
        .imgDiv {
          position: relative;
          display: inline-block;
          width: 100%;
          height: 100%;
          vertical-align: middle;
          background-image: url(https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png);
          background-repeat: no-repeat;
          background-size: contain;
          background-position: center;
        }
        .big {
          font-size: 24px;
        }
        .txt {
          margin: 0 0 15px 20px;
        }
        #vid1,
        #vid2 {
          fit-object: contain;
        }
        #b2 {
          background: #F06;
          min-width: 40vw;
          max-width: 100%;
          height: auto;
        }
      </style>
    </head>
    
    <body>
      <section class="box">
        <div class="case" style="width:300px; height: 150px; line-height: 150px;">
          <img class="control" src="https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png">
        </div>
        <span class="txt">This is the image<b class="big">&#8679;</b> from the OP.</span>
        <div class="case" style="width:300px; height: 150px; line-height: 150px;">
          <div class="imgDiv"></div>
        </div>
        <span class="txt">This div <b class="big">&#8679;</b> uses the property background-image.</span>
        <div class="case" style="width:300px; height: 150px; line-height: 150px;">
          <video id="vid1" poster="https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png" width="300" height="150"></video>
        </div>
        <span class="txt"><b class="big">&#8679;</b>This is a video  element it only has an image, no video.</span>
      </section>
    
      <section class="box" id="b2">
        <video id="vid2" poster="https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png" src="https://glpjt.s3.amazonaws.com/so/av/vs8s3.mp4" width="100%" height="auto"></video>
        <span class="txt">This is a video  element <b class="big">&#8679;</b>it has an image and a video.</span>
      </section>
    </body>
    
    </html>