Переименование/обновление Force DOM на Chrome/Mac

Время от времени Chrome делает абсолютно корректным HTML/CSS неправильно или вообще не работает. Копаться через инспектор DOM достаточно часто, чтобы заставить его осознать ошибку своих путей и правильно перерисовать, так что это доказуемо, что разметка хороша. Это часто случается (и предсказуемо) достаточно в проекте, над которым я работаю, что я установил код, чтобы заставить перерисовать в определенных обстоятельствах.

Это работает в большинстве комбинаций браузера /os:

    el.style.cssText += ';-webkit-transform:rotateZ(0deg)'
    el.offsetHeight
    el.style.cssText += ';-webkit-transform:none'

Как и в, настройте некоторое неиспользуемое свойство CSS, затем попросите некоторую информацию, которая заставляет перерисовать, а затем отключить свойство. К сожалению, яркая команда Chrome для Mac, похоже, нашла способ получить этот offsetHeight без перерисовки. Таким образом, убийство в противном случае полезно взломать.

До сих пор лучшее, что я придумал, чтобы получить тот же эффект от Chrome/Mac, - это часть уродства:

    $(el).css("border", "solid 1px transparent");
    setTimeout(function()
    {
        $(el).css("border", "solid 0px transparent");
    }, 1000);

Как и в самом деле, на самом деле заставить элемент немного перепрыгнуть, а затем охладить секунду и отскочить назад. Ухудшись, если вы потеряете этот тайм-аут ниже 500 мс (там, где он будет менее заметным), он часто не будет иметь желаемого эффекта, так как браузер не будет перерисовываться до того, как он вернется в исходное состояние.

Кто-нибудь хочет предложить лучшую версию этого взлома перерисовывания/обновления (желательно на основе первого примера выше), который работает на Chrome/Mac?

Ответ 1

Не уверен, что именно вы пытаетесь достичь, но это метод, который я использовал в прошлом с успехом, чтобы заставить браузер перерисовать, возможно, он будет работать для вас.

// in jquery
$('#parentOfElementToBeRedrawn').hide().show(0);

// in plain js
document.getElementById('parentOfElementToBeRedrawn').style.display = 'none';
document.getElementById('parentOfElementToBeRedrawn').style.display = 'block';

Если это простое перерисовывание не работает, вы можете попробовать это. Он вставляет пустой текст node в элемент, который гарантирует перерисовку.

var forceRedraw = function(element){

    if (!element) { return; }

    var n = document.createTextNode(' ');
    var disp = element.style.display;  // don't worry about previous display style

    element.appendChild(n);
    element.style.display = 'none';

    setTimeout(function(){
        element.style.display = disp;
        n.parentNode.removeChild(n);
    },20); // you can play with this timeout to make it as short as possible
}

EDIT: В ответ на Šime Vidas то, что мы здесь достигаем, будет вынужденным перепланированием. Вы можете узнать больше от самого мастера http://paulirish.com/2011/dom-html5-css3-performance/

Ответ 2

Ни один из вышеперечисленных ответов не работал у меня. Я заметил, что изменение размера моего окна привело к перерисовке. Так это сделало это для меня:

$(window).trigger('resize');

Ответ 3

Это решение без тайм-аутов! Реальная сила перерисовать! Для Android и iOS.

var forceRedraw = function(element){
  var disp = element.style.display;
  element.style.display = 'none';
  var trick = element.offsetHeight;
  element.style.display = disp;
};

Ответ 4

Мы недавно столкнулись с этим и обнаружили, что продвижение затронутого элемента на составной слой с помощью translateZ устраняет вопрос, не требуя дополнительного javascript.

.willnotrender { 
   transform: translateZ(0); 
}

Поскольку эти проблемы с краской появляются в основном в Webkit/Blink, и это исправление в основном нацелено на Webkit/Blink, оно предпочтительнее в некоторых случаях. Тем более, что многие JavaScript-решения вызывают reflow и перекрашивают, а не только перерисовку.

Ответ 5

Это работает для меня. Кудос идет здесь.

jQuery.fn.redraw = function() {
    return this.hide(0, function() {
        $(this).show();
    });
};

$(el).redraw();

Ответ 6

Скрытие элемента, а затем отображение его снова в пределах setTimeout из 0 приведет к перерисовке.

$('#page').hide();
setTimeout(function() {
    $('#page').show();
}, 0);

Ответ 7

вызов window.getComputedStyle() должен принудительно выполнить оплату

Ответ 8

Кажется, это трюк для меня. Кроме того, это действительно не отображается вообще.

$(el).css("opacity", .99);
setTimeout(function(){
   $(el).css("opacity", 1);
},20);

Ответ 9

Сегодня я столкнулся с этой проблемой в OSX El Capitan с Chrome v51. Эта страница работала нормально в Safari. Я пробовал почти каждое предложение на этой странице - никто не работал правильно - у всех были побочные эффекты... Я закончил реализацию кода ниже - супер простого - никаких побочных эффектов (по-прежнему работает как и раньше в Safari).

Решение. При необходимости переключите класс на проблемный элемент. Каждый переключатель заставит перерисовать. (Я использовал jQuery для удобства, но ванильный JavaScript не должен быть проблемой...)

jQuery Class Toggle

$('.slide.force').toggleClass('force-redraw');

Класс CSS

.force-redraw::before { content: "" }

И что это...

ПРИМЕЧАНИЕ. Чтобы увидеть эффект, вам нужно запустить фрагмент ниже "Полная страница".

$(window).resize(function() {
  $('.slide.force').toggleClass('force-redraw');
});
.force-redraw::before {
  content: "";
}
html,
body {
  height: 100%;
  width: 100%;
  overflow: hidden;
}
.slide-container {
  width: 100%;
  height: 100%;
  overflow-x: scroll;
  overflow-y: hidden;
  white-space: nowrap;
  padding-left: 10%;
  padding-right: 5%;
}
.slide {
  position: relative;
  display: inline-block;
  height: 30%;
  border: 1px solid green;
}
.slide-sizer {
  height: 160%;
  pointer-events: none;
  //border: 1px solid red;

}
.slide-contents {
  position: absolute;
  top: 10%;
  left: 10%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<p>
  This sample code is a simple style-based solution to maintain aspect ratio of an element based on a dynamic height.  As you increase and decrease the window height, the elements should follow and the width should follow in turn to maintain the aspect ratio.  You will notice that in Chrome on OSX (at least), the "Not Forced" element does not maintain a proper ratio.
</p>
<div class="slide-container">
  <div class="slide">
    <img class="slide-sizer" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">
    <div class="slide-contents">
      Not Forced
    </div>
  </div>
  <div class="slide force">
    <img class="slide-sizer" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">
    <div class="slide-contents">
      Forced
    </div>
  </div>
</div>

Ответ 10

Если вы хотите сохранить стили, объявленные в ваших таблицах стилей, лучше использовать что-то вроде:

jQuery.fn.redraw = function() {
    this.css('display', 'none'); 
    var temp = this[0].offsetHeight;
    this.css('display', '');
    temp = this[0].offsetHeight;
};

$('.layer-to-repaint').redraw();

NB: с последним webkit/blink сохранение значения offsetHeight является обязательным для запуска перерисовки, иначе VM (для целей оптимизации), вероятно, пропустит эту инструкцию.

Обновление: добавлено второе чтение offsetHeight, необходимо, чтобы браузер не запускал/кэшировал следующий CSS-свойство/изменение класса с восстановлением значения display (таким образом, переход CSS, который может следовать, должен быть оказываемых)

Ответ 11

Пример Html:

<section id="parent">
  <article class="child"></article>
  <article class="child"></article>
</section>

Js:

  jQuery.fn.redraw = function() {
        return this.hide(0,function() {$(this).show(100);});
        // hide immediately and show with 100ms duration

    };

функция вызова:

$('article.child').redraw();//< == bad idea

$('#parent').redraw();

Ответ 12

function resizeWindow(){
    var evt = document.createEvent('UIEvents');
    evt.initUIEvent('resize', true, false,window,0);
    window.dispatchEvent(evt); 
}

вызывает эту функцию через 500 миллисекунд.

Ответ 13

Подход, который работал у меня в IE (я не мог использовать технику отображения, потому что был вход, который не должен потерять фокус)

Он работает, если у вас есть 0 полей (также меняется изменение отступов)

if(div.style.marginLeft == '0px'){
    div.style.marginLeft = '';
    div.style.marginRight = '0px';
} else {
    div.style.marginLeft = '0px';
    div.style.marginRight = '';
}

Ответ 14

Только CSS. Это работает для ситуаций, когда дочерний элемент удаляется или добавляется. В этих ситуациях границы и закругленные углы могут оставлять артефакты.

el:after { content: " "; }
el:before { content: " "; }

Ответ 15

Мое исправление для IE10 + IE11. В основном происходит то, что вы добавляете DIV в элемент wrapping, который должен быть пересчитан. Тогда просто удалите его и вуаля; работает как шарм:)

    _initForceBrowserRepaint: function() {
        $('#wrapper').append('<div style="width=100%" id="dummydiv"></div>');
        $('#dummydiv').width(function() { return $(this).width() - 1; }).width(function() { return $(this).width() + 1; });
        $('#dummydiv').remove();
    },

Ответ 16

В большинстве ответов требуется использование асинхронного таймаута, что вызывает раздражающий мигание.

Но я придумал этот, который работает плавно, потому что он синхронен:

var p = el.parentNode,
    s = el.nextSibling;
p.removeChild(el);
p.insertBefore(el, s);

Ответ 17

Это мое решение, которое работало для исчезновения контента...

<script type = 'text/javascript'>
    var trash_div;

    setInterval(function()
    {
        if (document.body)
        {
            if (!trash_div)
                trash_div = document.createElement('div');

            document.body.appendChild(trash_div);
            document.body.removeChild(trash_div);
        }
    }, 1000 / 25); //25 fps...
</script>

Ответ 18

У меня возникла аналогичная проблема, и эта простая строка JS помогла исправить ее:

document.getElementsByTagName('body')[0].focus();

В моем случае это была ошибка с расширением Chrome, не перерисовывавшим страницу после изменения CSS изнутри расширения.

Ответ 19

Я хотел вернуть все состояния в предыдущее состояние (без перезагрузки), включая элементы, добавленные jquery. Вышеуказанная реализация не сработает. и я сделал следующее.

// Set initial HTML description
var defaultHTML;
function DefaultSave() {
  defaultHTML = document.body.innerHTML;
}
// Restore HTML description to initial state
function HTMLRestore() {
  document.body.innerHTML = defaultHTML;
}



DefaultSave()
<input type="button" value="Restore" onclick="HTMLRestore()">

Ответ 20

У меня был список реагирующих компонентов, который при прокрутке открывал другую страницу, затем при возврате список не отображался в Safari iOS до прокрутки страницы. Так что это исправление.

    componentDidMount() {
        setTimeout(() => {
            window.scrollBy(0, 0);
        }, 300);
    }

Ответ 21

Ниже CSS работает на IE 11 и Edge, JS не требуется. scaleY(1) здесь. Кажется самое простое решение.

.box {
    max-height: 360px;
    transition: all 0.3s ease-out;
    transform: scaleY(1);
}
.box.collapse {
    max-height: 0;
}