How can I force WebKit to redraw/repaint to propagate style changes?

后端 未结 27 2176
我寻月下人不归
我寻月下人不归 2020-11-22 02:04

I have some trivial JavaScript to effect a style change:

sel = document.getElementById(\'my_id\');
sel.className = sel.className.replace(/item-[1-9]-selected         


        
相关标签:
27条回答
  • 2020-11-22 02:28

    I had this problem with a a number of divs that were inserted in another div with position: absolute, the inserted divs had no position attribute. When I changed this to position:relative it worked fine. (was really hard to pinpoint the problem)

    In my case the elements where inserted by Angular with ng-repeat.

    0 讨论(0)
  • 2020-11-22 02:28

    The only solution works for me is similar to sowasred2012's answer:

    $('body').css('display', 'table').height();
    $('body').css('display', 'block');
    

    I have a lot of problem blocks on page, so I change display property of root element. And I use display: table; instead of display: none;, because none will reset scrolling offset.

    0 讨论(0)
  • 2020-11-22 02:28

    the "display/offsetHeight" hack didn't work in my case, at least when it was applied to the element being animated.

    i had a dropdown menu that was being open/closed over the page content. the artifacts were being left on the page content after the menu had closed (only in webkit browsers). the only way the "display/offsetHeight" hack worked is if i applied it to the body, which seems nasty.

    however, i did find another solution:

    1. before the element starts animating, add a class that defines "-webkit-backface-visibility: hidden;" on the element (you could also use inline style, i'd guess)
    2. when it's done animating, remove the class (or style)

    this is still pretty hacky (it uses a CSS3 property to force hardware rendering), but at least it only affects the element in question, and worked for me on both safari and chrome on PC and Mac.

    0 讨论(0)
  • 2020-11-22 02:28

    above suggestions didnt work for me. but the below one does.

    Want to change the text inside the anchor dynamically. The word "Search". Created an inner tag "font" with an id attribute. Managed the contents using javascript (below)

    Search
    

    script contents:

        var searchText = "Search";
        var editSearchText = "Edit Search";
        var currentSearchText = searchText;
    
        function doSearch() {
            if (currentSearchText == searchText) {
                $('#pSearch').panel('close');
                currentSearchText = editSearchText;
            } else if (currentSearchText == editSearchText) {
                $('#pSearch').panel('open');
                currentSearchText = searchText;
            }
            $('#searchtxt').text(currentSearchText);
        }
    
    0 讨论(0)
  • 2020-11-22 02:28

    I was having an issue with an SVG that was disappearing on Chrome for Android when the orientation was changed in certain circumstances. The below code doesn't reproduce it, but is the setup we had.

    body {
      font-family: tahoma, sans-serif;
      font-size: 12px;
      margin: 10px;
    }
    article {
      display: flex;
    }
    aside {
      flex: 0 1 10px;
      margin-right: 10px;
      min-width: 10px;
      position: relative;
    }
    svg {
      bottom: 0;
      left: 0;
      position: absolute;
      right: 0;
      top: 0;
    }
    .backgroundStop1 {
      stop-color: #5bb79e;
    }
    .backgroundStop2 {
      stop-color: #ddcb3f;
    }
    .backgroundStop3 {
      stop-color: #cf6b19;
    }
    <article>
      <aside>
        <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="100%" width="100%">
          <defs>
            <linearGradient id="IndicatorColourPattern" x1="0" x2="0" y1="0" y2="1">
              <stop class="backgroundStop1" offset="0%"></stop>
              <stop class="backgroundStop2" offset="50%"></stop>
              <stop class="backgroundStop3" offset="100%"></stop>
            </linearGradient>
          </defs>
          <rect x="0" y="0" rx="5" ry="5" width="100%" height="100%" fill="url(#IndicatorColourPattern)"></rect>
        </svg>
      </aside>
      <section>
        <p>Donec et eros nibh. Nullam porta, elit ut sagittis pulvinar, lacus augue lobortis mauris, sed sollicitudin elit orci non massa. Proin condimentum in nibh sed vestibulum. Donec accumsan fringilla est, porttitor vestibulum dolor ornare id. Sed elementum
          urna sollicitudin commodo ultricies. Curabitur tristique orci et ligula interdum, eu condimentum metus eleifend. Nam libero augue, pharetra at maximus in, pellentesque imperdiet orci.</p>
        <p>Fusce commodo ullamcorper ullamcorper. Etiam eget pellentesque quam, id sodales erat. Vestibulum risus magna, efficitur sed nisl et, rutrum consectetur odio. Sed at lorem non ligula consequat tempus vel nec risus.</p>
      </section>
    </article>

    Day and half later after poking and prodding and not happy with the hacky solutions offered here, I discovered that the issue was caused by the fact it seemed to keep the element in memory while drawing a new one. The solution was to make the ID of the linearGradient on the SVG unique, even though it was only ever used once per page.

    This can be achieved many different ways, but for our angular app we used lodash uniqueId function to add a variable to the scope:

    Angular Directive (JS):

    scope.indicatorColourPatternId = _.uniqueId('IndicatorColourPattern');
    

    HTML Updates:

    Line 5: <linearGradient ng-attr-id="{{indicatorColourPatternId}}" x1="0" x2="0" y1="0" y2="1">

    Line 11: <rect x="0" y="0" rx="5" ry="5" width="100%" height="100%" ng-attr-fill="url(#{{indicatorColourPatternId}})"/>

    I hope this answer saves someone else a days worth of face-smashing their keyboard.

    0 讨论(0)
  • 2020-11-22 02:29

    We recently encountered this and discovered that promoting the affected element to a composite layer with translateZ in CSS fixed the issue without needing extra JavaScript.

    .willnotrender { 
       transform: translateZ(0); 
    }
    

    As these painting issues show up mostly in Webkit/Blink, and this fix mostly targets Webkit/Blink, it's preferable in some cases. Especially since the accepted answer almost certainly causes a reflow and repaint, not just a repaint.

    Webkit and Blink have been working hard on rendering performance, and these kinds of glitches are the unfortunate side effect of optimizations that aim to reduce unnecessary flows and paints. CSS will-change or another succeeding specification will be the future solution, most likely.

    There are other ways to achieve a composite layer, but this is the most common.

    0 讨论(0)
提交回复
热议问题