Material: Angular Material very slow in IE 11

Created on 4 May 2016  路  24Comments  路  Source: angular/material

I've overhauled our application using world's finest Angular Material. It works fast on Chrome and Firefox.

  • Problem is, it is running slow on IE 11
  • Expected behavior should be the same as the 2 browsers

Below is the gif which illustrates the behavior of our application if run in Chrome:
animation_chrome

Below is the gif which illustrates the behavior of our application if run in IE 11:
animation

Issue Details:

  • Slow performance
  • Left menu items have inconsistent padding
  • mdDialog displays normal in Chrome, but not in IE

Angular Versions / Relevant Script used:

Additional Information:

  • Browser Type: IE
  • Browser Version: 11
  • OS: Windows 7
critical IE performance ink

Most helpful comment

Hi,

May I know the current status of this? Just for information purposes.

I'm thankful my project has been deferred, for a while. Not sure when it will commence, but much better if the application will be ready/stable/cross-browser compatible.

Thank you in advance! Happy to be part of this masterpiece :)

Cheers,

All 24 comments

+1. Very low performance on any animated transitional behaviour

@mtorres0612 Have a look here #8218 and here https://github.com/angular/material/issues/864#issuecomment-200325064

This works wonders on my side for performance problems.

Try to disable animations aswell as ripple effects.
They can be disabled on the root element
<body md-no-ink>

@berndvdveen - thanks for the info. found any workaround on this?
@graphefruit - thank you for the information! In line with this, what am I expecting? a 100% lag-free AM website in IE11?

If in that case yes, then here are the details of my test:

  • applied $scope.constant... fix related to #8218
  • applied
  • results:

    • navigating through different views improved

    • mdDialog popup behavior still lags

    • Tabs also lag when switching between tabs

What else should I apply?

Thank you in advance guys.

@mtorres0612 100% lag-free? I don't know, try it and you'll see. I reduced my load times from 11 seconds to 4-5 seconds on page navigation in my cordova-app on WP8.

With this fixes you disable all transitions (which I disabled in this CSS, need to be changed in RC-4 because of private classes).
Also you disable all ripple-effects which is causing terrible performance problems.
Transitions you can find with the Google-Chrome debugger "Animations".

For sure you'll get performance, and thats what you want right?

Update:
Also make sure you decimate watchers (one-time-bindings) and disable the debug-information: $debugInfo
With this line you cant access the scope via JavaScript angular.element(document).scope()

This takes lot of times but will pay.

@mtorres0612
Here is my CSS fix, also box-shadows remove improving the performance drastically, because the box-shadows need to be rerenderd. If you want box-shadows take borders.
This animations don't contain all elements maybe you need to find some more alone.

/*
 ******************************************
 ******************************************
   Disable animations
 ******************************************
 ******************************************
*/

/** disable transitions and animations for tab-contents**/
md-tab-content.md-right:not(.md-active) {
    animation: none;
    -webkit-animation: none;
}

md-tab-content.md-left:not(.md-active) {
    animation: none;
    -webkit-animation: none;
}

md-tab-content.md-left:not(.md-active) * {
    transition: none !important;
    transition-duration: 0ms !important;
    transition-delay: 0ms !important;
}

md-tab-content.md-right:not(.md-active) * {
    transition: none !important;
    transition-duration: 0ms !important;
    transition-delay: 0ms !important;
}

.md-tab {
    transition: none !important;
    transition-duration: 0ms !important;
    transition-delay: 0ms !important;
}

/**disable slider animation for thumbs **/
md-slider .md-focus-thumb {
    transition: none !important;
    transition-duration: 0ms !important;
    transition-delay: 0ms !important;
    animation: none !important;
    -webkit-animation: none !important;
}
md-slider ._md-thumb{
     transition: none !important;
    transition-duration: 0ms !important;
    transition-delay: 0ms !important;
}
md-option{

     transition: none !important;
    transition-duration: 0ms !important;
    transition-delay: 0ms !important;
}
/*Disable transition for opening menu.*/

/**disable on dialogs**/
md-dialog._md-transition-out {
    transition: none !important;
    transition-duration: 0ms !important;
    transition-delay: 0ms !important;
}

md-dialog._md-transition-in {
    transition: none !important;
    transition-duration: 0ms !important;
    transition-delay: 0ms !important;
}

/**Disable on ripple buttons**/
.md-ripple.md-ripple-placed {
    transition: none !important;
    transition-duration: 0ms !important;
    transition-delay: 0ms !important;
}

.md-ripple-container, .md-ripple-placed {
    transition: none !important;
    transition-duration: 0ms !important;
    transition-delay: 0ms !important;
}

/**Disable checkbox **/
md-checkbox ._md-icon {
    transition: none !important;
    transition-duration: 0ms !important;
    transition-delay: 0ms !important;
}

md-tabs-wrapper md-next-button, md-tabs-wrapper md-prev-button
{
     transition: none !important;
    transition-duration: 0ms !important;
    transition-delay: 0ms !important;
}

md-pagination-wrapper {
    transition: none !important;
    transition-duration: 0ms !important;
    transition-delay: 0ms !important;
}

._md-subheader-wrapper:not(.md-sticky-no-effect) {
    transition: none !important;
    transition-duration: 0ms !important;
    transition-delay: 0ms !important;
}

._md-sticky-clone[sticky-state=active]:not(.md-sticky-no-effect) ._md-subheader-inner {
    -webkit-animation: none !important;
    animation: none !important;
}

/**Disable on all other buttons**/
.md-button {
    transition: none !important;
    transition-duration: 0ms !important;
    transition-delay: 0ms !important;
}

/**Disable fading labels**/
md-input-container label {
    transition: none !important;
    transition-duration: 0ms !important;
    transition-delay: 0ms !important;
}

/** Disable slider animations**/
md-slider ._md-thumb-container, ._md-focus-ring, ._md-track-fill, ._md-thumb {
    transition: none !important;
    transition-duration: 0ms !important;
    transition-delay: 0ms !important;
}

md-input-container .md-char-counter, md-input-container .md-input-message-animation {
    transition: none !important;
}

/*  Disable dropdown animations*/

md-select-menu {
    transition: none !important;
    transition-duration: 0ms !important;
    transition-delay: 0ms !important;
}

md-select-menu md-content {
    transition: none !important;
    transition-duration: 0ms !important;
    transition-delay: 0ms !important;
}

._md-select-menu-container._md-leave {
    transition: none !important;
    transition-duration: 0ms !important;
    transition-delay: 0ms !important;
}

md-tab-content {
    -webkit-transition: none !important;
    -moz-transition: none !important;
    -ms-transition: none !important;
    -o-transition: none !important;
    transition: none !important;
}

md-ink-bar.md-right {
    -webkit-transition: none !important;
    -moz-transition: none !important;
    -ms-transition: none !important;
    -o-transition: none !important;
    transition: none !important;
}

md-ink-bar.md-left {
    -webkit-transition: none !important;
    -moz-transition: none !important;
    -ms-transition: none !important;
    -o-transition: none !important;
    transition: none !important;
}

md-tab-content.md-right {
    -webkit-transition: none !important;
    -moz-transition: none !important;
    -ms-transition: none !important;
    -o-transition: none !important;
    transition: none !important;
}

md-tab-content.md-left {
    -webkit-transition: none !important;
    -moz-transition: none !important;
    -ms-transition: none !important;
    -o-transition: none !important;
    transition: none !important;
}

/*
 ******************************************
 ******************************************
   Disable box shadows
 ******************************************
 ******************************************
*/

md-card {
    border: 1px solid rgba(0, 0, 0, .14) !important;
    box-shadow: none !important;
    -webkit-box-shadow: none !important;
    -moz-box-shadow: none !important;
}

md-dialog {
    border: 1px solid rgba(0, 0, 0, .14) !important;
    box-shadow: none !important;
    -webkit-box-shadow: none !important;
    -moz-box-shadow: none !important;
}

md-select-menu {
    border: 1px solid rgba(0, 0, 0, .14) !important;
    box-shadow: none !important;
    -webkit-box-shadow: none !important;
    -moz-box-shadow: none !important;
}

.md-button.md-raised {
    border: 1px solid rgba(0, 0, 0, .14) !important;
    box-shadow: none !important;
    -webkit-box-shadow: none !important;
    -moz-box-shadow: none !important;
}

md-toast .md-toast-content {
    /**no border needed here**/
    box-shadow: none !important;
    -webkit-box-shadow: none !important;
    -moz-box-shadow: none !important;
}

@graphefruit - sorry for the very late reply. I was given other tasks that's why I failed to respond swiftly.
Anyway, thank you for your information on this! Will test it immediately with my application. Will let you know the status of this the soonest.

Cheers

+1

@graphefruit - again, sorry for the long wait. Finally! I've tested again my application after adding above CSS tweaks. Noticeable results:

UI:

  • Shadows removed for cards and dialogs; replaced instead by borders
  • Removed animation in floating labels, Select, and tab switches
  • Removed ripple effect in menus
  • mdDialog not centered (included in observations, but should be in a separate issue perhaps)

Performance:

  • Way faster than before; kudos to the removal of cutting-edge animations (makes me feel sad, though)
  • Lag percentage = before tweak: 80%; after tweak: 30%; Still lags, especially when performing XHRs

DEMO:
animation

Credits to you @graphefruit on this one. What a great tweak.

While this is great, still hoping that AM fully performs normally in IE11, just as the way it behaves in Chrome and Firefox. IE sucks, says my mentor years ago.

Cheers,

@mtorres0612 Your welcome, I'm glad it helped out. Some more points here:
Did you overwrote $MD_THEME_CSS aswell with: $provide.constant('$MD_THEME_CSS', '');
And copy the content into an own stylesheet and include it?

Did you also disable the debugInfo?

Also track your watchers and try to reduce them (PS: This is not working if you're disabling the debug information $compileProvider.debugInfoEnabled(true);)

var logWatches = function () {
        setInterval(function () {

            (function () {
                var root = angular.element(document.getElementsByTagName('body'));

                var watchers = [];

                var f = function (element) {
                    angular.forEach(['$scope', '$isolateScope'], function (scopeProperty) {
                        if (element.data() && element.data().hasOwnProperty(scopeProperty)) {
                            angular.forEach(element.data()[scopeProperty].$$watchers, function (watcher) {
                                watchers.push(watcher);
                            });
                        }
                    });

                    angular.forEach(element.children(), function (childElement) {
                        f(angular.element(childElement));
                    });
                };

                f(root);

                // Remove duplicate watchers
                var watchersWithoutDuplicates = [];
                angular.forEach(watchers, function (item) {
                    if (watchersWithoutDuplicates.indexOf(item) < 0) {
                        watchersWithoutDuplicates.push(item);
                    }
                });

                console.log("Watcher:" + watchersWithoutDuplicates.length);
            })();

        }, 1000);
    }

If you want to know what is realy watched have a look on watchersWithoutDuplicates

Also it looks like in your last demo that some ripple/animation effects are still in use.
If you want to get rid of them, install chrome and track down the animations.
Have a look for it here: https://www.youtube.com/watch?v=U9xfYbKxosI

Update: Also use one-time-bindins in your ng-repeat, the trick is to set your repeat variable to undefined, and define an ng-if. The undefined doesn't dismiss the watcher, when the variable is out of the undefined state, the watcher gets destroyed.
ng-if="::(array!=undefined?true:undefined)" ng-repeat="obj in ::array"
If you cant use a one-time-binding in your ng-repeat, do it below in your bindings
<div>{{::value}}</div>

Also if you got large sets to render use virtual-repeat instead of normal ng-repeat.

If needed we can do a short hangout cast aswell.

Greetings
Graphefruit

@graphefruit - hi! sorry for the year-long response, just busy 9gagging (kidding). Thank you for the information. I won't be providing screencasts since it is hard to illustrate the changes just by showing gifs (in this state).

  • Already did $provide.constant('$MD_THEME_CSS', '');. Also manually added the styles removed in the process
  • Already applied $compileProvider.debugInfoEnabled(false);
  • Didn't apply one-time-bindins since limited data are involved (as of now), but will apply it in the future

Observations/Results:

  • my AM app is performing at an 'acceptable' level : meaning an average joe will have goosebumps with state-of-the-art technology the app has, which is great :)
  • last lag percentage mentioned: 30%; now: down to 5-10%

Thoughts:

  • Is there a possibility that AM will perform 100% in IE11, the same way it does in Chrome? Sorry if I'm not checking for any works in progress related to this

Again, thank you @graphefruit for your efforts to accommodate inquiries from a newbie.

Cheers,

@ThomasBurleson @crisbeto - Thank you for acknowledging this one :+1:

@mtorres0612 Your welcome, glad I can help.
After I'm still digging for performance I found some more points:

  1. JS: Replacing unneeded $interval or $timeout with the normal "native" JavaScript events:
    setInterval,setTimeout made less promise-calls and speed up.
  2. JS: Using requestAnimationFrame instead setTimeout (speeded some functions up from 140 to 30ms.
    Care on this 2 methods, maybe you need to trigger $scope.$apply / asyncApply yourself.
    You'll get more performance because the promises will not trigger all day long.
    You can debug this very good on IE if you do a breakpoint in your angular.js to see which one triggers
    self.defer = function(fn, delay) {
            var timeoutId;
            outstandingRequestCount++;
            timeoutId = setTimeout(function() {
                delete pendingDeferIds[timeoutId];
                completeOutstandingRequest(fn);
            }, delay || 0);
            pendingDeferIds[timeoutId] = true;
            return timeoutId;
        };
  1. JS: $httpProvider.useApplyAsync(true); https://docs.angularjs.org/api/ng/provider/$httpProvider
  2. AM - CSS: Remove the border-radius, IE has performance issues with repainting here.
.md-button {
    border-radius:0px!important;
}
.md-toast-content {
    border-radius: 0px !important;

md-dialog {
    border-radius: 0px !important;
}
md-card {
    border-radius:0px;
}

_Repaint:_ Specally IE has repaint problems. Your JavaScript can affect this aswell.
So maybe you force the layout to repaint all day long (if you set them or get them) e.g. repaint
There are 20 more articles for position:fixed etc.

Greetings

PS: Did you found some other things aswell? After you said you came down from 30% to 5-10%?

@graphefruit - thank you for this wonderful information!

Here's a quick feedback of how I implemented the 4 items you mentioned:

  1. _"Replacing unneeded $interval..."_ - I guess no need to do this one for me; I'm not currently using this.
  2. _"Using requestAnimationFrame"_ - Sorry if my AM level is weak but how should I correctly do this? An example use will do, not the actual code that I will write. I modified the latest angular.js, but this is giving me errors:

BEFORE:

self.defer = function(fn, delay) {
            var timeoutId;
            outstandingRequestCount++;
            timeoutId = setTimeout(function() {
                delete pendingDeferIds[timeoutId];
                completeOutstandingRequest(fn);
            }, delay || 0);//EXISTING
            pendingDeferIds[timeoutId] = true;
            return timeoutId;
        };

AFTER:

self.defer = function (fn, delay) {
      var timeoutId;
      outstandingRequestCount++;
      timeoutId = requestAnimationFrame(repeatOften(timeoutId, fn));//MODIFIED; INSIDE repeatOften ARE THE 2 STATEMENTS INSIDE SETTIMEOUT BEFORE
      pendingDeferIds[timeoutId] = true;
      return timeoutId;
  };
  1. _"$httpProvider.useApplyAsync(true);"_ - DONE
  2. _"Remove the border-radius..."_ - DONE

RESULTS:

  • Even though I haven't applied item#2, My app performed even faster ($httpProvider.useApplyAsync) played a significant role here, for me
  • Lag percentage: just less than or equal to 5%

THOUGHTS:

  • Other things? like findings? Yes I have:

    • Lag while <div> is adjusting its height upon switching Tabs

    • Lag while sorting in Daniel Nagy's data table

  • AM got no love from IE11 hahaha.. We aren't supposed to be doing this if IE doesn't suck, at least.. That's why I can't close this yet

@graphefruit - again thank you for this. Big fan here so I've been checking this asap on my wee time

Cheers,

@crisbeto - next week, let's discuss how to get the IE perf improvements into ngM1 for v1.1.0.

Hello @ThomasBurleson if I can help you here just give me a bump.

@graphefruit - can you email with direct message [email protected]. I have some ideas to suggest...

Hi,

May I know the current status of this? Just for information purposes.

I'm thankful my project has been deferred, for a while. Not sure when it will commence, but much better if the application will be ready/stable/cross-browser compatible.

Thank you in advance! Happy to be part of this masterpiece :)

Cheers,

Hi @mtorres0612 ,
My actual understanding is that there will be a documentation and small code fixes (ripple effect e.g.)
The user needs to insert this data in his app/website himself then.
Have a look here: https://github.com/angular/material/commit/ea62bc2de4dc09e0d7095b6f96d0746d20baa14a

Tab performance has been significantly improved. Fixed.

Hi @ThomasBurleson ,

My conclusion was that the main problem at least in my applications are the layout calculations.
Somehow, ie11 is overwhelmed by the css of angular material. Even if you make a md-list of 40 items with icons inside them where a click on the icon opens a md-dialog with a hello world string, it will be slow.
I am not sure that in the scope of angular material 1 there is something which can be done, but hope that this may be addressed in material 2. Another option would be that microsoft will release a better html engine which will be on the scale of webkit but i am not really optimistic :-)

Thanks a lot,
David

@david-gang I would really appreciate a codepen/demo of IE being slow, otherwise it's hard to pinpoint the issue. We decided to close this because the only instance I've found IE to be really slow was on 1.0.9 and a certain config of md-tabs, but that was addressed by @topherfangio and isn't an issue in 1.1.

Hi,

Sure :-)

http://codepen.io/david-gang/pen/RRJjxG

If you open this in ie11 and click on the icons you willl see slowness.
This is basically a md-list with not too much content.

Thanks,
David

Alright, this should be easier to benchmark. I'll reopen it.

Just a side notice:
I found out that the CSS files realy had more then 55k lines (material + theme)
Thats realy a huge factor for the IE11 engine.
After I test stripped the CSS down to actually 4k lines (painly road), even my android and iOS app are starting even more faster.
Sadly the rendering process for 20 list-items still need more then 2 seconds on a Windows Phone 10.

@crisbeto - let's open a new issue with David's codepen.
@graphefruit - please submit a new issue with your recent comment/issue. I think the mdList may need an overhaul.

Was this page helpful?
0 / 5 - 0 ratings