Texto

Como inverter texto sem quebrar acentos nem emoji

Inverter uma string parece uma linha de código. Essa linha solta os acentos das letras, parte os emoji e pode transformar uma bandeira na de outro país.

Inverter texto significa uma de quatro operações diferentes, e pedir a errada é o motivo de o resultado sair quebrado. Você pode inverter os caracteres (olá vira álo), inverter a ordem das palavras (um dois três vira três dois um), inverter a ordem das linhas ou inverter cada palavra no lugar e deixar o formato da frase intacto. A inversão de caracteres é a resposta literal, e é a que dá errado: os acentos se soltam das letras, os emoji chegam como quadrados vazios, e o motivo está em como o texto é armazenado, não na ferramenta que você usou.

Qual das quatro você quer?

Passe cada modo pela linha Café 👩‍💻 never odd or even e a diferença fica óbvia:

Se você não tem certeza de qual precisa, olhe os quatro. São botões separados no inversor de texto daqui, então a mesma entrada troca de modo sem você redigitar nada, e ele conta os caracteres do jeito que um leitor conta, não do jeito que o navegador guarda — que é onde a dificuldade começa.

Por que a versão de uma linha quebra

Procure como inverter uma string e a resposta é sempre s.split('').reverse().join(''). Ela está certa para o inglês sem acentos e errada para quase todo o resto, porque o JavaScript guarda texto como code units UTF-16: espaços fixos de 16 bits que só às vezes correspondem a um caractere que uma pessoa apontaria. Três coisas diferentes dão errado, e qualquer texto real esbarra em pelo menos uma delas.

Caracteres que ocupam dois espaços

Tudo acima de U+FFFF — a maioria dos emoji, o CJK menos comum, todas as escritas históricas, os alfabetos matemáticos — não cabe em 16 bits e é guardado como um surrogate pair: dois code units que só significam alguma coisa nessa ordem. O rosto levemente sorridente é U+1F642, guardado como D83D e depois DE42. Inverta a string e ele vira DE42 e depois D83D, um low surrogate na frente de um high surrogate, o que não é caractere nenhum. O navegador desenha dois quadrados de substituição.

Acentos que moram no próprio espaço

O é de Café pode ser um único code point (U+00E9) ou dois: um e simples seguido de U+0301, o acento agudo combinante. Eles ficam idênticos na tela e você raramente sabe qual tem em mãos — texto copiado da web e nomes de arquivo do macOS costumam usar a forma de duas partes. Inverta e o acento cai na frente da letra a que pertencia, grudando no que passou a vir antes dele ou flutuando sozinho sobre um círculo pontilhado. Uma palavra perde o acento e outra ganha um. O mesmo vale para os sinais vocálicos do tailandês, as matras do devanágari e os pontos do hebraico.

Emoji feitos de vários emoji

👩‍💻 são três code points: uma mulher, um zero-width joiner (U+200D) e um laptop. O joiner é a instrução para desenhá-los como um glifo só. Invertida, a sequência vira laptop, joiner, mulher, e nenhuma fonte tem uma forma combinada para isso, então ela se desfaz em dois emoji sem relação. As bandeiras são o caso mais marcante. Elas são pares de letras indicadoras regionais, então inverter a bandeira da Austrália — as letras A e U — dá a bandeira da Ucrânia. Nada dá erro, nada parece quebrado. Você simplesmente recebe outro país.

Como fazer isso direito

Divida o texto em grafemas, as unidades que um leitor conta como um caractere, em vez de em code units. No navegador, isso é Intl.Segmenter:

const seg = new Intl.Segmenter(undefined, { granularity: 'grapheme' });
const out = [...seg.segment(text)].map(g => g.segment).reverse().join('');

Espalhar a string com [...text] ou Array.from é o meio-conserto que você vai ver recomendado. Ele percorre code points em vez de code units, então resolve o problema do surrogate pair e nenhum dos outros dois — seus emoji sobrevivem e seus acentos continuam migrando. A segmentação por grafemas é a única abordagem que dá conta dos três.

O suporte é bom, mas não universal: o Chrome tem isso desde 2020 e o Safari desde 2021, enquanto o Firefox só lançou em 2024. Em navegadores antigos, a única alternativa é uma tabela Unicode grande que você mesmo precisa incluir no seu código. O inversor linkado acima usa a coisa de verdade onde ela existe e avisa embaixo dos botões quando teve que cair para code points, porque ali os acentos realmente se movem.

Inverter uma lista não é ordenar a lista

Inverter a ordem das linhas te dá a lista de baixo para cima. Se a lista não estava em ordem desde o começo, agora você tem uma lista desordenada de outro jeito — o que serve se você queria as entradas mais novas primeiro, e não serve para nada se queria de Z a A. São operações diferentes, e as pessoas escolhem a errada o tempo todo. Colocar uma lista em ordem alfabética com a opção decrescente é o que produz Z a A; a inversão só espelha a ordem que já estava ali.

Um lugar em que a inversão é exatamente o certo: conferir um palíndromo. Tire os espaços e a pontuação, inverta os caracteres, compare. Never odd or even passa. A maioria das coisas que as pessoas juram ser palíndromo, não é.

Não inverta árabe nem hebraico

As escritas da direita para a esquerda são armazenadas em ordem lógica — a ordem em que você as falaria — e o próprio navegador cuida da exibição da direita para a esquerda. Inverter a string dá um texto que está de trás para a frente na memória e mesmo assim é exibido da direita para a esquerda, o que está errado duas vezes. Para testar um layout RTL, coloque dir="rtl" e use texto de verdade traduzido: texto em alfabeto latino invertido não diz nada sobre como o árabe quebra linha nem sobre onde a pontuação cai.

Existe também um caractere, U+202E, que força tudo depois dele a ser exibido da direita para a esquerda, seja qual for a escrita. Ele é parte legítima do algoritmo bidirecional e é também como um anexo cujo nome real termina em .exe pode aparecer num cliente de e-mail terminando em algo inofensivo. Inversão visível é truque de festa. A inversão que o renderizador faz por você, disparada por um caractere sem largura, é a versão usada contra as pessoas.

Texto de cabeça para baixo é fantasia, não rotação

Virar o texto troca cada letra por um caractere Unicode diferente que por acaso se parece com ela de cabeça para baixo — ɐ é um a virado emprestado do alfabeto fonético, ǝ um e virado — e depois inverte o resultado para que se leia certo com a tela de cabeça para baixo. Nada gira. A string agora é feita de caracteres que significam outra coisa.

Isso importa antes de ir para um perfil. Um leitor de tela anuncia os caracteres de verdade, então um nome virado é lido como uma sequência de símbolos fonéticos. A busca não vai encontrar. Fontes sem esses glifos mostram quadrados, o que ainda é comum em Android antigo e em e-readers. Algumas plataformas normalizam ou rejeitam os caracteres quando você salva. E as letras maiúsculas quase não têm forma virada no Unicode, então saem com cara de minúsculas.

O que a inversão não vai fazer por você

Não é uma imagem espelhada. Parênteses e aspas continuam apontando para onde apontavam, então um (exemplo) invertido sai como )olpmexe(. Certo como inversão, errado como espelho. Só o modo de cabeça para baixo troca os caracteres pareados, porque ali a saída é feita para ser lida.

Não é ofuscação. Texto invertido é legível para qualquer um que gaste um segundo nele e é desfeito na hora por qualquer ferramenta, inclusive a que o criou. Esconde um spoiler e nada além disso.

Não é uma renomeação. Se o que você quer mesmo é userName escrito como user_name, isso é uma mudança de convenção e não uma inversão, e camelCase, snake_case e kebab-case têm cada um os lugares a que pertencem.

Ele não tem a menor ideia do que é o seu texto. Marcação, indentação, colunas de CSV e código saem todos destruídos estruturalmente. Inverta uma frase, não um arquivo de configuração.

Os quatro modos ficam lado a lado no inversor de texto, que segmenta por grafema, então os acentos ficam nas letras e um emoji de várias partes volta inteiro. Ele roda na própria página, ou seja, o que você colar nunca sai da sua máquina.

O zero-width joiner que segura esse emoji faz parte de toda uma família de caracteres que você não consegue ver, mas que mudam em silêncio o que o texto faz. Os caracteres invisíveis que quebram seu texto cobre o resto deles, inclusive como achar os que já estão dentro de algo que alguém te mandou.

Perguntas frequentes

Como inverto uma string em JavaScript sem quebrar os emoji?

Divida a string em grafemas em vez de em code units, usando o Intl.Segmenter com granularidade de grafema, depois inverta esse array e junte tudo. O clássico split('').reverse().join('') quebra qualquer caractere guardado como surrogate pair. Espalhar a string com Array.from é melhor, mas ainda move os acentos combinantes e parte os emoji unidos.

Por que meu texto invertido mostra quadrados vazios ou pontos de interrogação?

A inversão partiu um caractere ao meio. Emoji e outros caracteres acima de U+FFFF são guardados como duas metades de 16 bits que só valem em uma ordem, então invertê-las produz uma sequência que nenhuma fonte consegue desenhar. Um inversor que trabalha em grafemas evita isso por completo.

Como inverto a ordem das palavras mantendo cada palavra escrita certo?

Use uma inversão de ordem de palavras em vez de uma inversão de caracteres. Ela vira a sequência de palavras de cada linha e deixa as letras dentro de cada palavra em paz, então "one two three" vira "three two one". Inverter os caracteres do texto inteiro daria "eerht owt eno".

Dá para inverter texto em árabe ou hebraico?

Dá, mas quase nunca é o que você quer. Texto da direita para a esquerda é armazenado na ordem em que é falado e o navegador cuida da direção visual, então inverter os caracteres produz um texto de trás para a frente no armazenamento e ainda exibido da direita para a esquerda. Para testar um layout RTL, coloque dir="rtl" no elemento e use strings realmente traduzidas.

Texto de cabeça para baixo é a mesma coisa que texto invertido?

Não. O texto de cabeça para baixo substitui cada letra por um caractere Unicode diferente que parece a letra virada, e depois inverte a sequência. As letras são realmente trocadas, então leitores de tela leem os substitutos, a busca não encontra o texto e fontes sem esses glifos mostram quadrados vazios.

Última atualização 19 de setembro de 2026