Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
DJviolin opened this issue Apr 24, 2016 · 9 comments

Comments

@DJviolin
Copy link

DJviolin commented Apr 24, 2016

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!

@DJviolin DJviolin changed the title Serious bug: Slick Slider turns off subpixel font rendering in Chrome Serious bug: Slick Slider turns off subpixel font rendering in Chrome on the entire site Apr 24, 2016
@DJviolin DJviolin changed the title Serious bug: Slick Slider turns off subpixel font rendering in Chrome on the entire site Serious bug: Slick Slider turns off subpixel font rendering on the entire site in Chrome Apr 24, 2016
@simeydotme
Copy link
Collaborator

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

@DJviolin
Copy link
Author

DJviolin commented Apr 24, 2016

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.

@DJviolin
Copy link
Author

DJviolin commented Apr 24, 2016

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...

@leggomuhgreggo
Copy link
Collaborator

leggomuhgreggo commented Apr 24, 2016

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.

@DJviolin
Copy link
Author

DJviolin commented Jul 15, 2016

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'));

@leggomuhgreggo
Copy link
Collaborator

leggomuhgreggo commented Jul 15, 2016

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

@DJviolin
Copy link
Author

DJviolin commented Jul 15, 2016

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).

@ktaftaf
Copy link

ktaftaf commented Nov 21, 2016

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. ¯\_(ツ)_/¯

@leggomuhgreggo
Copy link
Collaborator

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants