Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chrome messing up images inside a scaled element which has border radius

USE CASE

I am trying to build a "slide show" type application. Each slide has a fixed aspect ratio, but I want the contents to be rendered with their normal width/height - so I am trying to use the CSS3 "transform:scale" on the contents of the slide, using the viewport width/height I calculate the ideal scale/margins to fit the slide into the viewport. On one particular slide I am showing some "info card" for people and a list of each person's "successors"

ISSUE

Chrome is showing some very weird behavior on the images. If you resize the window the images move all over the place. If you force the image to repaint somehow the image seems to fix itself (i.e. scroll page down and back up)

Edit this seems related specifically to an image inside a box with border radius!

QUESTION

Is this a bug in Chrome? Is there any work around that will fix this issue?

LIVE EXAMPLE

Live Fiddle

In this live example - you can resize the Result Pane to cause the image to be scaled. At least in my version of chrome the image goes haywire.

POST EDITS

I widdled the code down to the minimum required to reproduce issue. I only used webkit vendor prefixes.

I also updated the issue description because after widdling the code down I realized it must have something to do with the border radius of the element containing the image!

Original Fiddle

HTML

<div class="container">
    <div class="inner">
        <div class="box">
            <img src="https://en.gravatar.com/userimage/22632911/5cc74047e143f8c15493eff910fc3a51.jpeg"/>
        </div>
    </div>
</div>

CSS

body {
    background-color: black;
}

.inner {
    background-color: white;
    width: 800px;
    height: 600px;
    -webkit-transform-origin: 0 0;
}

.box {
    overflow: hidden;
    -webkit-border-radius: 10px;
    width: 80px;
    height: 80px;
    margin: 10px;
}

JAVASCRIPT

(function ($) {
    var $inner = $('.inner');
    var $window = $(window);
    var iWidth = parseInt($inner.css('width'));
    var iHeight = parseInt($inner.css('height'));
    var iRatio = iWidth / iHeight;

    function adjustScale() {
        var vWidth = $window.width();
        var vHeight = $window.height();
        if (vWidth / vHeight > iRatio) {
            width = vHeight * iRatio;
        } else {
            width = vWidth;
        }
        var scale = width / iWidth;
        $inner[0].style.WebkitTransform = 'scale(' + scale + ')';
    }

    adjustScale();
    $window.resize(adjustScale);
})(jQuery);
like image 630
codefactor Avatar asked Mar 05 '13 20:03

codefactor


1 Answers

This is happening because you are performing a division here

var scale = width / iWidth;

that is giving you a number with a lot of decimals;

Using this number with CSS3 Transform - Scale() forces the engine to perform some long calculation, that appearently is not well-handled by Chrome;

then +1, you probably discovered an CSS engine flaw of Chrome.


For the records: appearently, Chrome starts having problems from TWO decimal numbers:

// Bad
var scale = (width / iWidth).toFixed(2);

(Not) Working demo: http://jsfiddle.net/VPZqA/1/

Feel free to open a bug-report @ Google.


Solution:

To prevent that, you can simply round the value to ONE decimal number, like this:

// Right
var scale = (width / iWidth).toFixed(1);

Working demo: http://jsfiddle.net/VPZqA/

This way your math will be less precise, but in a way probably not noticeable.

Hope that helps

like image 105
Andrea Ligios Avatar answered Sep 19 '22 21:09

Andrea Ligios