Como desenvolver um editor de texto para a Web

Publicados: 2022-03-10
Resumo rápido ↬ Como funciona a digitação e edição de texto na web? Embora esse processo possa parecer simples, há muitas nuances técnicas por trás de sua aparente simplicidade. Este artigo analisa como a digitação na web funciona.

Eu trabalho para a Readymag, que faz uma ferramenta de design baseada em navegador que ajuda as pessoas a criar sites, portfólios e todos os tipos de publicações online, sem codificação. Muitos widgets estão disponíveis em nossa ferramenta, e o widget de texto é um dos mais utilizados.

O widget de texto é um campo de entrada de texto onde o usuário pode estilizar o texto usando uma variedade de controles no editor. Cada controle aplica uma propriedade CSS ao texto. Do lado do usuário, parece um campo comum para inserir texto, mas um grande número de processos complexos está oculto por trás de sua aparente simplicidade.

Neste artigo, explicarei os desafios que minha empresa enfrentou e as soluções que usamos para criar um widget de texto em nosso aplicativo. Também falarei sobre como o implementamos e o que aprendemos ao longo do caminho – e como a digitação na web funciona em geral.

Editando texto na web

Existem várias maneiras de implementar campos de entrada de texto na web. Poderíamos usar um campo de texto simples, ou um elemento textarea de várias linhas, ou o atributo contenteditable para tornar uma entrada editável, ou document.designMode = on . Como eles são diferentes?

Widget de texto no Readymag
Widget de texto no Readymag. (Visualização grande)

Os elementos input e textarea são ideais para adicionar texto a uma página, mas não fornecem uma experiência rica de formatação de texto. Para isso, podemos usar o atributo contenteditable para tornar praticamente qualquer elemento editável e permitir o uso de estilos de texto.

Veja a caneta “Inputs de texto” de Ilya Medvedev.

Veja a caneta “Inputs de texto” de Ilya Medvedev.

Se você precisar editar a página inteira de uma vez, use document.designMode . Este modo permite que qualquer elemento dentro de um determinado documento seja editado, mesmo um iframe .

Optamos pelo atributo contenteditable , que inclui todos os recursos necessários de edição de texto. Com este atributo, qualquer texto na página se torna editável, o que é muito importante se quisermos permitir que as pessoas estilizem o texto com CSS . Por exemplo, os usuários podem estilizar seções selecionadas ou todo o texto diretamente.

Estilos de texto e propriedades de fonte

Permitimos que os usuários estilizem o texto da maneira que desejarem, fornecendo acesso a todas as opções que o CSS fornece imediatamente. Além das propriedades conhecidas, como fonte, estilo, cor e decoração, oferecemos aos usuários a oportunidade de usar recursos de fonte OpenType, como ligaduras, conjuntos estilísticos, frações e assim por diante. Esses recursos funcionam por meio da propriedade CSS font-feature-settings , que permite aos usuários personalizar estilos de texto.

Nota : Eu recomendo a leitura do excelente artigo do Sparanoid que mostra todos os recursos do OpenType.

Usando propriedades de fonte no widget de texto
Usando propriedades de fonte no widget de texto. (Visualização grande)

A tipografia moderna deu um grande passo à frente, permitindo o uso de fontes variáveis ​​na web por meio da propriedade font-variation-settings .

Mostra de recursos de fonte OpenType
Mostra de recursos de fonte OpenType. (Visualização grande)

Cada fonte variável possui propriedades variáveis ​​cujos valores você pode alterar. Por exemplo, em uma fonte padrão, você pode alterar o peso da fonte usando valores estritamente especificados ( 400 , 500 , 600 e assim por diante), enquanto em uma fonte variável, você pode usar qualquer valor no intervalo disponível, oferecendo possibilidades mais amplas para estilo de texto.

 .style-1 { font-weight: 600; } .style-2 { font-variation-settings: "wght" 777; }

Abaixo você pode ver um exemplo de como trabalhar com uma fonte variável parece em um widget de texto.

Exemplo de configurações de variação de fonte

Além dos valores registrados ( wght , wdth , slnt , etc.), os criadores de fontes também podem criar seus próprios recursos de fonte exclusivos (como no exemplo acima). Para dar aos nossos usuários a oportunidade de usar todos os recursos de fonte possíveis, precisamos primeiro dessas informações.

Todos os recursos que você deseja usar devem ser definidos no arquivo de fonte. Vejamos suas especificações. Cada fonte pode ser representada na forma de tabelas, fornecendo todas as diferentes informações usadas na renderização de seus caracteres.

Usamos duas tabelas para coletar essas informações sobre fontes:

  1. Tabela de substituição de glifos
    A tabela de substituição de glifo (GSUB) contém uma lista de dados de renderização de glifo. O objeto GSUB.featureList é uma enumeração de recursos de fonte e suas propriedades. Você pode ver um exemplo de dados na tabela no GitHub. Nesta tabela, o campo tag é o mais interessante. Este é o nome do recurso de fonte e indica que esse recurso está disponível com essa fonte. Podemos usar com segurança a tag na propriedade font-feature-settings .
  2. Tabela de variações de fonte
    A tabela de variações de fonte (fvar) é uma representação das propriedades variáveis ​​associadas a uma fonte. Um exemplo da tabela também está disponível no GitHub. Cada objeto é uma propriedade de fonte, com uma descrição dos valores possíveis ( min , max , default) e um nome localizado (se houver). Usamos esses valores com a propriedade font-variation-settings .

Com a ajuda dessas duas tabelas, podemos cobrir todos os nossos requisitos: usando propriedades de fonte variáveis ​​e vários recursos de fonte. Os dados resultantes são exibidos nos controles de widget de texto no editor, onde os usuários podem estilizar o texto sem usar nenhum código.

Usando seu teclado

A entrada de texto é um dos aspectos mais importantes da experiência do usuário do widget de texto. Além de habilitar atalhos para trabalhar com texto, tivemos que lidar com alguns desafios inusitados. Navegar pelo texto com as teclas de seta foi definitivamente um deles.

Ícones de caracteres ocultos
Ícones de caracteres ocultos. (Visualização grande)

Enquanto o usuário está editando, o widget de texto também mostra caracteres ocultos, como espaços sem quebra e quebras de linha. Eles são implementados como ícones SVG inseridos no texto, o que representa um problema: se usarmos contenteditable , esses ícones impedirão que os usuários movam o cursor com as teclas de seta.

A solução é bastante simples: use um span e o pseudo-elemento :before . Dessa forma, o navegador percebe o ícone como sendo texto e as teclas de seta funcionam muito bem.

 span:before { content: ""; height: 1em; position: relative; background-repeat: no-repeat; background-image: url("data:image/svg+xml,..."); background-position: center bottom; background-size: 1em; }

Atalhos

Existem dois atalhos de teclado para colar texto em um widget de texto.

Cmd / Ctrl + V cola o texto da área de transferência e mantém todos os estilos que havia no documento original. Se o texto foi copiado de um aplicativo como Pages, Notes, Word ou Google Docs, sua área de transferência conterá informações HTML, não apenas texto simples. Este HTML pode ser analisado e colado mantendo os estilos originais.

Você pode obter os dados HTML da seguinte forma:

 // https://www.w3.org/TR/clipboard-apis/#reading-from-clipboard document.addEventListener('paste', (e) => { const text = e.clipboardData.getData('text/plain'); const html = e.clipboardData.getData('text/html'); handlePaste(); });

Além disso, temos o atalho Cmd + Shift + V. Quando você insere texto usando essa combinação de teclado, o navegador deixa os dados simples na carga útil, de modo que o estilo é controlado pelo destino da colagem. Esses atalhos existem no navegador por padrão, mas você precisa se lembrar de implementá-los em seu projeto.

Seleção de texto e foco

Veja a caneta “Exemplo de seleção” de Ilya Medvedev.

Veja a caneta “Exemplo de seleção” de Ilya Medvedev.

A seleção de texto ajuda os usuários a ver qual parte do texto está sendo editada no momento. Vamos tentar um exemplo simples: um campo de entrada com um botão para controlar o negrito do texto.

Neste exemplo, podemos selecionar um pedaço de texto e pressionar o botão Bold , e a seleção no texto permanecerá depois. Mas e se o nosso exemplo for mais complicado? Digamos que adicionamos um campo de entrada ao seletor de tamanho de texto. Nesse caso, o foco mudará para a nova entrada.

Existem duas opções para resolver este problema :

  • Após cada evento de entrada, forçamos o foco a voltar para o bloco de texto. Nesse caso, a seleção começará a piscar após um certo número de eventos de entrada — não queremos isso.
  • Podemos adicionar o bloco de texto a um iframe . Como você provavelmente sabe, um iframe tem seu próprio objeto de window global. Portanto, enquanto a seleção estiver dentro do iframe , ela persistirá mesmo que o foco fora seja movido.

Acabamos com um widget de texto embrulhado em iframe . Portanto, enquanto a seleção estiver dentro do iframe , ela persistirá mesmo que o foco fora seja movido. Dê uma olhada na captura de tela abaixo. Temos duas seleções na página: o fragmento selecionado no widget de texto e o valor selecionado do tamanho do texto no controle.

Seleção de texto dentro do iframe
Seleção de texto dentro do iframe. (Visualização grande)

Desempenho durante a entrada de texto

A capacidade de resposta da sua interface de edição de texto é importante. Monitore o valor de quadros por segundo (FPS) de perto, especialmente quando se trata de tarefas como editar texto em alta velocidade ou alterar o tamanho da fonte.

O Readymag tem duas janelas de visualização: desktop e mobile . Os estilos de texto podem parecer diferentes em cada um. Enquanto o texto está sendo inserido, o editor realizará vários cálculos para sincronizar os dados entre as viewports. A alta capacidade de resposta é alcançada usando a API do navegador: requestAnimationFrame e requestIdleCallback :

  • requestAnimationFrame é chamado toda vez que a tela é atualizada;
  • requestIdleCallback é chamado apenas quando o navegador está ocioso.

Esta é uma ótima maneira de realizar operações tediosas sem bloquear o thread principal.

Acessibilidade

Habilitar a acessibilidade é uma das práticas mais importantes no desenvolvimento web hoje. Se o seu site for projetado com acessibilidade em mente, mais pessoas terão acesso ao seu produto . Isso significa acomodar não apenas pessoas com deficiência, mas também usuários em diferentes plataformas: dispositivos desktop e touch, leitores de tela, aparelhos auditivos e assim por diante. Para entender o quão importante pode ser tornar os projetos acessíveis, recomendo verificar as estatísticas de acessibilidade recentes.

Para começar a incorporar práticas de acessibilidade na web, primeiro verifique as Diretrizes de Acessibilidade de Conteúdo da Web (WCAG), o recurso mais abrangente sobre o tema. E desde que o Readymag seja uma ferramenta para publicação, além das WCAG, também precisamos seguir as Diretrizes de Acessibilidade da Ferramenta de Autor (ATAG).

Nossa equipe está atualmente na fase de integração da acessibilidade no editor. Nos artigos subsequentes, compartilharemos mais sobre nossa jornada para integrar totalmente a acessibilidade na Readymag. Você também pode verificar qualquer trabalho feito com o Readymag usando nossa lista de verificação de acessibilidade.

Melhores Práticas

Por fim, aqui estão algumas dicas para ajudá-lo a desenvolver um editor de texto na web:

  • Pense cuidadosamente sobre o layout.
    Identifique antecipadamente quais recursos você precisa e como trabalhará com os elementos no editor de texto.
  • Configure os testes visuais.
    Ao trabalhar com texto, você não pode confiar inteiramente no resultado do teste de instantâneo. Você pode obter o resultado correto no teste, esperando o CSS fornecido para o bloco, mas às vezes o resultado pode não ser o que você esperava.
  • Teste seu trabalho em diferentes navegadores.
    Embora a maioria dos navegadores suporte razoavelmente bem os novos recursos online, muitas vezes há problemas com a exibição dos mesmos estilos em navegadores diferentes.
  • Use sinalizadores de recursos para um desenvolvimento mais seguro de novos recursos.
  • Meça o FPS no navegador ao inserir texto.
    Não execute tarefas com uso intenso de CPU em um único thread.
  • Não tenha medo de experimentar .
  • Por último, mas não menos importante, experimente o Text Widget no Readymag.

Alguns links úteis

  • “A demonstração CSS completa para recursos OpenType,” Sparanoid
  • “Introdução às fontes variáveis ​​na Web,” web.dev
  • “Tipografia incrível”, Joel Galeran
  • “Fontes Variáveis”, Nick Sherman
  • Fontkit
  • OpenType.js