Search code examples
csswebkit

How to fix lags on webkit/iphone when using transform rotate in radial progress bar


I am using this radial progress bar: http://jsfiddle.net/andsens/mLA7X/ It uses transform: rotate(); to visually display a percentage (e.g. 80%).

It works like a charm in chrome and FF, however it seems to 'lag' in webkit (e.g. my iPhone, see pictures below). I've tried to following to fix the lag:

.mask, .fill {-webkit-backface-visibility: hidden;}

however, it doesn't seem to work. This was the only advice I could find on this issue, that's why I am now asking SO. I hope you guys can help.

Initial state Initial state

showing lag during transition to final state Showing lag during transition to final state

Final stage Final stage. No problems.

Feel free to check-out the lag yourself. (It appears when loading bigger percentages (>60%).)


Solution

  • CSS clip property is deprecated. You can use clip-path instead.

    I tested to find that clip-path works flawlessly on desktop Safari and every web browser on iPhone (Safari, Chrome and embedded browser) but behaves weirdly on desktop Chrome. That's why we are going to use clip-path on iPhone and desktop Safari but use clip on others.

    First, check the browser with javascript:

    var ua = navigator.userAgent.toLowerCase();
    var isIphone = ua.indexOf('iphone') != -1;
    var isSafari = ua.indexOf('safari') != -1 && ua.indexOf('chrome') == -1;
    if (isIphone || isSafari) {
        $('body').addClass('safari');
    }
    

    And change your CSS codes on line 38:

    .mask {
        clip: rect(0px, @circle-size, @circle-size, @circle-size/2);
        .fill {
            clip: rect(0px, @circle-size/2, @circle-size, 0px);
            background-color: @circle-color;
        }
    }
    

    to this:

    .mask {
        clip: rect(0px, @circle-size, @circle-size, @circle-size/2);
        .fill {
            clip: rect(0px, @circle-size/2, @circle-size, 0px);
            background-color: @circle-color;
        }
    
        body.safari & {
            clip: auto;
            -webkit-clip-path: inset(0px 0px 0px @circle-size/2);
            .fill {
                clip: auto;
                -webkit-clip-path: inset(0px @circle-size/2 0px 0px);
            }
        }
    }
    

    You can test by yourself: https://jsfiddle.net/64dtpsba/4/