style examples content attribute css google-chrome safari webkit

css - examples - ¿Cómo puedo forzar a WebKit a volver a dibujar/repintar para propagar cambios de estilo?



title css (25)

Como todos parecen tener sus propios problemas y soluciones, pensé que agregaría algo que funcionara para mí. En Android 4.1 con Chrome actual, tratando de arrastrar un lienzo dentro de un div con desbordamiento: oculto, no podría volver a dibujar a menos que añadiera un elemento al div padre (donde no haría ningún daño).

var parelt = document.getElementById("parentid"); var remElt = document.getElementById("removeMe"); var addElt = document.createElement("div"); addElt.innerHTML = " "; // Won''t work if empty addElt.id="removeMe"; if (remElt) { parelt.replaceChild(addElt, remElt); } else { parelt.appendChild(addElt); }

No hay parpadeo de la pantalla o actualización real, y limpieza después de mí. No hay variables globales o de ámbito de clase, solo locales. No parece afectar nada en los navegadores Mobile Safari / iPad o de escritorio.

Tengo un JavaScript trivial para efectuar un cambio de estilo:

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

Esto funciona bien con las últimas versiones de FF, Opera e IE, pero falla en las últimas versiones de Chrome y Safari.

Afecta a dos descendientes, que resultan ser hermanos. El primer hermano se actualiza, pero el segundo no. Un elemento secundario del segundo elemento también tiene el foco y contiene la etiqueta <a> que contiene el código anterior en un atributo onclick .

En la ventana de "Herramientas de desarrollo" de Chrome, si me doy un codazo (p. Ej., Desmarque y marque) cualquier atributo de cualquier elemento, el segundo hermano se actualiza al estilo correcto.

¿Hay una solución para "Kudge" WebKit de forma fácil y programada para que haga lo correcto?



Descubrí que solo al agregar un estilo de contenido al elemento lo forzaba a volver a pintar, este debería ser un valor diferente cada vez que se desea volver a dibujar y no es necesario que esté en un pseudo elemento.

.selector { content: ''1'' }


Encontré algunas sugerencias complicadas y muchas sencillas que no funcionaron, pero un comentario de Vasil Dinkov que me proporcionó una solución simple para forzar un redibujado / repintado que funciona bien:

sel.style.display=''none''; sel.offsetHeight; // no need to store this anywhere, the reference is enough sel.style.display='''';

Dejaré que alguien más comente si funciona para otros estilos que no sean "bloque".

Gracias, Vasil!


Estaba sufriendo el mismo problema. La corrección de "pantalla de alternancia" de Danorton funcionó para mí cuando se agregó a la función de pasos de mi animación, pero me preocupaba el rendimiento y busqué otras opciones.

En mi circunstancia, el elemento que no se repintaba estaba dentro de un elemento de posición absoluta que, en ese momento, no tenía un índice z. La adición de un índice z a este elemento cambió el comportamiento de Chrome y las repeticiones ocurrieron como se esperaba -> las animaciones se volvieron suaves.

Dudo que esto sea una panacea, imagino que depende de por qué Chrome ha elegido no volver a dibujar el elemento, pero estoy publicando esta solución específica aquí con la ayuda que espera de alguien.

Saludos, Rob

tl; dr >> Intente agregar un índice z al elemento o un elemento primario del mismo.


Estaba teniendo un problema con un SVG que estaba desapareciendo en Chrome para Android cuando se modificó la orientación en ciertas circunstancias. El siguiente código no lo reproduce, pero es la configuración que tuvimos.

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>

Día y medio después de pinchar y pinchar y no estar contento con las soluciones intrépidas que se ofrecen aquí, descubrí que el problema se debía al hecho de que parecía mantener el elemento en la memoria mientras dibujaba uno nuevo. La solución fue hacer que el ID de linearGradient en el SVG fuera único, aunque solo se usara una vez por página.

Esto se puede lograr de muchas maneras diferentes, pero para nuestra aplicación angular usamos la función lodash uniqueId para agregar una variable al alcance:

Directiva Angular (JS):

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

Actualizaciones de HTML:

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

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

Espero que esta respuesta le salve a otra persona un día de destrozar su teclado.


Esto está bien para JS

sel.style.display=''none''; sel.offsetHeight; // no need to store this anywhere, the reference is enough sel.style.display=''block'';

Pero en Jquery, y especialmente cuando solo puede usar $ (document) .ready y no puede vincularse al evento .load de un objeto por un motivo en particular, lo siguiente funcionará.

Debe obtener el contenedor EXTERIOR (MOST) de los objetos / divs y luego eliminar todo su contenido en una variable, luego volver a agregarlo. Hará visibles TODOS los cambios realizados dentro del contenedor externo.

$(document).ready(function(){ applyStyling(object); var node = $("div#body div.centerContainer form div.centerHorizontal").parent().parent(); var content = node.html(); node.html(""); node.html(content); }


Esto parece estar relacionado con esto: el estilo jQuery no se aplica en Safari

La solución sugerida en la primera respuesta me ha funcionado bien en estos escenarios, a saber: aplicar y eliminar una clase ficticia en el cuerpo después de realizar los cambios de estilo:

$(''body'').addClass(''dummyclass'').removeClass(''dummyclass'');

Esto obliga a safari a volver a dibujar.


Estoy trabajando en la aplicación html5 ionica, en algunas pantallas tengo absolute elemento posicionado absolute , cuando se desplaza hacia arriba o hacia abajo en dispositivos IOS (iPhone 4,5,6, 6+) tuve un error de repintado.

Probé muchas soluciones, ninguna de ellas funcionaba, excepto que esta solucionó mi problema.

He usado la clase css .fixRepaint en esos elementos de posiciones absolutas

.fixRepaint{ transform: translateZ(0); }

Esto ha solucionado mi problema, puede ser de ayuda a alguien


He encontrado que este método es útil cuando se trabaja con transiciones

$element[0].style.display = ''table''; $element[0].offsetWidth; // force reflow $element.one($.support.transition.end, function () { $element[0].style.display = ''block''; });


Intenté más respuesta irónica pero no funciona para mí. Tuve problemas para tener el mismo clienteWidth con safari en comparación con otros navegadores y este código resolvió el problema:

var get_safe_value = function(elm,callback){ var sty = elm.style sty.transform = "translateZ(1px)"; var ret = callback(elm)//you can get here the value you want sty.transform = ""; return ret } // for safari to have the good clientWidth var $fBody = document.body //the element you need to fix var clientW = get_safe_value($fBody,function(elm){return $fBody.clientWidth})

Es realmente extraño porque si vuelvo a intentar obtener clientWidth después de get_safe_value, obtengo un valor incorrecto con safari, el getter debe estar entre sty.transform = "translateZ(1px)"; y sty.transform = "";

La otra solución que funciona definitivamente es

var $fBody = document.body //the element you need to fix $fBody.style.display = ''none''; var temp = $.body.offsetHeight; $fBody.style.display = "" temp = $.body.offsetHeight; var clientW = $fBody.clientWidth

El problema es que pierdes el foco y los estados de desplazamiento.


La única solución que funciona para mí es similar a la respuesta de sowasred2012:

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

Tengo muchos bloques de problemas en la página, así que cambio la propiedad de display del elemento raíz. Y uso display: table; en lugar de display: none; , porque none restablecerá el desplazamiento de desplazamiento.


La solución de danorton no funcionó para mí. Tuve algunos problemas realmente extraños donde webkit no dibujaría algunos elementos en absoluto; donde el texto en las entradas no se actualizó hasta onblur; y el cambio de className no daría lugar a un redibujado.

Mi solución, descubrí accidentalmente, era agregar un elemento de estilo vacío al cuerpo, después del script.

<body> ... <script>doSomethingThatWebkitWillMessUp();</script> <style></style> ...

Eso lo arregló. ¿Qué tan raro es eso? Espero que esto sea de ayuda para alguien.


Las sugerencias anteriores no funcionaron para mí. pero el de abajo lo hace.

Quiere cambiar el texto dentro del ancla dinámicamente. La palabra "Buscar". Creó una etiqueta interna "fuente" con un atributo id. Manejó los contenidos usando javascript (abajo)

Search

Contenidos del guión:

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


Los siguientes trabajos. Solo se debe configurar una vez en CSS puro. Y funciona de manera más confiable que una función JS. El rendimiento no parece afectado.

@-webkit-keyframes androidBugfix {from { padding: 0; } to { padding: 0; }} body { -webkit-animation: androidBugfix infinite 1s; }


Me encontré con esto hoy: Element.redraw () para prototype.js

Utilizando:

Element.addMethods({ redraw: function(element){ element = $(element); var n = document.createTextNode('' ''); element.appendChild(n); (function(){n.parentNode.removeChild(n)}).defer(); return element; } });

Sin embargo, a veces he notado que debe llamar a redraw () en el elemento problemático directamente. A veces, volver a dibujar el elemento padre no solucionará el problema que el niño está experimentando.

Buen artículo sobre la forma en que los navegadores representan los elementos: Representación: repintado, reflujo / retransmisión, restauración de estilo


No es que esta pregunta necesite otra respuesta, pero encontré que simplemente cambiar el color en un solo bit forzó un repintado en mi situación particular.

//Assuming black is the starting color, we tweak it by a single bit elem.style.color = ''#000001''; //Change back to black setTimeout(function() { elem.style.color = ''#000000''; }, 0);

El setTimeout resultó crítico para mover el segundo cambio de estilo fuera del bucle de eventos actual.


No puedo creer que esto siga siendo un problema en 2014. Acabo de tener este problema al actualizar un cuadro de subtítulos de posición fija en la parte inferior izquierda de la página mientras se desplaza, el subtítulo "desaparecería" hasta la pantalla. Después de intentar todo lo anterior sin éxito, noté que muchas cosas eran lentas / causaban problemas debido a la creación de relés de salida DOM muy cortos, etc., lo que causaba una sensación poco natural de desplazamiento, etc.

Terminé haciendo una posición fija, div de tamaño completo con pointer-events: none y aplicando la respuesta de danorton a ese elemento, que parece forzar un redibujado en toda la pantalla sin interferir con el DOM.

HTML:

<div id="redraw-fix"></div>

CSS:

div#redraw-fix { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 25; pointer-events: none; display: block; }

JS:

sel = document.getElementById(''redraw-fix''); sel.style.display=''none''; sel.offsetHeight; // no need to store this anywhere, the reference is enough sel.style.display=''block'';


Por alguna razón no conseguí que funcionara la respuesta de Danorton, pude ver qué se suponía que debía hacer, así que lo pellizqué un poco para esto:

$(''#foo'').css(''display'', ''none'').height(); $(''#foo'').css(''display'', ''block'');

Y funcionó para mí.


Recientemente encontramos esto y descubrimos que la promoción del elemento afectado a una capa compuesta con translateZ en CSS solucionó el problema sin necesidad de JavaScript adicional.

.willnotrender { transform: translateZ(0); }

Como estos problemas de pintura aparecen principalmente en Webkit / Blink, y esta solución se dirige principalmente a Webkit / Blink, en algunos casos es preferible. Sobre todo porque la respuesta aceptada casi seguramente causa un reflujo y repintado , no solo un repintado.

Webkit y Blink han estado trabajando arduamente en el rendimiento del renderizado, y este tipo de fallas son el desafortunado efecto secundario de las optimizaciones que apuntan a reducir los flujos y pinturas innecesarios. El cambio de CSS u otra especificación posterior será la solución futura, lo más probable.

Hay otras formas de lograr una capa compuesta, pero esta es la más común.


Recomendaría una forma menos formal y más formal para forzar un reflujo: use forceDOMReflowJS . En su caso, su código se vería de la siguiente manera.

sel = document.getElementById(''my_id''); forceReflowJS( sel ); return false;


Tuve este problema con un número de divs que se insertaron en otro div con position: absolute , los divs insertados no tenían atributo de posición. Cuando cambié esto a la position:relative funcionó bien. (fue realmente difícil de identificar el problema)

En mi caso los elementos fueron insertados por Angular con ng-repeat .


Una solución simple con jquery:

$el.html($el.html());

o

element.innerHTML = element.innerHTML;

Tenía un SVG que no se mostraba cuando se agregó al html.

Esto se puede agregar después de que los elementos svg estén en la pantalla.

Mejor solución es utilizar:

document.createElementNS(''http://www.w3.org/2000/svg'', ''svg'');

y con jQuery:

$(svgDiv).append($(document.createElementNS(''http://www.w3.org/2000/svg'', ''g''));

Esto se procesará correctamente en Chrome.


Vine aquí porque necesitaba volver a dibujar las barras de desplazamiento en Chrome después de cambiar su css.

Si alguien tiene el mismo problema, lo resolví llamando a esta función:

//Hack to force scroll redraw function scrollReDraw() { $(''body'').css(''overflow'', ''hidden'').height(); $(''body'').css(''overflow'', ''auto''); }

Este método no es la mejor solución, pero puede funcionar con todo, ocultando y mostrando el elemento que necesita ser redibujado puede resolver todos los problemas.

Aquí está el violín donde lo usé: http://jsfiddle.net/promatik/wZwJz/18/


el truco "display / offsetHeight" no funcionó en mi caso, al menos cuando se aplicó al elemento que se estaba animando.

Tuve un menú desplegable que estaba siendo abierto / cerrado sobre el contenido de la página. los artefactos se dejaron en el contenido de la página después de que el menú se hubiera cerrado (solo en los navegadores de webkit). La única forma en que funcionó el hack "display / offsetHeight" es si lo aplico al cuerpo, lo que parece desagradable.

Sin embargo, encontré otra solución:

  1. antes de que el elemento comience a animarse, agregue una clase que defina "-webkit-backface-visibilidad: oculta;" en el elemento (también podría usar el estilo en línea, supongo)
  2. Cuando termine de animar, elimina la clase (o estilo)

esto todavía es bastante intrincado (usa una propiedad CSS3 para forzar la representación del hardware), pero al menos solo afecta el elemento en cuestión, y me funcionó tanto en safari como en chrome en PC y Mac.