Eu tenho algum JavaScript trivial para efetuar uma alteração de estilo:
sel = document.getElementById('my_id');
sel.className = sel.className.replace(/item-[1-9]-selected/,'item-1-selected');
return false;
Isso funciona bem com as versões mais recentes do FF, Opera e IE, mas falha nas versões mais recentes do Chrome e Safari.
Afeta dois descendentes, que são irmãos. O primeiro irmão é atualizado, mas o segundo não. Um filho do segundo elemento também tem foco e contém a tag <a> que contém o código acima em um atributo onclick .
Na janela "Ferramentas do desenvolvedor" do Chrome, se eu cutucar (por exemplo, desmarcar e marcar) qualquer atributo de qualquer elemento, o segundo irmão será atualizado para o estilo correto.
Existe uma solução alternativa para "fácil" e de forma programática "induzir" o WebKit a fazer a coisa certa?
css
google-chrome
safari
webkit
danorton
fonte
fonte
Respostas:
Encontrei algumas sugestões complicadas e muitas simples que não funcionaram, mas um comentário de Vasil Dinkov a uma delas forneceu uma solução simples para forçar um redesenho / repintura que funciona muito bem:
Vou deixar outra pessoa comentar se funcionar para outros estilos além de "bloquear".
Obrigado, Vasil!
fonte
'inline-block'
, tente'table'
ou'run-in'
não'none'
, mas isso pode ter efeitos colaterais. Além disso, um tempo limite de 0 aciona um reflow, assim como a consultaoffsetHeight
:sel.style.display = 'run-in'; setTimeout(function () { sel.style.display = 'block'; }, 0);
Recentemente, descobrimos isso e descobrimos que a promoção do elemento afetado para uma camada composta com translateZ em CSS corrigia o problema sem a necessidade de JavaScript extra.
Como esses problemas de pintura aparecem principalmente no Webkit / Blink, e essa correção visa principalmente o Webkit / Blink, é preferível em alguns casos. Especialmente porque a resposta aceita quase certamente causa um reflow e repintar , não apenas repintar.
O Webkit e o Blink têm trabalhado duro no desempenho da renderização e esses tipos de falhas são o infeliz efeito colateral das otimizações que visam reduzir fluxos e tintas desnecessários. A mudança de CSS ou outra especificação subsequente será a solução futura, provavelmente.
Existem outras maneiras de obter uma camada composta, mas essa é a mais comum.
fonte
A solução danorton não funcionou para mim. Eu tive alguns problemas realmente estranhos nos quais o webkit não desenhava alguns elementos; onde o texto nas entradas não foi atualizado até o onblur; e alterar className não resultaria em um redesenho.
Descobri acidentalmente que minha solução era adicionar um elemento de estilo vazio ao corpo, após o script.
Isso consertou. Quão estranho é isso? Espero que isso seja útil para alguém.
fonte
var div = $('<div>').appendTo(element); setTimeout(function(){ div.remove(); }, 0);
$('<style></style>').appendTo($(document.body)).remove();
Como o gatilho display + offset não funcionou para mim, encontrei uma solução aqui:
http://mir.aculo.us/2009/09/25/force-redraw-dom-technique-for-webkit-based-browsers/
ie
fonte
scale(1)
, atribuí-o a si mesmo comoelement.style.webkitTransform = element.style.webkitTransform
. A razão para isso é que configurá-lo para o anterior estava distorcendo a página ligeiramente paraabsolute
elementos posicionados!display
solução fez.Eu estava sofrendo o mesmo problema. A correção 'alternar exibição' do danorton funcionou para mim quando adicionada à função step da minha animação, mas eu estava preocupada com o desempenho e procurei outras opções.
Na minha circunstância, o elemento que não estava pintando estava dentro de um elemento absolutamente de posição que, na época, não possuía um índice z. A adição de um índice z a esse elemento alterou o comportamento do Chrome e as repetições ocorreram conforme o esperado -> as animações se tornaram suaves.
Duvido que isso seja uma panacéia, imagino que depende do motivo pelo qual o Chrome optou por não redesenhar o elemento, mas estou postando esta solução específica aqui na ajuda que ele espera de alguém.
Cheers, Rob
tl; dr >> Tente adicionar um índice z ao elemento ou a um pai dele.
fonte
Os seguintes trabalhos. Ele só precisa ser definido uma vez em CSS puro. E funciona de maneira mais confiável que uma função JS. O desempenho parece não ser afetado.
fonte
zoom
vez de preenchimento:@-webkit-keyframes safariBugFix {from { zoom: 100%; } to { zoom: 99.99999%; }}
Por alguma razão, não consegui que a resposta de danorton funcionasse, pude ver o que era para fazer, então ajustei um pouco isso:
e funcionou para mim.
fonte
Eu vim aqui porque precisava redesenhar as barras de rolagem no Chrome depois de alterar o css.
Se alguém está tendo o mesmo problema, resolvi-o chamando esta função:
Esse método não é a melhor solução, mas pode funcionar com tudo, ocultar e mostrar o elemento que precisa ser redesenhado pode resolver todos os problemas.
Aqui está o violino onde eu o usei: http://jsfiddle.net/promatik/wZwJz/18/
fonte
Eu me deparei com isso hoje: Element.redraw () para prototype.js
Usando:
No entanto, notei às vezes que você deve chamar redraw () no elemento problemático diretamente. Às vezes, redesenhar o elemento pai não resolverá o problema que o filho está enfrentando.
Bom artigo sobre como os navegadores renderizam elementos: Renderização: repintar, refluir / retransmitir, restyle
fonte
appendChild
é um método DOM, não um método jQuery.Eu tive esse problema com um número de divs que foram inseridos em outra div com
position: absolute
, as divs inseridas não tinham atributo de posição. Quando eu mudei issoposition:relative
, funcionou bem. (foi realmente difícil identificar o problema)No meu caso, os elementos foram inseridos pelo Angular com
ng-repeat
.fonte
Não posso acreditar que isso ainda é um problema em 2014. Acabei de ter esse problema ao atualizar uma caixa de legenda de posição fixa na parte inferior esquerda da página durante a rolagem, a legenda seria 'fantasma' na tela. Depois de tentar tudo o que foi descrito acima sem sucesso, notei que muitas coisas estavam lentas / causando problemas devido à criação de relayouts DOM muito curtos, etc, causando uma sensação pouco natural de rolagem, etc.
Acabei fazendo uma posição fixa, div em tamanho real
pointer-events: none
e aplicando a resposta de danorton a esse elemento, que parece forçar um redesenho em toda a tela sem interferir no DOM.HTML:
CSS:
JS:
fonte
z-index
epointer-events
são supérfluas aqui.Não que essa pergunta precise de outra resposta, mas descobri que simplesmente mudar a cor um pouco forçou a redesenhar em minha situação específica.
O resultado
setTimeout
foi crítico para mover a segunda mudança de estilo para fora do loop de eventos atual.fonte
A única solução que funciona para mim é semelhante à resposta de sowasred2012:
Como tenho muitos bloqueios de problemas na página, altero a
display
propriedade do elemento raiz. E eu uso emdisplay: table;
vez dedisplay: none;
, porquenone
irá redefinir o deslocamento da rolagem.fonte
Eu uso o
transform: translateZ(0);
método, mas em alguns casos não é suficiente.Eu não sou fã de adicionar e remover uma classe, então tentei encontrar uma maneira de resolver isso e acabei com um novo hack que funciona bem:
fonte
Como todo mundo parece ter seus próprios problemas e soluções, achei que acrescentaria algo que funcione para mim. No Android 4.1 com o Chrome atual, tentando arrastar uma tela dentro de uma div com estouro: oculto, não era possível redesenhar a menos que eu adicionasse um elemento à div pai (onde isso não causaria nenhum dano).
Nenhuma cintilação na tela ou atualização real e limpeza depois de mim. Não há variáveis de escopo global ou de classe, apenas locais. Não parece prejudicar nada no Mobile Safari / iPad ou nos navegadores de desktop.
fonte
Estou trabalhando no aplicativo iônico html5, em algumas telas
absolute
posicionei o elemento, ao rolar para cima ou para baixo em dispositivos IOS (iPhone 4,5,6, 6+), repintei o bug.Tentei muitas soluções nenhuma delas estava funcionando, exceto esta resolver o meu problema.
Eu uso classe css
.fixRepaint
nesses elementos de posições absolutasIsso corrigiu meu problema, pode ser útil para alguém
fonte
Isso é bom para JS
Mas no Jquery, e principalmente quando você pode usar apenas $ (document) .ready e não pode se vincular a um evento .load de um objeto por qualquer motivo específico, o seguinte funcionará.
Você precisa obter o contêiner OUTER (MOST) dos objetos / divs, remover todo o seu conteúdo em uma variável e adicioná-lo novamente. Tornará visíveis TODAS as alterações feitas no contêiner externo.
fonte
Eu achei esse método útil ao trabalhar com transições
fonte
o hack "display / offsetHeight" não funcionou no meu caso, pelo menos quando foi aplicado ao elemento que está sendo animado.
Eu tinha um menu suspenso que estava sendo aberto / fechado sobre o conteúdo da página. os artefatos estavam sendo deixados no conteúdo da página depois que o menu foi fechado (apenas nos navegadores de kit da web). a única maneira que o hack "display / offsetHeight" funcionou é se eu o aplicasse ao corpo, o que parece desagradável.
no entanto, eu encontrei outra solução:
isso ainda é bastante hacky (usa uma propriedade CSS3 para forçar a renderização do hardware), mas pelo menos afeta apenas o elemento em questão e funcionou para mim no safari e no chrome no PC e Mac.
fonte
Isso parece relacionado a isso: o estilo jQuery não está sendo aplicado no Safari
A solução sugerida na primeira resposta funcionou bem para mim nesses cenários, a saber: aplicar e remover uma classe fictícia do corpo depois de fazer as alterações de estilo:
Isso força o safari a redesenhar.
fonte
as sugestões acima não funcionaram para mim. mas o abaixo faz.
Deseja alterar o texto dentro da âncora dinamicamente. A palavra "Pesquisar". Criou uma tag interna "font" com um atributo de ID. Gerenciei o conteúdo usando javascript (abaixo)
conteúdo do script:
fonte
Eu estava tendo um problema com um SVG que estava desaparecendo no Chrome para Android quando a orientação foi alterada em determinadas circunstâncias. O código abaixo não o reproduz, mas é a configuração que tivemos.
Dia e meio depois, depois de cutucar e cutucar e não estar satisfeito com as soluções hacky oferecidas aqui, descobri que o problema era causado pelo fato de parecer manter o elemento na memória enquanto desenhava um novo. A solução foi tornar o ID do linearGradient no SVG exclusivo, mesmo que fosse usado apenas uma vez por página.
Isso pode ser conseguido de várias maneiras diferentes, mas para nosso aplicativo angular usamos a função lodash uniqueId para adicionar uma variável ao escopo:
Diretiva Angular (JS):
Atualizações HTML:
Linha 5:
<linearGradient ng-attr-id="{{indicatorColourPatternId}}" x1="0" x2="0" y1="0" y2="1">
Linha 11:
<rect x="0" y="0" rx="5" ry="5" width="100%" height="100%" ng-attr-fill="url(#{{indicatorColourPatternId}})"/>
Espero que essa resposta poupe a alguém mais dias do que esmagar seu teclado.
fonte
Eu recomendaria uma maneira menos burra e mais formal de forçar um reflow: use forceDOMReflowJS . No seu caso, seu código teria a seguinte aparência.
fonte
Descobri que apenas a adição de um estilo de conteúdo ao elemento obrigava a redesenhar, esse deveria ser um valor diferente toda vez que você deseja redesenhar e não precisa estar em um pseudo-elemento.
fonte
Tentei uma resposta mais difícil, mas não funciona para mim. Eu tive problemas para ter o mesmo clientWidth com o safari em comparação com outros navegadores e esse código resolveu o problema:
É realmente estranho, porque se eu tentar novamente obter o clientWidth após get_safe_value, obtenho um valor ruim no safari, o getter deve estar entre
sty.transform = "translateZ(1px)";
esty.transform = "";
A outra solução que funciona definitivamente é
O problema é que você perde o foco e os estados de rolagem.
fonte
Isso forçará a repintura enquanto evita oscilações, ajustes de elementos existentes e qualquer problema de layout ...
fonte
Uma solução simples com jquery:
ou
Tinha um SVG que não estava aparecendo quando foi adicionado ao html.
Isso pode ser adicionado depois que os elementos svg estiverem na tela.
Melhor solução é usar:
e com jQuery:
isso será renderizado corretamente no Chrome.
fonte