Jools Jools - 2 months ago 14
HTML Question

How do you reduce the scrollable height of a div with scaled content?

I have a scrollable div that I zoom/scale the content of using css3 transform. It works fine if I'm zooming in (scaling up the content) but I've noticed that when scaling down, below 100%, the amount that you can scroll vertically of the container div does not reduce.

I've made a jsfiddle to illustrate this

CSS:

.scrollable
{
height: 250px;
width: 250px;
overflow: auto;
background-color: green;
}

.content
{
height :500px;
width : 500px;
background: linear-gradient(red, blue);
...
}


JS/jquery:

function scaleContent(newScale){
var $content = $("#content");
var scaleString = "scale("+newScale+")";
//var height = (newScale<1)? $("#content").height()/scale*newScale : originalHeight;
$content.css({
'-webkit-transform' : scaleString,
'-webkit-transform-origin' : '0 0',
...
//'height' : height +'px'
});
scale=newScale;
}


The actual scaling and the amount that you can scroll horizontally works perfectly, but the amount you can scroll vertically doesn't change below 100%.

Note: the amount you can scroll vertically appears to change on the first scaledown/zoomout, but this is simply because the horizontal scrollbar is removed.

I tried to manually change the height of the content, but this just messed with the content dimensions (duh). That's the commented-out height code.

The ellipses are where I've repeated things for other browsers.

Answer

I've managed to come up with one solution, though it's probably not the best. I introduced another div around the content, which I call the view wrapper. I set its overflow to "hidden" and manually set its width and height to match what the scaled content should be.

CSS:

.viewwrapper{
    height :500px;
    width : 500px;
    overflow: hidden
}

JS:

function scaleContent(newScale){
    var $content = $("#content");
    var scaleString = "scale("+newScale+")";
    var $viewwrapper = $("#viewwrapper");
    var height = $content.height()/newScale;
    var width = $content.width()/newScale;
    $viewwrapper.height(height);
    $viewwrapper.width(width);
    $content.css({
        '-webkit-transform' : scaleString,
        '-webkit-transform-origin' : '0 0',
    ...
    });
}

JS Fiddle

Update:

This won't work if you're using jQuery 3.0 or 3.1. The read behaviour of the height and width functions has changed, so they return the scaled values. To fix the above code for those versions you can just say.

function scaleContent(newScale){
    var $content = $("#content");
    var scaleString = "scale("+newScale+")";
    var $viewwrapper = $("#viewwrapper");
    $viewwrapper.height($content.height());
    $viewwrapper.width($content.width());
    $content.css({
        '-webkit-transform' : scaleString,
        '-webkit-transform-origin' : '0 0',
    ...
    });
}

JSFiddle using jQuery 3.0

However this probably won't make it into future versions of jQuery.

Update 2: You might see unnecessary scrollbars in Chrome when you zoom out of the content. This is down to a Chrome bug.