Layout semelhante a uma revista para a Web com regiões e exclusões de CSS

Christian Cantrell
Christian Cantrell

Introdução

A Web é uma plataforma extremamente poderosa para texto, uma área em que a Adobe tem muita experiência e conhecimento. Quando a Adobe estava procurando maneiras de ajudar a avançar a Web, melhorar ainda mais os recursos de texto da Web parecia um ponto de partida óbvio para nós. A Web geralmente assume uma única coluna, com orientação vertical para o texto. Embora seja possível ajustar o texto ao redor de gráficos e até mesmo formatar o texto em várias colunas com CSS, ainda é muito difícil conseguir um layout de revista na Web. Com as regiões CSS e as exclusões CSS, a Adobe está liderando o esforço para levar o poder da editoração eletrônica aos navegadores mais recentes. Por exemplo, na captura de tela abaixo, as exclusões de CSS estão sendo usadas para que o texto siga o contorno da montanha:

Exemplo de exclusões de CSS em ação
Exemplo de exclusões de CSS em ação

O documento na captura de tela abaixo também usa exclusões de CSS para permitir que o texto se ajuste às formas nas imagens, bem como regiões de CSS para formatar o texto em colunas e ao redor de uma citação:

Exemplo de regiões CSS em ação
Exemplo de regiões CSS em ação

Regiões do CSS

Antes de entrar em detalhes sobre as regiões CSS, gostaria de explicar como as regiões podem ser ativadas no Google Chrome. Depois de ativar as regiões CSS, você pode testar algumas das amostras mencionadas neste artigo e criar as suas.

Como ativar as regiões CSS no Google Chrome

A partir da versão 20 do Chrome (versão 20.0.1132.57, para ser exato), as regiões CSS são ativadas pela interface chrome://flags. Para ativar as regiões CSS, siga estas etapas:

  1. Abra uma nova guia ou janela no Chrome.
  2. Digite chrome://flags na barra de localização.
  3. Use localizar na página (control/command + f) e pesquise a seção "experimental Web Platform features".
  4. Clique no link Ativar.
  5. Clique no botão Reiniciar agora na parte de baixo.

Para mais informações sobre as flags do Chrome, consulte minha postagem do blog Tudo sobre as flags do Chrome.

Depois de reiniciar o navegador, você pode começar a testar as regiões CSS.

Uma visão geral das regiões CSS

As regiões CSS permitem que um bloco de texto marcado semanticamente flua automaticamente para "caixas" (atualmente elementos). O diagrama abaixo demonstra a separação do texto (o fluxo) e das caixas (as regiões para onde o texto flui):

O conteúdo flui para regiões definidas
O conteúdo flui para regiões definidas

Vamos dar uma olhada em um caso de uso real de regiões CSS. Além de ser desenvolvedor na Adobe, também sou escritor de ficção científica. Costumo publicar meu trabalho on-line sob uma licença Creative Commons. Para que ele funcione no maior número possível de dispositivos e navegadores, costumo usar um formato extremamente simples, semelhante a este:

Exemplo de projeto legado humano sem estilo
Exemplo de projeto legado humano sem estilo

Usando as regiões CSS, consegui criar uma experiência que é mais interessante visualmente e muito mais funcional, já que é mais fácil de navegar e mais confortável de ler:

Projeto Human Legacy mostrando a região
Projeto Human Legacy com Regions.

Para fins de demonstração, adicionei a capacidade de revelar regiões CSS neste protótipo. A captura de tela abaixo mostra como as regiões são organizadas para dar a impressão de serem colunas que envolvem um gráfico e uma citação no centro:

Projeto Human Legacy mostrando regiões
Projeto Human Legacy mostrando as regiões

Você pode testar esse protótipo (e conferir o código-fonte) aqui. Use as teclas de seta para navegar e pressione a tecla Esc para revelar as regiões. Os protótipos anteriores também estão disponíveis aqui.

Como criar um fluxo nomeado

O CSS necessário para fazer um bloco de texto fluir pelas regiões é extremamente simples. O snippet abaixo atribui um fluxo nomeado chamado "article" a uma div com o ID "content" e atribui esse mesmo fluxo nomeado "article" a qualquer elemento com a classe "region". O resultado é que o texto contido no elemento "content" vai fluir automaticamente por qualquer elemento com a classe "region".

<!DOCTYPE html>
<html>
<head>
    <style>
    #content {
        { % mixin flow-into: article; % }
    }

    .region {
        { % mixin flow-from: article; % }
        box-sizing: border-box;
        position: absolute;
        width: 200px;
        height: 200px;
        padding: 10px;
    }

    #box-a {
        border: 1px solid red;
        top: 10px;
        left: 10px;
    }

    #box-b {
        border: 1px solid green;
        top: 210px;
        left: 210px;
    }

    #box-c {
        border: 1px solid blue;
        top: 410px;
        left: 410px;
    }
    </style>
</head>
<body>
    <div id="box-a" class="region"></div>
    <div id="box-b" class="region"></div>
    <div id="box-c" class="region"></div>
    <div id="content">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent eleifend dapibus felis, a consectetur nisl aliquam at. Aliquam quam augue, molestie a scelerisque nec, accumsan non metus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin cursus euismod nisi, a egestas sem rhoncus eget. Mauris non tortor arcu. Pellentesque in odio at leo volutpat consequat....
    </div>
</body>
</html>

O resultado será este:

Resultado do código acima
Resultado do código acima

O texto dentro da div "content" não tem conhecimento da apresentação. Em outras palavras, ele pode permanecer totalmente intacto semanticamente, mesmo que esteja fluindo por várias regiões. Além disso, como as regiões são apenas elementos, elas são posicionadas e dimensionadas usando CSS, assim como qualquer outro elemento, e, portanto, são perfeitamente compatíveis com os princípios de design responsivo. Designar elementos como parte de um fluxo nomeado significa apenas que o texto especificado flui automaticamente por eles.

O modelo de objeto CSS

O Modelo de Objeto CSS, ou CSSOM, define APIs JavaScript para trabalhar com CSS. Confira abaixo uma lista das novas APIs relacionadas às regiões CSS:

  • document.webkitGetNamedFlows(): uma função que retorna a coleção de fluxos nomeados disponíveis no documento.
  • document.webkitGetNamedFlows().namedItem("article"): uma função que retorna uma referência a um fluxo nomeado específico. O argumento corresponde ao nome especificado como o valor das propriedades CSS flow-into e from-from. Para receber uma referência ao fluxo nomeado especificado no snippet de código acima, transmita a string "article".
  • WebKitNamedFlow: uma representação de objeto de um floe nomeado com as seguintes propriedades e funções:
    • firstEmptyRegionIndex: um valor inteiro que aponta para o índice da primeira região vazia associada ao fluxo nomeado. Consulte getRegions() abaixo para saber como acessar a coleção de regiões.
    • name: um valor de string com o nome do fluxo.
    • overset: uma propriedade booleana que é:
      • false quando o conteúdo do fluxo nomeado se ajusta às regiões associadas
      • true quando o conteúdo não couber e mais regiões forem necessárias para conter todo o conteúdo.
    • getContent(): uma função que retorna uma coleção com referências aos nós que fluem para o fluxo nomeado.
    • getRegions(): uma função que retorna uma coleção com referências a regiões que contêm o conteúdo do fluxo nomeado.
    • getRegionsByContentNode(node): uma função que retorna uma referência à região que contém o nó especificado. Isso é especialmente útil para encontrar regiões que contêm itens como âncoras nomeadas.
  • webkitregionoversetchange. Esse evento é acionado em um WebkitNamedFlow sempre que o layout do conteúdo associado muda por qualquer motivo (conteúdo adicionado ou removido, tamanho da fonte alterado, formato da região alterado etc.) e faz com que a propriedade webkitRegionOverset de uma região mude. Esse evento é útil para detectar mudanças gerais de layout. É um indicador de que algo importante aconteceu e o layout requer atenção, por exemplo: mais regiões são necessárias, algumas regiões podem estar vazias etc.
  • webkitregionfragmentchange. Não implementado no momento desta edição. Esse evento é acionado em um WebkitNamedFlow sempre que o layout do conteúdo associado muda por qualquer motivo, de forma semelhante a webkitregionoversetchange, mas independentemente de qualquer mudança nas propriedades de webkitRegionOverset. Esse evento é útil para detectar mudanças de layout detalhadas que não necessariamente afetam todo o layout do fluxo nomeado. Por exemplo: o conteúdo se move de uma região para outra, mas o conteúdo geral ainda cabe em todas as regiões.
  • Element.webkitRegionOverset: os elementos se tornam regiões quando têm a propriedade CSS flow-from atribuída. Esses elementos têm uma propriedade webkitRegionOverset que, se fizerem parte de um fluxo nomeado, indica se o conteúdo de um fluxo está transbordando da região. Os valores possíveis de webkitRegionOverset são:
    • "overflow" se houver mais conteúdo do que a região pode conter
    • "fit" se o conteúdo parar antes do final da região
    • "empty" se o conteúdo não tiver chegado à região

Um dos principais usos do CSSOM é detectar eventos webkitregionoversetchange e adicionar ou remover regiões de forma dinâmica para acomodar quantidades variadas de texto. Por exemplo, se a quantidade de texto a ser formatada for imprevisível (talvez gerada pelo usuário), se a janela do navegador for redimensionada ou se o tamanho da fonte mudar, talvez seja necessário adicionar ou remover regiões para acomodar a mudança no fluxo. Além disso, se você quiser organizar seu conteúdo em páginas, vai precisar de um mecanismo para modificar dinamicamente o DOM e as regiões.

O snippet de código JavaScript a seguir demonstra o uso do CSSOM para adicionar regiões dinamicamente conforme necessário. Para simplificar, ele não lida com a remoção de regiões nem com a definição do tamanho e das posições delas. Ele é apenas para fins de demonstração.

var flow = document.webkitGetNamedFlows().namedItem("article")
flow.addEventListener("webkitregionoversetchange", onLayoutUpdate);

function onLayoutUpdate(event) {
    var flow = event.target;
    
    // The content does not fit
    if (flow.overset === true) {
    addRegion();
    } else {
    regionLayoutComplete();
    }
}

function addRegion() {
    var region = document.createElement("div");
    region.style = "flow-from: article";
    document.body.appendChild(region);
}

function regionLayoutComplete() {
    // Finish up your layout.
}

Mais demonstrações estão disponíveis na página de exemplos de regiões CSS.

Modelos de página do CSS

Aproveitar o CSSOM é provavelmente a maneira mais poderosa e flexível de implementar recursos como paginação e layout responsivo, mas a Adobe trabalha com ferramentas de texto e editoração eletrônica há tempo suficiente para saber que designers e desenvolvedores também vão querer uma maneira mais fácil de obter recursos de paginação relativamente genéricos. Por isso, estamos trabalhando em uma proposta chamada Modelos de Página CSS, que permite que o comportamento de paginação seja definido de forma totalmente declarativa.

Vamos dar uma olhada em um caso de uso comum para modelos de página CSS. O snippet de código abaixo mostra o uso de CSS para criar dois fluxos nomeados: "article-flow" e "timeline-flow". Além disso, ele define um terceiro seletor chamado "combined-articles", que vai conter os dois fluxos. A simples inclusão da propriedade overflow-style no seletor "combined-articles" indica que o conteúdo precisa ser paginado automaticamente ao longo do eixo x ou horizontalmente:

<style>
    #article {
    { % mixin flow-into: article-flow; % }
    }

    #timeline {
    { % mixin flow-into: timeline-flow; % }
    }

    #combined-articles {
    overflow-style: paged-x;
    }
</style>

Agora que os fluxos foram definidos e o comportamento de overflow desejado foi especificado, podemos criar o modelo de página:

@template {
    @slot left {
    width: 35%;
    float: left;
    { % mixin flow-from: article-flow; % }
    }

    @slot time {
    width: 25%;
    float: left;
    { % mixin flow-from: timeline-flow; % }
    }

    @slot right {
    width: 35%;
    float: left;
    { % mixin flow-from: article-flow; % }
    }
}

Os modelos de página são definidos usando a nova sintaxe "at". No snippet de código acima, definimos três slots, cada um correspondente a uma coluna. O texto de "article-flow" vai fluir pelas colunas à esquerda e à direita, e o texto de "timeline-flow" vai preencher a coluna do meio. O resultado será parecido com este:

Exemplo de modelos de página
Exemplo de modelos de página

O texto do artigo (nas colunas esquerda e direita) está em inglês, e a linha do tempo no centro está em alemão. Além disso, o documento é paginado horizontalmente sem a necessidade de código JavaScript. Tudo foi feito de forma totalmente declarativa no CSS.

Os modelos de página CSS ainda são uma proposta, mas temos um protótipo que usa um "shim" de JavaScript (também conhecido como polyfill) para que você possa testá-los agora.

Para saber mais sobre as regiões CSS em geral, confira a página de regiões CSS em html.adobe.com.

Exclusões de CSS

Para conseguir um layout que realmente se pareça com o de uma revista, não basta apenas distribuir o texto pelas regiões. Um elemento essencial da editoração eletrônica de alta qualidade e visualmente interessante é a capacidade de fazer o texto fluir ao redor ou dentro de gráficos e formas irregulares. As exclusões de CSS estão trazendo esse nível de qualidade de produção para a Web.

A captura de tela abaixo é de um protótipo de exclusões de CSS e mostra o texto fluindo dinamicamente em torno de um caminho que corresponde ao contorno de uma grande formação rochosa:

Exemplo de exclusões de CSS em ação
Exemplo de exclusões de CSS em ação

O inverso é ilustrado na próxima captura de tela: texto fluindo dentro de polígonos de formato irregular:

Texto fluindo em polígonos de formato irregular
Texto fluindo para polígonos de formato irregular

A primeira etapa para poder ajustar o texto ao redor ou dentro de formas arbitrárias é desenvolver e otimizar os algoritmos necessários. A Adobe está trabalhando em implementações que serão contribuídas diretamente para o WebKit. Depois que esses algoritmos forem otimizados, eles vão se tornar as bases sobre as quais o restante das exclusões de CSS será criado.

Para mais informações sobre as exclusões de CSS, consulte a página sobre exclusões de CSS em html.adobe.com. Para uma análise mais detalhada do trabalho da Adobe na tecnologia subjacente para exclusões de CSS, consulte a postagem do blog de Hans Muller intitulada Horizontal Box: Polygon Intersection for CSS Exclusions.

O estado das regiões e exclusões de CSS (2012)

A primeira vez que falei publicamente sobre as regiões e exclusões de CSS foi no Adobe Developer Pod no Google I/O 2011. Na época, eu mostrava demonstrações no nosso próprio navegador de protótipo personalizado. A recepção foi extremamente entusiasmada, mas houve uma sensação palpável de decepção quando os espectadores descobriram que nenhuma das funcionalidades que eu estava mostrando estava disponível em nenhum dos principais navegadores.

Estive no Google I/O novamente este ano (2012), desta vez como apresentador, junto com meu colega de trabalho Vincent Hardy e Alex Danilo do Google (você pode assistir à apresentação aqui). Apenas um ano depois, cerca de 80% da especificação de regiões CSS foi implementada no WebKit e já está na versão mais recente do Google Chrome (as regiões CSS precisam ser ativadas em chrome://flags). O suporte preliminar para regiões CSS foi incluído até mesmo no Google Chrome para Android:

Regiões no Google Chrome para Android
Regiões no Google Chrome para Android

Além disso, as regiões e exclusões de CSS são implementadas na prévia do Internet Explorer 10 e estão no roteiro de 2012 da Mozilla para o Firefox. A próxima versão principal do Safari deve oferecer suporte à maior parte da especificação de regiões CSS, e as atualizações subsequentes devem incluir o restante.

Veja abaixo uma linha do tempo detalhada do progresso que fizemos com as regiões e exclusões de CSS desde nossa proposta inicial ao W3C em abril de 2011:

Progresso da região e da exclusão
Progresso da região e da exclusão

Conclusão

A Adobe tem muita experiência com textos, fontes e editoração eletrônica em geral, com ferramentas como o InDesign. Embora a Web já seja uma plataforma muito poderosa para texto, queremos usar nosso conhecimento e experiência para melhorar ainda mais a apresentação de texto. As regiões e exclusões de CSS permitem que o conteúdo permaneça estruturado semanticamente, além de possibilitar um layout semelhante ao de uma revista e, por fim, uma Web muito mais expressiva.