2

I've built a carousel, and I want the images to max out the screen in one dimension width if the width of the image is greater than the height, and height if vice versa.

Maxing the height should allow space for a header/navbar and footer, and I want them scaled proportionally. At the moment, they are scaling to the width, but they hugely overflow the viewport in the vertical direction.

HTML:

<div id="frontimages" class="carousel slide" data-ride="carousel">

    <ul class="carousel-indicators">
        <li data-target="#frontimages", data-slide-to="0" class="active"></li>
    </ul>

    <div class="carousel-inner">
        <div class="carousel-item active">
            <img class="d-block img-fluid" src="url" alt="title">
        </div>
    </div>

    <a class="carousel-control-prev" href="#frontimages" data-slide="prev">
        <span class="carousel-control-prev-icon"></span>
    </a>

    <a class="carousel-control-next" href="#frontimages" data-slide="next">
        <span class="carousel-control-next-icon"></span>
    </a>

</div>

CSS:

.carousel-inner img {
    width: 100%;
    height: 100%;
}
Stickers
  • 75,527
  • 23
  • 147
  • 186
Alex
  • 2,270
  • 3
  • 33
  • 65
  • 2
    Use background images instead – Carol Skelly Mar 05 '18 at 13:24
  • The best solution is, at @ZimSystem said, just use background-image and `background-size: cover` which maxes out the image in one dimensions, yet maintains aspect ratio, so it "covers" the area. Rather than using a mountain of JavaScript/CSS. – Adam Jenkins Mar 05 '18 at 18:01

4 Answers4

5

If you want each image to cover the entire carousel item, you can do:

.carousel-item {
  width: 100%;
  height: 300px; /* example */
}

.carousel-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit

Or, use background images, instead of fixed height you can also make it responsive:

<div class="carousel-item" style="background-image:url('url');"></div>

.carousel-item {
  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
}

.carousel-item:before {
  content: "";
  display: block;
  padding-bottom: 56.25%; /* example */
}

Aspect ratio tables:

aspect ratio  | padding-bottom value
--------------|----------------------
    16:9      |       56.25%
    4:3       |       75%
    3:2       |       66.66%
    8:5       |       62.5%

https://stackoverflow.com/a/10441480/483779

Stickers
  • 75,527
  • 23
  • 147
  • 186
0

Your best way of doing this would be as follows:

.carousel-inner img { 
    max-width:100%;
    max-height:100%;
    width: auto; 
    height: auto; 
}

This way it will maintain the aspect ratio whilst filling the screen.

Hope this helps!

DKyleo
  • 806
  • 8
  • 11
  • Thanks, that seems to have made them much smaller, but they're now about 50% of the screen, not all of it. They're also no longer centred... – Alex Mar 05 '18 at 13:55
  • I'd add in margin:auto; and vertical-align:middle; into your carousel-inner class. As for the issue of it taking up only half of the screen, the size of the image is dependant on the size of the div it is inside. – DKyleo Mar 05 '18 at 13:59
0

This is a live demo: http://jsbin.com/vewavayexa/edit?output

I suggest you copy the code to local to check the effect, they are not fitted with the jsbin elements and sometimes it can not load all images (refresh your browser if so)

   <header>
    <h1>Gallery</h1>
  </header>
  <nav><a href="Home">Home</a><a href="">Blog</a><a href="">About</a></nav>
  <div class="gallery">
    <div class="container">
      <img src="https://i.loli.net/2018/03/06/5a9d82e150523.jpg" alt="">
      <img src="https://i.loli.net/2018/03/06/5a9d82e1bd5b0.jpg" alt="">
      <img src="https://i.loli.net/2018/03/06/5a9d82e203fc3.jpg" alt="">
      <img src="https://i.loli.net/2018/03/06/5a9d82e1be833.jpg" alt="">
    </div>
  </div>
  <footer>Copyright</footer>

css

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }
  ul {
    list-style: none;
  }
  a {
    text-decoration: none;
    color:#FFF;
  }
  a:hover {
    background:#B7023F;
  }
  header {
    height: 70px;
    background:#55024A;
    color: #FFF;
  }
  h1 {
    line-height: 70px;
    padding: 0 30px;
  }
  nav {
    background: #E16639;
    padding: 0 15px;
    color: #FFF;
    height: 50px;
  }

  nav a {
    /* height: 50px; */
    /* line-height: 50px; */
    display: inline-block;
    padding: 15px 15px;
  }

  footer {
    height: 70px;
    line-height: 70px;
    background: #AD860A;
    color: #FFF;
    padding: 0 30px;
  }

  img {
    display: block;
    position: absolute;
  }
  .gallery {
    overflow: hidden;
    position: relative;
  }

  .container {
    top: 0;
    left: 0;
    position: absolute;
  }

js

    const wh = getWH()
    const gallery = document.querySelector('.gallery')
    const container = document.querySelector('.container')
    gallery.style.width = wh.w + 'px'
    gallery.style.height = wh.h + 'px'
    container.style.height = wh.h + 'px'
    let imgs = document.querySelectorAll('img')
    const allImgWidth = []

    container.appendChild(imgs[0].cloneNode(true))
    container.insertBefore(imgs[imgs.length -1].cloneNode(true), imgs[0])

    imgs = document.querySelectorAll('img')
    // set width and height for each images
    Array.prototype.forEach.call(imgs, img => {
      if (parseInt(img.clientWidth) > parseInt(img.clientHeight)) {
        img.style.width = wh.w + 'px'
      } else {
        img.style.height = wh.h + 'px'
      }

      img.style.left = allImgWidth.reduce((a, b) => a + b, 0 )
      allImgWidth.push(img.offsetWidth)
    })
    const totalWidth = allImgWidth.reduce((a, b) => a + b, 0)
    container.style.width = totalWidth + 'px'
    const slideWidth = totalWidth - allImgWidth[allImgWidth.length - 1]
    const step = parseInt(slideWidth / 100)
    let startPoint = container.style.left = -allImgWidth[0]
    // move container, if it got max left, then reset to starting point
    setInterval(() => {
      let x = container.style.left.slice(0, -2) - step
      if (Math.abs(x) >= slideWidth) {
        container.style.left = startPoint
      } else {
        container.style.left = x
      }
    }, 100)

    function getWH() {
      const header = document.querySelector('header')
      const nav = document.querySelector('nav')
      const footer = document.querySelector('footer')
      const offset = header.offsetHeight + nav.offsetHeight + footer.offsetHeight
      return {
        w: window.innerWidth,
        h: document.body.clientHeight - (header.offsetHeight + nav.offsetHeight + footer.offsetHeight)
      }
    }
sfy
  • 2,810
  • 1
  • 20
  • 22
0

I'm still learning bootstrap v 4.0.0, but I put the code above in the .d-block section under the carousel and it scaled the images well.

.d-block {
  display: block !important;
  /*added this below*/
    width: 100%;
    height: 100%;
    object-fit: cover;
}
tbrinkley
  • 1
  • 3
  • If there's no difference between the screenshot and the code you included, you can remove the screenshot. If that code from a particular source, it would be better to link the source instead. – buratino Dec 16 '18 at 18:41