Scale image to fit a bounding box

前端 未结 13 1905
轻奢々
轻奢々 2020-11-27 10:17

Is there a css-only solution to scale an image into a bounding box (keeping aspect-ratio)? This works if the image is bigger than the container:

img {
  max-         


        
相关标签:
13条回答
  • 2020-11-27 10:52

    html:

        <div class="container">
          <img class="flowerImg" src="flower.jpg">
        </div>
    

    css:

    .container{
      width: 100px;
      height: 100px;
    }
    
    
    .flowerImg{
      width: 100px;
      height: 100px;
      object-fit: cover;
      /*object-fit: contain;
      object-fit: scale-down;
      object-position: -10% 0;
      object-fit: none;
      object-fit: fill;*/
    }
    
    0 讨论(0)
  • 2020-11-27 10:52

    You can accomplish this with pure CSS and complete browser support, both for vertically-long and horizontally-long images at the same time.

    Here's a snippet which works in Chrome, Firefox, and Safari (both using object-fit: scale-down, and without using it):

    figure {
      margin: 0;
    }
    
    .container {
      display: table-cell;
      vertical-align: middle;
      width: 80px;
      height: 80px;
      border: 1px solid #aaa;
    }
    
    .container_image {
      display: block;
      max-width: 100%;
      max-height: 100%;
      margin-left: auto;
      margin-right: auto;
    }
    
    .container2_image2 {
      width: 80px;
      height: 80px;
      object-fit: scale-down;
      border: 1px solid #aaa;
    }
    Without `object-fit: scale-down`:
    
    <br>
    <br>
    
    <figure class="container">
      <img class="container_image" src="https://i.imgur.com/EQgexUd.jpg">
    </figure>
    
    <br>
    
    <figure class="container">
      <img class="container_image" src="https://i.imgur.com/ptO8pGi.jpg">
    </figure>
    
    <br> Using `object-fit: scale-down`:
    
    <br>
    <br>
    
    <figure>
      <img class="container2_image2" src="https://i.imgur.com/EQgexUd.jpg">
    </figure>
    
    <br>
    
    <figure>
      <img class="container2_image2" src="https://i.imgur.com/ptO8pGi.jpg">
    </figure>

    0 讨论(0)
  • 2020-11-27 10:54

    Note: Even though this is the accepted answer, the answer below is more accurate and is currently supported in all browsers if you have the option of using a background image.

    No, there is no CSS only way to do this in both directions. You could add

    .fillwidth {
        min-width: 100%;
        height: auto;
    }
    

    To the an element to always have it 100% width and automatically scale the height to the aspect ratio, or the inverse:

    .fillheight {
        min-height: 100%; 
        width: auto;
    }
    

    to always scale to max height and relative width. To do both, you will need to determine if the aspect ratio is higher or lower than it's container, and CSS can't do this.

    The reason is that CSS does not know what the page looks like. It sets rules beforehand, but only after that it is that the elements get rendered and you know exactly what sizes and ratios you're dealing with. The only way to detect that is with JavaScript.


    Although you're not looking for a JS solution I'll add one anyway if someone might need it. The easiest way to handle this with JavaScript is to add a class based on the difference in ratio. If the width-to-height ratio of the box is greater than that of the image, add the class "fillwidth", else add the class "fillheight".

    $('div').each(function() {
      var fillClass = ($(this).height() > $(this).width()) 
        ? 'fillheight'
        : 'fillwidth';
      $(this).find('img').addClass(fillClass);
    });
    .fillwidth { 
      width: 100%; 
      height: auto; 
    }
    .fillheight { 
      height: 100%; 
      width: auto; 
    }
    
    div {
      border: 1px solid black;
      overflow: hidden;
    }
    
    .tower {
      width: 100px;
      height: 200px;
    }
    
    .trailer {
      width: 200px;
      height: 100px;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="tower">
      <img src="http://placekitten.com/150/150" />
    </div>
    <div class="trailer">
      <img src="http://placekitten.com/150/150" />
    </div>

    0 讨论(0)
  • 2020-11-27 10:57

    The cleanest and simplest way to do this:

    First some CSS:

    div.image-wrapper {
        height: 230px; /* Suggestive number; pick your own height as desired */
        position: relative;
        overflow: hidden; /* This will do the magic */
        width: 300px; /* Pick an appropriate width as desired, unless you already use a grid, in that case use 100% */
    }
    img {
        width: 100%;
        position: absolute;
        left: 0;
        top: 0;
        height: auto;
    }
    

    The HTML:

    <div class="image-wrapper">
      <img src="yourSource.jpg">
    </div>
    

    This should do the trick!

    0 讨论(0)
  • 2020-11-27 11:01

    Thanks to CSS3 there is a solution !

    The solution is to put the image as background-image and then set the background-size to contain.

    HTML

    <div class='bounding-box'>
    </div>
    

    CSS

    .bounding-box {
      background-image: url(...);
      background-repeat: no-repeat;
      background-size: contain;
    }
    

    Test it here: http://www.w3schools.com/cssref/playit.asp?filename=playcss_background-size&preval=contain

    Full compatibility with latest browsers: http://caniuse.com/background-img-opts

    To align the div in the center, you can use this variation:

    .bounding-box {
      background-image: url(...);
      background-size: contain;
      position: absolute;
      background-position: center;
      background-repeat: no-repeat;
      height: 100%;
      width: 100%;
    }
    
    0 讨论(0)
  • 2020-11-27 11:01

    Here's a hackish solution I discovered:

    #image {
        max-width: 10%;
        max-height: 10%;
        transform: scale(10);
    }
    

    This will enlarge the image tenfold, but restrict it to 10% of its final size - thus bounding it to the container.

    Unlike the background-image solution, this will also work with <video> elements.

    Interactive example:

     function step(timestamp) {
         var container = document.getElementById('container');
         timestamp /= 1000;
         container.style.left   = (200 + 100 * Math.sin(timestamp * 1.0)) + 'px';
         container.style.top    = (200 + 100 * Math.sin(timestamp * 1.1)) + 'px';
         container.style.width  = (500 + 500 * Math.sin(timestamp * 1.2)) + 'px';
         container.style.height = (500 + 500 * Math.sin(timestamp * 1.3)) + 'px';
         window.requestAnimationFrame(step);
     }
    
     window.requestAnimationFrame(step);
     #container {
         outline: 1px solid black;
         position: relative;
         background-color: red;
     }
     #image {
         display: block;
         max-width: 10%;
         max-height: 10%;
         transform-origin: 0 0;
         transform: scale(10);
     }
    <div id="container">
        <img id="image" src="https://upload.wikimedia.org/wikipedia/en/7/7d/Lenna_%28test_image%29.png">
    </div>

    0 讨论(0)
提交回复
热议问题