3

I have scaled content within an unscaled <div>:

<style>
#outer { 
    background-color: blue; 
    padding: 3px;
}
#inner { 
    background-color: red;
    width: 400px; 
    height: 400px; 
    -moz-transform: scale(0.5);
    -webkit-transform: scale(0.5);
    transform: scale(0.5);
}
</style>

<div id=outer>
    <div id=inner>
    </div>
</div>

It looks like this:

Outer div wapping original inner div size

Here's a JS Fiddle too.

The problem is that outer <div> - following the transform: scale the inner <div> is 200px in size, but the outer <div> still wraps the original size of 400px.

I want to collapse the size of the outer <div> to wrap the scaled content, so it should look something like this:

Outer div collapses to the scaled size with padding

In the application the scale property is changed dynamically, and the div contains content that should scale with it.

Is there any way to do this with CSS?

Failing that is there any way to do this with Javascript?

Keith
  • 150,284
  • 78
  • 298
  • 434
  • JS I think...because that looks like expected behaviour. – Paulie_D Feb 14 '14 at 17:09
  • 1
    Quick google found this which seems to be relevant although does not provide a solution: http://stackoverflow.com/questions/16301625/rotated-elements-in-css-that-affects-their-parents-height-correctly – Paulie_D Feb 14 '14 at 17:13
  • 1
    @Paulie_D arg, I thought that was familiar! I've had the same problem before (kicks self) http://stackoverflow.com/questions/716970/rotating-table-header-text-with-css-transforms – Keith Feb 14 '14 at 17:24

2 Answers2

0

I've been reading a bit and apparently you cannot control a parent element from a sibling element with CSS.

So I put together a little FIDDLE, and using jQuery to adjust the outer element to the inner element. I'm not sure it does exactly what you want, but perhaps it will give you a start.

JS

$('#inner').hover(
    function(){
               var innerwidth = $('#inner').width();
                   innerwidth = innerwidth * 1.05;
               var innerheight = $('#inner').height();
                   innerheight = innerheight * 1.05;
               $('#outer').css({
                                width: innerwidth,
                                height: innerheight
                                 });
               },
    function(){
               $('#outer').css({
                                width: '600',
                                height: '400'
                                 });
               }
    );
TimSPQR
  • 2,964
  • 3
  • 20
  • 29
  • Cheers, but that does not work. Your fiddle appears to do the job, but you removed the scale from the inner `div` - put it back and setting explicit CSS width/height does nothing - see this fork: http://jsfiddle.net/QDRhX/ – Keith Feb 17 '14 at 08:51
0

I've got a solution in Javascript, but it's horrible:

  1. To everything outside of the scaled content it's still its original size.
  2. It's still positioned from its original size/location.

So we need to dynamically for the parent's size (to get round 1) and then apply a negative offset to the inner content with an absolute position (to get round 2).

The solution looks something like this:

function collapseScale(inner, scale)
{
    var $inner = $(inner);

    // Get the width and height pre-scaling, including borders
    var x = $inner.outerWidth(),
        y = $inner.outerHeight();

    // Get the scaled width and height
    var xs = x * scale,
        ys = y * scale;

    // The offset will be half the difference (either side) of the difference between the original size and the scaled size
    var xo = (xs - x)/2,
        yo = (ys - y)/2;

    // Set the parent to be the same size, with no overflow
    $inner.parent().css({
        width: xs,
        height: ys,
        overflow: 'hidden',
        position: 'relative'
    });

    // Now absolutelty position the inner with a negative offset
    $inner.css({
        position: 'absolute',
        top: '' + yo + 'px',
        left: '' + xo + 'px'
    });
}

Here's the fiddle, it appears to work in most of the browsers that support transform: scale.

Update

I've found a better way to do part of this - issue (2) above can be alleviated with transform-origin:

#inner {
    -webkit-transform-origin: left top;
    -ms-transform-origin: left top;
    transform-origin: left top;
}

That lets me drop the dynamic absolute positioning, but Javascript is still needed to resize the outer content:

function collapseScale(inner, scale) {
    var $inner = $(inner);

    // Set the parent to be the same size
    $inner.parent().css({
        width: $inner.outerWidth() * scale,
        height: $inner.outerHeight() * scale
    });

    var scaleCss = 'scale(' + scale + ')'
    $inner.css({
        '-moz-transform': scaleCss,
        '-webkit-transform': scaleCss,
        'transform': scaleCss
    });
}

Here's the updated fiddle, with a jQuery UI slider to test different scale amounts.

Keith
  • 150,284
  • 78
  • 298
  • 434