1

I want to show only a percentage of an image (say, the top half), but in a responsive way so that resizing the viewport doesn't affect what portion of the image is shown.

JSFiddle attempt

The only solutions I've found rely on using a fixed height for the image (say, 200px) rather than a %age, but this isn't responsive. As you shrink the viewport, more and more of the image shows until you eventually see the entire image.


Note: My JSFiddle example is using the bootstrap class img-responsive, which adds the following CSS properties:

display: block
max-width: 100%;
height: auto

You can also grab the middle divider/handlebar in the JSFiddle and move it around to see the effect on the image.


What can be done to meet my requirements? Is it even possible without JavaScript and with browser support down to IE9?

ericgrosse
  • 1,490
  • 20
  • 37

3 Answers3

2

Here, I threw this together for you: https://jsfiddle.net/qse2LL4b/4/

function showPart(img, offsetTop, offsetLeft, width, height){
  var src = img.src;
    $(img).replaceWith("<canvas id='cnvs' style='max-width:100%;'></canvas>");
  var canvas = document.getElementById('cnvs');
  canvas.height = height;
  canvas.width = width;
  var ctx = canvas.getContext("2d");
  var img = new Image();
  img.onload = function(){
    ctx.drawImage(this, offsetLeft, offsetTop, width, height, 0, 0, width, height);
  };
  img.src = src;
}

It takes the source of your image and crops it and replaces it. You can add the im-responsive class to the "canvas" element in the function if you want.

I wrestled a bear once.
  • 22,983
  • 19
  • 69
  • 116
1

You can use a pseudo-element :after in addition to position: absolute.

div:after {
  content: "";
  position: absolute;
  height: 50%;
  width: 100%;
  top: 0;
  left: 0;
  background-color: #ffffff
}

Fiddle: https://jsfiddle.net/qse2LL4b/3/

Xzandro
  • 957
  • 6
  • 14
  • but as you shrink the viewport, the image disappears eventually...not what was asked...and you fiddle link is the same as the original – rby Apr 05 '16 at 20:07
  • Fixed fiddle link. – Xzandro Apr 05 '16 at 20:09
  • Nice solution. Can you explain a little how it works? – ericgrosse Apr 05 '16 at 20:13
  • div:after reacts like a normal element inside the div container. div container is set as `position: relative` so the :after element starts from the top and is 50% height. If you want to show the top half you only need to change the `top: 0` in `bottom: 0` so that is starts from the bottom. – Xzandro Apr 05 '16 at 20:18
  • I just realized that you're masking the top half of the image with a white background. Unfortunately that top half is still taking up space, which is problematic. If you put a header above the image, you'll have a bunch of empty space before seeing the image. – ericgrosse Apr 05 '16 at 20:31
  • Yes, you are right. You could add `margin-top: -50%;` to free this space. https://jsfiddle.net/qse2LL4b/5/ – Xzandro Apr 05 '16 at 20:36
1

Maybe like this

body {
  background: gray;
}
div {
  display: inline-block;
  overflow: hidden;
}
div img {
  position: relative;
  margin-top: -50%;
  transform: translateY(50%);
}
<div>
  <img class="img-responsive" src="http://icons.iconarchive.com/icons/mazenl77/I-like-buttons-3a/512/Cute-Ball-Go-icon.png" class="img-responsive" />
</div>
Asons
  • 84,923
  • 12
  • 110
  • 165