kenwheeler/slick

Serious bug: Slick Slider turns off subpixel font rendering on the entire site in Chrome

DJviolin opened this issue ยท 9 comments

short description of the bug / issue, provide more detail below.

The fonts looks like this in latest Chrome with Slick Slider's .js file uncommented in my HTML:

slicker-slider-off

However if I re-activate slick slider the subpixel rendering just gone in Chrome:

slicker-slider-on

https://jsfiddle.net/Lanti/pnkogaLz/29/
https://jsfiddle.net/Lanti/pnkogaLz/30/

Steps to reproduce the problem

  1. Make a screenshot from the following Fiddle example in Chrome latest: https://jsfiddle.net/Lanti/pnkogaLz/29/
  2. Insert in Photoshop, zoom in to see pixels.
  3. The subpixel rendering (chromatic abberation around the characters) is gone, when Slick Slider is enabled!
  4. Uncomment the slick slider's init code and the subpixel rendering back again: https://jsfiddle.net/Lanti/pnkogaLz/30/

Needs to be fixed ASAP!!! This causing blurry, bolder text in Chrome.

Can it be an issue in slick.min.css?

UPDATE:

This is happens to be the case when:
a.) Slick slider used with default slick.min.css, no own styling for the slider, as seen at https://jsfiddle.net/Lanti/pnkogaLz/29/.
b.) Slick slider used with my own styling (flexbox layout), but using a <div class="container"> after the <body> tag with the following CSS:

.container {
  display: -webkit-flex; display: flex;
  -webkit-flex-direction: column; flex-direction: column;
}

So, the bug is only presented when either you use with the default CSS or having slick slider in a flexbox layout. Both cases the subpixel font rendering turned off on the entire site in Chrome.

More Details

  • Which browsers/versions does it happen on?

Chrome 50.0.2661.87 m 64bit

  • Which jQuery/Slick version are you using?

Jquery 3.0.0-Beta1
Slick Slider 1.5.9

  • Did this work before?

No, Slick Slider always causing this!

Thanks for finding an interesting CSS quirk in Chrome...

it's caused by the browser splitting layers out to the GPU for 3d transforms...
https://jsfiddle.net/bkf18379/

some people say -webkit-font-smoothing: antialiased; will help, it doesnt for me.
http://stackoverflow.com/questions/12502234/how-to-prevent-webkit-text-rendering-change-during-css-transition

I think you'll find all sliders will cause this, unless they avoid any transforms and use the left properties. You can try to edit the CSS of slick so that there's no transforms.

Best, Simon

Seems like useTransform: false solves the issue. Turning this off causing any side effects in slick's operation?

$('.sidescroll .images').slick({
  dots: false,
  infinite: true,
  speed: 300,
  slidesToShow: 20, // Set at least half of all slides
  centerMode: true,
  initialSlide: 0, // Fix for centerMode with 1
  variableWidth: true,

  arrows: true,
  draggable: true,
  swipeToSlide: true,
  slidesToScroll: 1,
  autoplay: false,
  autoplaySpeed: 3000,

  useTransform: false
});

I experiencing performance drop in rotation with this solution.

Changing translate3d lines to translate in slick.js solves this:

                if (_.options.vertical === false) {
                    //animProps[_.animType] = 'translate3d(' + targetLeft + 'px, 0px, 0px)';
                    animProps[_.animType] = 'translate(' + targetLeft + 'px, 0px)';
                } else {
                    //animProps[_.animType] = 'translate3d(0px,' + targetLeft + 'px, 0px)';
                    animProps[_.animType] = 'translate(0px,' + targetLeft + 'px)';
                }
                _.$slideTrack.css(animProps);

And:

        if (_.transformsEnabled === false) {
            _.$slideTrack.css(positionProps);
        } else {
            positionProps = {};
            if (_.cssTransitions === false) {
                positionProps[_.animType] = 'translate(' + x + ', ' + y + ')';
                _.$slideTrack.css(positionProps);
            } else {
                //positionProps[_.animType] = 'translate3d(' + x + ', ' + y + ', 0px)';
                positionProps[_.animType] = 'translate(' + x + ', ' + y + ')';
                _.$slideTrack.css(positionProps);
            }
        }

I understand that translate3d is slightly faster than translate, but maybe a custom option with 2D transforms for Webkit browsers, activated with a boolean? Until Chrome will not fix this...

Excellent investigative work, gents! It's too bad Chrome has had such a hard time with font rendering.

I feel like since there's already the option to use left by setting useTransform: false, cases where people elect to trade performance for font rendering on chrome is sufficiently satisfied.

There's a lengthy, and fairly active, thread over at the chromium bug tracker. Looks like they're on it, but couldn't hurt to bump it.

If anyone interested in such solution in the future, I managed to automate the translate3d to translate replacement with gulp and regex:

const paths = {
  vendor: [
    'https://raw.githubusercontent.com/kenwheeler/slick/master/slick/slick.js'
  ]
};

gulp.task('vendor', () => {
  return download(paths.vendor)
    .pipe(gulp.dest('public/vendor'));
});

gulp.task('slick', () => {
  return gulp.src(['public/vendor/slick.js'])
    .pipe(replace(
      /animProps\[_\.animType\] = 'translate3d\(' \+ targetLeft \+ 'px, 0px, 0px\)';/igm,
      'animProps[_.animType] = \'translate(\' + targetLeft + \'px, 0px)\'; // FIX BY DJviolin'
    ))
    .pipe(replace(
      /animProps\[_\.animType\] = 'translate3d\(0px,' \+ targetLeft \+ 'px, 0px\)';/igm,
      'animProps[_.animType] = \'translate(0px,\' + targetLeft + \'px)\'; // FIX BY DJviolin'
    ))
    .pipe(replace(
      /positionProps\[_\.animType\] = 'translate3d\(' \+ x \+ ', ' \+ y \+ ', 0px\)';/igm,
      'positionProps[_.animType] = \'translate(\' + x + \', \' + y + \')\'; // FIX BY DJviolin'
    ))
    .pipe(replace(/mozHidden/igm, 'hidden'))
    .pipe(replace(/mozVisibilityState/igm, 'visibilityState'))
    .pipe(uglify({ output: {quote_style: 1} }))
    .pipe(rename({ extname: '.min.js' }))
    .pipe(gulp.dest('public/vendor'));
});

gulp.task('vendors', gulp.series('vendor', 'slick'));

Neat. Only drag is I think it loses hardware acceleration.

Yes, it should be noted, sorry. For really lightweight fonts this is the only way until Chrome will finally fix this. But probably it will take years...

If I want to be more specific, I can put the replacement part into an if-else, where only Webkit browsers getting translate (80% of the browsers, so targeting Firefox not worse it).

Not necessarily a solution, but I did find a quick fix not mentioned here.

Setting -webkit-font-smoothing: subpixel-antialiased (or desired value); works when toggling it in developer tools, however setting it as a fixed value in css to the slide or content did not work for me.

Specifying an animation that set the aliasing after a set amount of time (should be slide transition time) does seem to work.

.slide-content {
    animation-name: render-fix;
    animation-duration: 0.7s;
}

@keyframes render-fix {
    100% {
        -webkit-font-smoothing: subpixel-antialiased;
    }
}

This might not be of help to anyone, and I know this was marked as closed, but I figured I'd share this since it was a quicker fix than some of the more robust solutions above. ยฏ\_(ใƒ„)_/ยฏ

@ktaftaf Im surprised! I thought chrome turned off those browser prefixes.