skip to Main Content

I have a JavaScript slideshow that displays images of various dimensions in a browser window. It uses object-fit: scale-down to resize the image to fit the container. I’d like to add a border to the image, but when I apply the style border: 2px solid black to the <img> element, it seems to surround what would be the image in its original, unscaled size.

Is there a way, either with CSS or with JavaScript, to apply the border to the resized image?

Update: I’d prefer a solution that allows me to use the border-family of style settings, even if it requires some JavaScript.

const duration = 2000; // time (msec) to display each slide
const sizes = [
  [4000, 500],
  [1000, 4000],
  [600, 400],
  [100, 200]
];
const sleep = ms => new Promise(r => setTimeout(r, ms));
let size_index = 0;

function show_slides(duration) {
  let this_duration = duration;
  const my_parent = document.querySelector('#slide-div');
  if (size_index == sizes.length) {
    size_index = 0;
  }
  let w = sizes[size_index][0];
  let h = sizes[size_index][1];
  ++size_index;

  let my_randomizer = `https://placehold.co/${w}x${h}?text=${w}+x+${h}npx`;
  fetch(my_randomizer)
    .then(my_response => my_response.blob())
    .then(my_blob => {
      let my_url = URL.createObjectURL(my_blob);
      sleep(this_duration)
        .then(() => {
          URL.revokeObjectURL(my_parent.querySelector('img').src);
          my_parent.querySelector('img').src = my_url;
          show_slides(duration);
        });
    })
    .catch(my_error => console.error('Error: ', my_error));
}
html {
  height: 100%;
  width: 100%;
}

body {
  /* prevent body from displacing */
  margin: 0;
  /* body should perfectly superimpose the html */
  height: 100%;
  width: 100%;
}

.outer-div {
  display: flex;
  flex-flow: column;
  height: 100%;
  /* Now create left/right margins */
  margin: 0 0.5em;
}

.inner-fixed-div {
  margin-top: 0.5em;
}

.inner-remaining-div {
  margin-bottom: 1em;
  flex-grow: 1;
  /* hints the contents to not overflow */
  overflow: hidden;
}

.picture-div {
  /* force the div to fill the available space */
  width: 100%;
  height: 100%;
}

.picture-div-img {
  /* force the image to stay true to its proportions */
  width: 100%;
  height: 100%;
  /* and force it to behave like needed */
  object-fit: scale-down;
  object-position: center;
  /* does not properly enclose image: */
  border: 2px solid black;
}
<!DOCTYPE html>
<html lang="en">
<!-- Self-contained slideshow demo -->

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">

</head>

<body onload="show_slides(duration);">
  <div class="outer-div">
    <div class="inner-fixed-div">
      <h1>Lorem Epsom</h1>
    </div>
    <div class="inner-remaining-div">
      <!-- This div will hold the <img> -->
      <div id="slide-div" class="picture-div">
        <!-- Placeholder <img> element for slides -->
        <img class="picture-div-img">
      </div>
    </div>
    <!-- end of inner-remaining-div -->
  </div>
  <!-- end of outer-div -->
</body>

</html>

2

Answers


  1. You can approximate it using a drop-shadow filter:

    const duration = 2000; // time (msec) to display each slide
    const sizes = [
      [4000, 500],
      [1000, 4000],
      [600, 400],
      [100, 200]
    ];
    const sleep = ms => new Promise(r => setTimeout(r, ms));
    let size_index = 0;
    
    function show_slides(duration) {
      let this_duration = duration;
      const my_parent = document.querySelector('#slide-div');
      if (size_index == sizes.length) {
        size_index = 0;
      }
      let w = sizes[size_index][0];
      let h = sizes[size_index][1];
      ++size_index;
    
      let my_randomizer = `https://placehold.co/${w}x${h}?text=${w}+x+${h}npx`;
      fetch(my_randomizer)
        .then(my_response => my_response.blob())
        .then(my_blob => {
          let my_url = URL.createObjectURL(my_blob);
          sleep(this_duration)
            .then(() => {
              URL.revokeObjectURL(my_parent.querySelector('img').src);
              my_parent.querySelector('img').src = my_url;
              show_slides(duration);
            });
        })
        .catch(my_error => console.error('Error: ', my_error));
    }
    body {
      margin: 0;
      height: 100vh;
    }
    
    .outer-div {
      display: flex;
      flex-flow: column;
      height: 100%;
      margin: 0 0.5em;
    }
    
    .inner-fixed-div {
      margin-top: 0.5em;
    }
    
    .inner-remaining-div {
      margin-bottom: 1em;
      flex-grow: 1;
      overflow: hidden;
    }
    
    .picture-div {
      width: 100%;
      height: 100%;
    }
    
    .picture-div-img {
      width: 100%;
      height: 100%;
      object-fit: scale-down;
      object-position: center;
      border: 2px solid #0000;
      box-sizing: border-box;
      filter: drop-shadow(0 0 1px black) drop-shadow(0 0 1px black) drop-shadow(0 0 1px black);
    }
    <body onload="show_slides(duration);">
      <div class="outer-div">
        <div class="inner-fixed-div">
          <h1>Lorem Epsom</h1>
        </div>
        <div class="inner-remaining-div">
          <!-- This div will hold the <img> -->
          <div id="slide-div" class="picture-div">
            <!-- Placeholder <img> element for slides -->
            <img class="picture-div-img">
          </div>
        </div>
        <!-- end of inner-remaining-div -->
      </div>
      <!-- end of outer-div -->
    </body>
    Login or Signup to reply.
  2. You can use max-width and max-height and include calculated padding/margin. Also used position, left and transform: translate to center image element.

    const duration = 2000; // time (msec) to display each slide
    const sizes = [
      [4000, 500],
      [1000, 4000],
      [600, 400],
      [100, 200]
    ];
    const sleep = ms => new Promise(r => setTimeout(r, ms));
    let size_index = 0;
    
    function show_slides(duration) {
      let this_duration = duration;
      const my_parent = document.querySelector('#slide-div');
      if (size_index == sizes.length) {
        size_index = 0;
      }
      let w = sizes[size_index][0];
      let h = sizes[size_index][1];
      ++size_index;
    
      let my_randomizer = `https://placehold.co/${w}x${h}?text=${w}+x+${h}npx`;
      fetch(my_randomizer)
        .then(my_response => my_response.blob())
        .then(my_blob => {
          let my_url = URL.createObjectURL(my_blob);
          sleep(this_duration)
            .then(() => {
              URL.revokeObjectURL(my_parent.querySelector('img').src);
              my_parent.querySelector('img').src = my_url;
              show_slides(duration);
            });
        })
        .catch(my_error => console.error('Error: ', my_error));
    }
    html {
      height: 100%;
      width: 100%;
    }
    
    body {
      /* prevent body from displacing */
      margin: 0;
      /* body should perfectly superimpose the html */
      height: 100%;
      width: 100%;
    }
    
    .outer-div {
      display: flex;
      flex-flow: column;
      height: 100%;
      /* Now create left/right margins */
      margin: 0 0.5em;
    }
    
    .inner-fixed-div {
      margin-top: 0.5em;
    }
    
    .inner-remaining-div {
      margin-bottom: 1em;
      flex-grow: 1;
      /* hints the contents to not overflow */
      overflow: hidden;
    }
    
    .picture-div {
      /* force the div to fill the available space */
      width: 100%;
      height: 100%;
    }
    
    .picture-div-img {
      position: relative;
      left: 50%;
      transform: translate(-50%);
      max-width: calc(100% - 1em); /* included 0.5em * 2 margin on parent */ 
      max-height: calc(100% - 0.5em); /* included 0.5em margin on parent */ 
      object-fit: scale-down;
      object-position: center;
      border: 2px solid black;
    }
    <!DOCTYPE html>
    <html lang="en">
    <!-- Self-contained slideshow demo -->
    
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">
    
    </head>
    
    <body onload="show_slides(duration);">
      <div class="outer-div">
        <div class="inner-fixed-div">
          <h1>Lorem Epsom</h1>
        </div>
        <div class="inner-remaining-div">
          <!-- This div will hold the <img> -->
          <div id="slide-div" class="picture-div">
            <!-- Placeholder <img> element for slides -->
            <img class="picture-div-img">
          </div>
        </div>
        <!-- end of inner-remaining-div -->
      </div>
      <!-- end of outer-div -->
    </body>
    
    </html>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search