Estilo RTL 101 - Um guia detalhado sobre o estilo CSS RTL



Tradução de " RTL Styling 101 - Um extenso guia sobre como estilizar para RTL em CSS " por Ahmad Shadid.

Mais de 292 milhões de pessoas em todo o mundo falam árabe como língua materna. Eu pertenço a eles, então às vezes desenvolvo sites que devem suportar as duas direções do texto: da esquerda para a direita (LTR - Esquerda para a direita) e da direita para a esquerda (direita para a esquerda).

Introdução ao estilo RTL


CSS usa a direção LTR por padrão. Se você verificar os estilos do navegador para o elemento html, verá que, para a propriedade dir (ou "direction"), o valor ltr é o valor padrão. A seguir, é apresentado um exemplo básico para demonstrar a diferença entre as marcações LTR e RTL.



Preste atenção ao bloco RTL - ao contrário do LTR, o texto é lido da direita para a esquerda. Neste exemplo simples, o navegador o exibiu corretamente. Para alterar a direção do idioma do documento, você precisa adicionar o atributo dir ao elemento raiz.

<html dir="rtl">...</html> 

Quando o valor dir muda, todos os elementos aninhados devem alternar automaticamente a seguir: títulos, parágrafos, links, imagens e formulários.

Também vale mencionar que o atributo dir pode ser definido como "auto", o que alterará automaticamente a direção do elemento com base em uma análise de seu conteúdo. De acordo com a especificação HTML:
Os autores recomendam que esse valor seja usado apenas como último recurso, quando a direção do texto é realmente desconhecida e não há como determinar efetivamente isso no lado do servidor.


Além de definir o atributo dir = rtl para o elemento HTML, também podemos adicionar direction: rtl como um estilo CSS.

 .element { direction: rtl; } 

No entanto, o CSSWG (o grupo de trabalho CSS) recomenda definir a direção como um atributo para o elemento raiz HTML para garantir que a marcação esteja correta, independentemente de o CSS estar ou não presente.

Exemplo de alteração da direção da marcação


Vejamos um exemplo mais detalhado para entender melhor como alterar a direção da marcação de LTR para RTL.



 <article class="media"> <img class="media__photo" src="blueberry-cheesecake.jpg" alt=""> <div class="media__content"> <h2>Blueberry Cheesecake</h2> <p>...</p> <p><a href="#" class="link">View Recipe</a></p> </div> </article> 

Inicialmente, usei o bom e velho float para justificar à esquerda a imagem na marcação LTR e, é claro, apliquei o clearfix.

 .media:after { content: ""; display: block; clear: both; } .media img { float: left; width: 200px; margin-right: 16px; } 

Em seguida, adicionamos dir = "rtl" para o elemento que contém texto em árabe. O seguinte resultado é obtido:



Todos os elementos estão alinhados no lado direito, exceto a imagem. Isso aconteceu porque a propriedade da imagem foi configurada para flutuar: esquerda e margem-direita: 16px. Para corrigir isso, substitua os seguintes estilos

 .media[dir="rtl"] img { float: right; margin-right: 0; margin-left: 16px; } 


Conteúdo em inglês e árabe no layout LTR


O que acontece se algum texto tiver uma mistura de palavras em inglês e árabe e a marcação estiver na direção da LTR? O resultado é estranho



O navegador não exibirá o título corretamente. Os falantes de árabe serão confusos. As palavras neste cabeçalho devem estar na ordem mostrada na imagem abaixo. Apenas começando pela direita.



Para evitar esse problema, defina a direção do idioma apropriada sempre que possível. Se o elemento estiver definido como o atributo dir = "rtl", ele será exibido conforme o esperado.




A situação pode se tornar ainda mais complicada se o título for longo. Abaixo eu o completei um pouco e o resultado foi inesperado. Eu indiquei com números a sequência correta. Mais uma vez, começando pela direita.



Quando o atributo dir = "rtl" é definido para o elemento, o título fica correto. Ou seja, a sentença parece gramaticalmente correta e as palavras são organizadas na sequência correta.




Flexbox


O Flexbox basicamente leva em consideração o modo de escrita definido no documento. Esse fator é usado para determinar como os blocos serão alinhados na página por padrão. Por exemplo, em um site em inglês, eles vão da esquerda para a direita e em chinês de cima para baixo. Para inglês e árabe, a propriedade padrão do modo de escrita é horizontal-tb.

De acordo com a Mozilla Developer Network (MDN), um valor de tb horizontal significa o seguinte:

O conteúdo é posicionado horizontalmente da esquerda para a direita, verticalmente de cima para baixo. A próxima linha horizontal está abaixo da anterior.

Quando a direção da página muda para RTL, o flexbox expande adequadamente o fluxo de seus elementos. Esta é uma grande vantagem! A imagem abaixo mostra como o eixo da caixa flexível gira, dependendo do valor da propriedade direction.



No exemplo abaixo, criei três elementos e os numerei para mostrar a diferença ao alterar a direção da página.

 <div class="element"> <div class="item"^_^gt lt^_^/div> <div class="item"^_^gt lt^_^/div> <div class="item"^_^gt lt^_^/div> </div> 

 .element { display: flex; flex-direction: row; /* Default value, added for clarity */ } 





Grade CSS


Assim como o flexbox, a grade css depende do modo de escrita do documento, o que nos dá as mesmas vantagens de usar o flexbox.

No exemplo abaixo, para a direção LTR, a barra lateral deve estar à esquerda e a principal à direita. Para RTL, o oposto é verdadeiro. Quando usamos o CSS Grid, essa reconstrução será realizada automaticamente de acordo com a direção definida nesta página.

 <div class="element"> <div class="side">Side</div> <div class="main">Main</div> </div> 

 .element { display: grid; grid-template-columns: 220px 1fr; grid-gap: 1rem; } 


Principais erros ao mudar para a direção RTL


Desenvolvedores não-árabes cometem erros comuns que são imediatamente aparentes para falantes nativos.

1. Espaçamento entre letras


Em inglês, é comum usar a propriedade espaçamento entre letras para controlar o espaçamento entre letras em uma palavra. Considere o exemplo a seguir com conteúdo em inglês. Parece bastante normal.



No entanto, se você adicionar o mesmo espaçamento entre letras ao texto em árabe, isso parecerá muito estranho. Considere o seguinte exemplo da vida real.



Observe que no texto ao qual a propriedade de espaçamento entre letras é aplicada, as letras de cada palavra são separadas uma da outra. Isto está errado. As letras árabes devem parecer conectadas e manter o mesmo espaçamento das letras em inglês evita isso. Certifique-se de que, ao trabalhar com um site multilíngue, não esqueça de definir a propriedade espaçamento entre letras: 0 no lugar certo.



2. Transparência do texto


No design do site, o texto geralmente é translúcido. Por exemplo, para marcar sua importância secundária. Isso funciona para o inglês. No entanto, se o conteúdo estiver em árabe, poderá surgir um problema devido à maneira estranha de renderizar o texto.



Aparecem lugares nos quais a cor do contorno do personagem muda devido à sobreposição. Neste exemplo, a propriedade espaçamento entre letras não foi definida e, portanto, não afeta o problema. A solução é definir cores sem translucidez (que geralmente é definida via RGBa ou opacidade).


3. Diferenças no tamanho das palavras em diferentes idiomas


Às vezes, quando um site é traduzido para o árabe, o tamanho dos elementos muda devido ao fato de que algumas palavras após a tradução se tornam maiores ou menores. Considere o seguinte exemplo, no qual simulei a navegação do site da Smashing Magazine.



Na versão árabe, algumas das palavras têm quase o mesmo tamanho das versões em inglês, algumas são exatamente iguais e outras são maiores. Para tornar mais claro, aqui está uma comparação de cada palavra e sua tradução para o árabe.



Você pode se perguntar por que estou falando sobre a diferença no tamanho das palavras em diferentes idiomas, pois isso é normal e esperado. Considere o seguinte exemplo do LinkedIn no mundo real.



O botão "Concluído" é traduzido para o árabe como "تم", e é por isso que se torna bem pequeno e geralmente parece estranho. Especialmente nesses casos, seria melhor definir a propriedade de largura mínima para o botão. Adicionei-o através do painel do desenvolvedor para mostrar como deve ficar:



Aqui está um exemplo muito semelhante do Twitter:



Observe que os problemas acima com o LinkedIn e o Twitter foram descobertos no momento da redação (13 de dezembro de 2019).

4. Truncamento de texto


Certa vez, trabalhei em um projeto multilíngue e me deparei com um problema relacionado ao texto truncado na direção errada. Considere o seguinte exemplo.



O truncamento para o texto em inglês está incorreto. Isso deve acontecer no final do elemento, não no começo. Para resolver esse problema, você precisa definir o atributo dir = "auto" para esse elemento e, em seguida, o navegador analisará automaticamente o conteúdo e decidirá qual valor de dir será aplicado.

 <p dir="auto">أهلاً وسهلاً بكم في المقال الذي يتحدث عن تصميم صفحات الويب للغة العربية</p> <p dir="auto">Welcome to the article that explains how to design for RTL pages.</p> 





5. Escolhendo uma fonte RTL incorreta


A presença de uma versão RTL do site não significa que você pode simplesmente se limitar a especificar a fonte do sistema instalada pelo usuário por padrão. Você precisa levar isso a sério para garantir uma boa legibilidade. Um exemplo de seleção de uma fonte com falha é o Twitter:



Do ponto de vista de língua árabe, a palavra "تغريد" é difícil de ler por vários motivos:
  • fonte não muito boa
  • a gordura prejudica a legibilidade
  • os pontos da palavra são muito pequenos e muito próximos das letras


Dei alguns exemplos que parecem muito mais claros:



6. Misturando Números Hindi e Árabe


Em árabe, existem duas maneiras de escrever números:
  • Hindi: ١ ٢ ٣ ٤ ٦ ٦ ٧ ٩
  • Árabe: 0 1 2 3 4 5 6 7 8 9

Os números usados ​​em inglês são herdados do árabe: "0, 1, 2, 3, 4, 5, 6, 7, 8, 9". O texto que contém números deve corresponder apenas a uma das duas opções: hindi ou árabe.

De acordo com a Wikipedia:
A razão pela qual na Europa e na América os números são chamados de "árabe" é porque foram introduzidos na Europa no século 10 por pessoas de língua árabe do norte da África.

O exemplo a seguir contém uma mistura de números hindi e árabe. Essa abordagem parece inconsistente e um estilo único deve ser usado.



Momentos que podem não funcionar com RTL


1. Altura da linha (altura da linha)


Normalmente, uma fonte separada é definida para marcação RTL. Nesse caso, verifique a aparência do conteúdo em uma ou mais linhas. No exemplo a seguir, há menos espaço entre as linhas para o texto em árabe que para o inglês, mesmo que elas tenham o mesmo valor para a propriedade altura da linha.



É importante considerar isso e definir o valor correto para a altura da linha do texto em árabe.



O Twitter, por exemplo, tem um botão com conteúdo cortado. Só por causa do valor errado da altura da linha.



Observe que na primeira imagem, o diacrítico árabe é cortado. É chamado de kasra e é muito importante para a leitura correta da palavra. Na próxima imagem, corrigi a altura da linha e agora os caracteres são exibidos completamente, sem cortes.

2. Links sublinhados


Com palavras em árabe, o sublinhado padrão dos links do CSS parece ruim. Isso ocorre devido às peculiaridades de escrever palavras e letras em árabe e é mostrado na imagem a seguir:



Marquei as áreas problemáticas com um círculo vermelho. O sublinhado sobrepõe os pontos das letras. Aqui está um close:



Os pontos marcados com um círculo vermelho se sobrepõem a um sublinhado, dificultando a leitura. A solução é personalizar o sublinhado com CSS.

2.1 Tipografia (decoração de texto)


É possível alterar o estilo e a cor do sublinhado usando as novas propriedades de estilo de decoração de texto e cor de decoração de texto. No entanto, não há garantia de que isso funcione corretamente com todas as famílias e tamanhos de fontes. No momento da redação deste artigo, o Firefox é o navegador com o melhor suporte para esses recursos.

 .link-2 { text-decoration-color: rgba(21, 132, 196, 0.2); text-decoration-style: normal; text-underline-offset: 4px; text-decoration-thickness: 2px; } 



2.2 Sombra (sombra de caixa)


O suporte do navegador para a propriedade box-shadow é muito melhor que a decoração de texto. Você pode procurar o suporte para uma das novas propriedades de decoração de texto e, se o navegador não suportar, aplique um fallback usando a propriedade box-shadow.
 .link-3 { color: #000; text-decoration-color: rgba(21, 132, 196, 0.2); text-decoration-style: normal; text-underline-offset: 4px; text-decoration-thickness: 2px; box-shadow: inset 0 -5px 0 0 rgba(#1584c4, 0.2); } @supports (text-decoration-color: red){ .link-3 { box-shadow: none; } } 


3. Quebra de linha


Se você usar a propriedade de quebra de palavra, precisará verificar a correção de sua operação. Veja o seguinte exemplo:



As áreas circuladas são palavras árabes quebradas por quebras de linha devido ao uso de quebra de palavra. E em árabe, a quebra de linha não é usada, porque as letras de cada palavra devem estar conectadas uma à outra.

4. Abreviações


Em inglês, abreviações são frequentemente usadas, por exemplo, nos dias da semana. Assim, "sábado" se torna "sáb".



Em árabe, isso é impossível em princípio, pois as letras da palavra devem estar conectadas.



Ícones bidirecionais


Os ícones simétricos não precisam ser invertidos ao alternar entre layouts LTR e RTL. Aqui estão alguns exemplos:



Ao mesmo tempo, para alguns ícones, é importante alterar a direção na versão RTL do site para que eles sejam entendidos corretamente pelo usuário.



Virando itens


Enquanto trabalho em alguns componentes, preciso de uma maneira de alterá-los rapidamente. No Sketch, copio o componente e viro-o com o comando apropriado. A mesma funcionalidade está disponível no Adobe XD e Figma.



Para entender o que quero dizer, aqui está uma animação demonstrando o que faço depois de virar o componente.



Recursos de design para RTL


Nesta seção, examinarei os componentes mais comuns e mostrarei como eles devem aparecer no modo RTL.

Ícones de botão


Há situações em que o botão possui um ícone que abre um menu de ações adicionais. Nesse caso, o local do ícone deve ser revertido no layout RTL.



Campos de entrada


Alguns campos de entrada do formulário devem permanecer alinhados à esquerda, mesmo no modo RTL. Por exemplo, campos de entrada de email ou números de telefone.



Migalhas de pão


As setas entre as seções na farinha de rosca também devem ser giradas.



Título da página


O componente do cabeçalho da página contém as seções inicial e final. Ambos devem ser rotacionados em RTL



Tabelas


As tabelas também devem ser giradas.



Favoritos


Se o ícone estiver à esquerda do nome nos indicadores no modo LTR, esse componente precisará ser expandido em RTL.



Cartão


Para um cartão horizontal, a imagem e o texto precisam ser trocados em RTL



Notificações pop-up


Como você pode esperar, os ícones "fechar" e "aviso" devem ser trocados



Propriedades booleanas de CSS


De acordo com a MDN:
Propriedades e valores lógicos CSS é um módulo que representa propriedades e valores lógicos que fornecem a capacidade de controlar o layout usando direções e dimensões lógicas em vez de físicas.

Vamos dar um exemplo simples. Suponha que precisamos alinhar uma linha de texto à direita. Adicione o seguinte:
 .page-header { text-align: right; } 

E para RTL:
 [dir="rtl"] .nav-item { text-align: left; } 

E se houvesse uma maneira de adicionar apenas um valor para a propriedade de alinhamento de texto, o que alteraria o lado do alinhamento, dada a direção da página? As propriedades lógicas do CSS são úteis!
 .page-header { text-align: end; } 


Ao usá-lo, o lado especificado pela propriedade alinhar texto será baseado na direção da página. Demo

Para facilitar a visualização da diferença entre início e fim, preparei o diagrama abaixo. O valor inicial é equivalente ao valor esquerdo em LRT e o valor certo em RTL. Mesmo com o fim, exatamente o oposto.



Agora que você tem uma idéia geral de como isso funciona, vejamos exemplos adicionais e maneiras de aplicar as propriedades lógicas do CSS.

Preenchimento lógico




Suponha que tenhamos um campo de entrada com um ícone de pesquisa à direita. Temos que definir o preenchimento dos dois lados. O preenchimento à direita será um pouco maior para evitar sobrepor o ícone no texto.

 .input--search { padding-inline-start: 1rem; padding-inline-end: 2.5rem; } 

Margem lógica



A margem à direita do ícone deve ser lógica, portanto usamos margem-in-line-end para isso.
 .page-header__avatar { margin-inline-end: 1rem; } 

Quadros lógicos (borda)



Geralmente, um quadro é usado para indicar um elemento de navegação ativo. No exemplo acima, um quadro é definido no lado esquerdo de cada elemento. Como implementar isso usando propriedades lógicas?

 .nav__item { border-inline-start: 3px solid transparent; } .nav__item.is-active { border-color: #1e9ada; } 

Arredondamento lógico dos cantos (raio da borda)




Na imagem acima, o plano de fundo do elemento de navegação é arredondado apenas para os cantos superiores direito e esquerdo. Isso pode ser implementado usando propriedades lógicas:

 .nav__item { border-start-end-radius: 30px; border-end-end-radius: 30px; background-color: transparent; } .nav__item.is-active { background-color: #ecf6fb; } 


Propriedades lógicas da folha de dicas


Em caso de dúvida sobre a escolha de um análogo lógico da propriedade que define o lado, você pode espiar a folha de dicas abaixo. Observe que ele contém apenas as propriedades lógicas que podem ser úteis ao trabalhar com os modos LTR e RTL. Compilei esta folha de dicas com base em um maravilhoso artigo de Adrian Roselli.

https://codepen.io/shadeed/pen/2981e62691e67452d9f282a5351d7c79

Além disso, Adrian criou uma demonstração que facilita a compreensão da diferença entre propriedades lógicas e direcionais.



Suporte do navegador


O suporte ao navegador é muito bom para propriedades de preenchimento, margem e alinhamento de texto. No entanto, ainda não é suficiente para propriedades do raio da borda. Abaixo está uma tabela de suporte do site Can I Use :




Mesmo que o suporte ainda não seja perfeito (e nunca será), recomendo que você comece a usar propriedades lógicas com fallbacks agora. Por exemplo

 .input--search { padding-left: 1rem; padding-right: 2.5rem; padding-inline-start: 1rem; padding-inline-end: 2.5rem; } 

Além disso, você pode usar o plug- in PostCSS Logical , que adiciona um fallback para cada propriedade lógica usada.

Convenções de Nomenclatura CSS


Evite dar nomes de classes CSS anexados aos seus elementos. Use nomes que podem ser extraídos em componentes reutilizáveis. Considere o seguinte exemplo:
 <div class="c-section"> <p><a href="#" class="see-link">See more</a></p> </div> <div class="c-section"> <p><a href="#" class="see-link">Learn more</a></p> </div> 


Os links são os mesmos nos dois blocos, mas seus nomes são diferentes. No segundo bloco, a classe see-link não faz sentido. Um bom nome pode ser c-link. O prefixo c– é substituído por componentes; adotei esse método a partir da estrutura do ITCSS.

Agora que você entendeu a idéia, também podemos aplicar isso ao estilo RTL. O exemplo abaixo mostra uma seção com dois filhos



Em vez de dar nomes aos elementos como .c-page-header__left e .c-page-header__right, eu os chamo de .c-page-header__start e .c-page-header__end. Isso é mais orientado para o futuro e não implica que o site seja criado apenas no modo LTR ou RTL.

Ferramentas de automação


Existem ótimas ferramentas para facilitar o trabalho com as marcações LTR e RTL.

1. Bi-App-Sass


O Bi-App-Sass de Anas Nakawa permite escrever uma versão de estilos que é compilada em duas folhas de estilo diferentes: uma para marcação LRT e outra para marcação RTL.

Essa ferramenta pode ser útil para projetos grandes.Como resultado, pode haver muitas folhas de estilo para cada direção da escrita. Considere o seguinte exemplo:
 .elem { display: flex; @include margin-left(10px); @include border-right(2px solid #000); } 


O código CSS resultante pode ser o seguinte.

Arquivo App-ltr.css:
 .elem { display: flex; margin-left: 10px; border-right: 2px solid #000; } 


Arquivo App-rtl.css:
 .elem { display: flex; margin-right: 10px; border-left: 2px solid #000; } 


Observe, no entanto, que o último commit no repositório no GitHub foi há quatro anos (novembro de 2015).

2. RTLCSS


RTLCSS por Mohamed Jonas é um framework para a conversão de estilo LTR em RTL.

A diferença entre essa ferramenta é que ela se aplica a uma versão já montada do arquivo CSS. Por exemplo, se você tiver mais de 50 componentes Sass em seu projeto, o RTLCSS é útil para analisar um arquivo CSS compilado e criar uma versão RTL a partir dele.

Exemplos práticos


Cabeçalho do site


Eu fiz especificamente um layout para mostrar qual abordagem eu estou usando para implementar a versão RTL da marcação.



Vamos começar com os componentes do cabeçalho. Para implementar isso corretamente no código, descrevi esquematicamente sua estrutura geral. Observe que eu dividi o cabeçalho na seção principal e subseção. Além disso, foram adicionadas classes de início e fim para elementos filho.



 .header__main, .header__sub { display: flex; justify-content: space-between; } 


Como a operação do CSS Flexbox leva em consideração a direção especificada na página, conforme explicado anteriormente neste guia, ela será expandida automaticamente quando a marcação RTL for usada.



O próximo ponto é a linha divisória entre o logotipo e a navegação. No começo, pensei em usar a borda direita. Funciona, mas não é perfeito. É melhor usar um pseudo-elemento, pois ele se desdobra após a direção da página.



 .c-brand:after { content: ""; display: inline-block; vertical-align: middle; width: 3px; height: 38px; border-radius: 5px; background: #e4e4e4; margin-inline-start: 1.25rem; } 


Aqui está o resultado atual:



Em seguida, trabalharei com o componente de seção (aquele que está na subseção do cabeçalho e contém nomes e contadores). Abaixo está um layout de como esse componente deve aparecer no LTR.



À primeira vista, isso pode parecer simples, mas na verdade requer a especificação de várias propriedades de preenchimento e margem. Aqui está um layout demonstrando isso:



 .topics-heading { margin-inline-end: 1.5rem; } .topics-list { margin-inline-end: 1rem; } .c-topic { padding-inline-start: 0.5rem; } .c-topic:not(:last-child) { margin-inline-end: 10px; } .c-topic__counter { margin-inline-start: 1rem; } 


Como você pode ver, eu uso propriedades booleanas CSS em vez de valores à esquerda e à direita.

O próximo passo é o link "Ver tudo". Preste atenção na seta no final. Ela deve ter o seguinte comportamento:
  • Ao passar o mouse, a cor da seta deve mudar
  • Ao passar o mouse, a animação deve ser aplicada à seta

Decidi usar o SVG embutido para esta tarefa.Quando defini a seta para traduzir, pensei em RTL. Não há propriedades lógicas adequadas para essa situação e preciso considerar outra solução. Surgiu a opção de alterar a margem.

 .c-link svg { margin-inline-start: 4px; transition: 0.15s ease-in; } .c-link:hover svg { margin-inline-start: 8px; } 

Embora a animação de margens não afete muito o desempenho, ela ainda funciona. Outra solução é determinar a direção da página e indicar, com base nisso, a direção correspondente para o deslocamento
 .c-link:hover svg { transform: translateX(6px); } /* I'm using dir=rtl in the header for the purpose of clarity. It should be added to the root element. */ .c-header[dir="rtl"] .c-link svg { transform: scaleX(-1); } .c-header[dir="rtl"] .c-link:hover svg { transform: scaleX(-1) translateX(6px); } 


Observe que, para a direção da página RTL, adicionei scaleX (-1) para expandir o ícone horizontalmente. Você também pode usar girar (180deg), mas a opção de dimensionamento parece mais simples para mim.



Em seguida, vem o campo de pesquisa. Os requisitos são os seguintes:
  • O ícone de pesquisa deve aparecer no final do campo.
  • A localização do ícone de pesquisa deve ser dinâmica

 .c-input--search { background-image: url("data:image/svg+xml..."); background-position: right 6px center; } .c-header[dir="rtl"] .c-input--search { /* We replace the original icon with a flipped one. */ background-image: url("data:image/svg+xml..."); background-position: right 6px center; } 

Além disso, quando o usuário digita o texto nesse campo, o texto não deve se sobrepor ao ícone. Para evitar isso, adicione preenchimento nos dois lados do campo.



O resultado é a seguinte marcação para os modos LTR e RTL:



O próximo é o menu móvel. Para designá-lo, usarei um ícone de hambúrguer. A localização do ícone mudará dependendo da direção (LTR ou RTL). O mesmo vale para a direção da animação de deslocamento.



Você pode ver a demonstração no CodePen

Gratidão


Um agradecimento especial à minha esposa Kholoud pelo apoio contínuo e pela leitura múltipla do manual. Agradeço também a Adebiyi Adedotun Lukman e Šime Vidas por seus incríveis comentários.

Source: https://habr.com/ru/post/pt484886/


All Articles