Apresentação da API de posicionamento de âncoras CSS

A API CSS Anchor Positioning é um divisor de águas no desenvolvimento da Web porque permite posicionar elementos de maneira nativa em relação a outros elementos, conhecidos como âncoras. Essa API simplifica requisitos complexos de layout para muitos recursos de interface, como menus e submenus, dicas, seleções, rótulos, cards, caixas de diálogo de configurações e muito mais. Com o posicionamento de âncoras incorporado no navegador, você pode criar interfaces de usuário em camadas sem depender de bibliotecas de terceiros, o que abre um mundo de possibilidades criativas.

O posicionamento de âncora está disponível no Chrome 125.

Compatibilidade com navegadores

  • 125
  • 125
  • x
  • x

Origem

Conceitos principais: âncoras e elementos posicionados

A relação entre âncoras e elementos posicionados está no centro dessa API. Uma âncora é um elemento designado como um ponto de referência usando a propriedade anchor-name. Um elemento posicionado é aquele posicionado em relação a uma âncora usando a propriedade position-anchor ou explicitamente usando anchor-name na lógica de posicionamento.

Elementos de âncora e elementos posicionados.

Configurar âncoras

Criar uma âncora é simples. Aplique a propriedade anchor-name ao elemento selecionado e atribua a ele um identificador exclusivo. Esse identificador exclusivo precisa ser precedido de um traço duplo, assim como uma variável CSS.

.anchor-button {
    anchor-name: --anchor-el;
}

Após receber um nome da âncora, .anchor-button serve como uma âncora, pronto para orientar o posicionamento de outros elementos. É possível conectar essa âncora a outros elementos de duas maneiras:

Âncoras implícitas

A primeira maneira de conectar uma âncora a outro elemento é com uma âncora implícita, como no exemplo de código a seguir. A propriedade position-anchor é adicionada ao elemento que você quer conectar à âncora e tem o nome dela (neste caso, --anchor-el) como um valor.

.positioned-notice {
    position-anchor: --anchor-el;
}

Com um relacionamento de âncora implícito, você pode posicionar elementos usando a função anchor() sem especificar explicitamente o nome da âncora no primeiro argumento.

.positioned-notice {
    position-anchor: --anchor-el;
    top: anchor(bottom);
}

Âncoras explícitas

Como alternativa, você pode usar o nome da âncora diretamente na função correspondente (por exemplo, top: anchor(--anchor-el bottom). Isso é chamado de âncora explícita e pode ser útil se você quiser fixar vários elementos. Confira mais um exemplo a seguir.

.positioned-notice {
    top: anchor(--anchor-el bottom);
}

Posicionar elementos relativos às âncoras

Diagrama de posicionamento da âncora com propriedades físicas
.

O posicionamento de âncora é baseado no posicionamento absoluto de CSS. Para usar os valores de posicionamento, você precisa adicionar position: absolute ao elemento posicionado. Em seguida, use a função anchor() para aplicar os valores de posicionamento. Por exemplo, para posicionar um elemento ancorado no canto superior esquerdo do elemento de ancoragem, use o seguinte posicionamento:

.positioned-notice {
    position-anchor: --anchor-el;
    /* absolutely position the positioned element */
    position: absolute;
    /* position the right of the positioned element at the right edge of the anchor */
    right: anchor(right);
    /* position the bottom of the positioned element at the top edge of the anchor */
    bottom: anchor(top);
}
Diagrama das bordas de posicionamento no elemento posicionado
.

Agora você tem um elemento ancorado a outro, assim:

Demonstração de uma âncora básica.

Captura de tela da demonstração.

Para usar o posicionamento lógico para esses valores, os equivalentes são os seguintes:

  • top = inset-block-start
  • left= inset-inline-start
  • bottom = inset-block-end
  • right= inset-inline-end

Centralizar um elemento posicionado com anchor-center

Para facilitar a centralização do elemento posicionado como âncora em relação à âncora, há um novo valor chamado anchor-center, que pode ser usado com as propriedades justify-self, align-self, justify-items e align-items.

Este exemplo modifica a anterior usando justify-self: anchor-center para centralizar o elemento posicionado sobre a âncora.

.positioned-notice {
  position: absolute;
  /*  Anchor reference  */
  position-anchor: --anchor-el;
  /*  Position bottom of positioned elem at top of anchor  */
  bottom: anchor(top);
  /*  Center justification to the anchor */
  justify-self: anchor-center;
}
Demonstração de uma âncora centralizada usando justify-center.

Captura de tela da demonstração.

Várias âncoras

Os elementos podem ser vinculados a mais de uma âncora. Isso significa que talvez seja necessário definir valores de posição que são posicionados em relação a mais de uma âncora. Para isso, use a função anchor() e informe explicitamente qual âncora você está referenciando no primeiro argumento. No exemplo a seguir, a parte superior esquerda de um elemento posicionado é ancorada na parte inferior direita de uma âncora, e a parte inferior direita do elemento posicionado é fixada na parte superior esquerda da segunda âncora:

.anchored {
  position: absolute;
  top: anchor(--one bottom);
  left: anchor(--one right);
  right: anchor(--two left);
  bottom: anchor(--two top);
}
Demonstração com várias âncoras

Captura de tela da demonstração.

Posição com inset-area

Além do posicionamento direcional padrão do posicionamento absoluto, há um novo mecanismo de layout incluído na API de âncora, chamado área de encarte.

A área inserida facilita a colocação de elementos posicionados como âncora em relação às respectivas âncoras e funciona em uma grade de nove células com o elemento de fixação no centro.

Várias opções possíveis de posicionamento em área inserida, mostradas na grade de 9 células

Para usar a área do encarte em vez do posicionamento absoluto, use a propriedade inset-area, com valores físicos ou lógicos. Exemplo:

  • Parte superior central: inset-area: top ou inset-area: block-start
  • Lado esquerdo central: inset-area: left ou inset-area: inline-start
  • Parte inferior central: inset-area: bottom ou inset-area: block-end
  • Lado direito do centro: inset-area: right ou inset-area: inline-end
Demonstração com várias âncoras

Captura de tela da demonstração.

Para explorar essas posições mais a fundo, confira a seguinte ferramenta:

Ferramenta de fixação para posições de área inserida.

Dimensionar elementos com anchor-size()

A função anchor-size(), que também faz parte da API de posicionamento de âncora, pode ser usada para dimensionar ou posicionar um elemento posicionado na âncora com base no tamanho dela (largura, altura ou tamanhos inline e de bloco).

O CSS a seguir mostra um exemplo de uso desse atributo para a altura,com anchor-size(height) em uma função calc() para definir a altura máxima da dica como duas vezes a altura da âncora.

.positioned-notice {
  position-anchor: --question-mark;

  /*  set max height of the tooltip to 2x height of the anchor  */
  max-height: calc(anchor-size(height) * 2);
}
Demonstração do anchor-size

Captura de tela da demonstração.

Use âncora com elementos da camada superior, como pop-up e caixa de diálogo

O posicionamento de âncora funciona muito bem com elementos da camada superior, como popover. e <dialog>. Embora esses elementos sejam colocados em uma camada separada do resto da subárvore do DOM, o posicionamento de âncoras permite que você os vincule e role junto com elementos que não estão na camada superior. Essa é uma grande vitória para as interfaces em camadas.

No exemplo a seguir, um conjunto de pop-ups de dica é aberto usando um botão. O botão é a âncora, e a dica é o elemento posicionado. É possível definir o estilo do elemento posicionado como qualquer outro elemento ancorado. Para este exemplo específico, anchor-name e position-anchor são estilos in-line no botão e na dica. Como cada âncora precisa de um nome de âncora exclusivo, ao gerar conteúdo dinâmico, a inserção in-line é a maneira mais fácil de fazer isso.

Demonstração de como usar âncoras com popover

Captura de tela da demonstração.

Ajustar as posições de âncora com @position-try

Depois de obter sua posição de âncora inicial, você pode querer ajustar a posição se a âncora atingir as bordas do seu bloco que o contém. Para criar posições de âncora alternativas, use a diretiva @position-try com a propriedade position-try-options.

No exemplo a seguir, um submenu aparece à direita de um menu. Menus e submenus são um ótimo uso da API de posicionamento de âncoras com o atributo de popover, já que eles tendem a estar ancorados em um botão de acionamento.

Neste submenu, se não houver espaço suficiente na horizontal, é possível movê-lo para baixo do menu. Para fazer isso, primeiro configure a posição inicial:

#submenu {
  position: absolute;
  position-anchor: --submenu;

  /* initial position */
  margin-left: var(--padding);
  inset-area: right span-bottom;
}

Em seguida, configure as posições ancoradas substitutas usando @position-try:

/* alternate position */
@position-try --bottom {
  margin: var(--padding) 0 0 var(--padding);
  inset-area: bottom;
}

Por fim, conecte os dois com position-try-options. O resultado é parecido com este:

#submenu {
  position: absolute;
  position-anchor: --submenu;
  /* initial position */
  margin-left: var(--padding);
  inset-area: right span-bottom;
  */ connect with position-try options */
  position-try-options: --bottom;
}

/* alternate position */
@position-try --bottom {
  margin: var(--padding) 0 0 var(--padding);
  inset-area: bottom;
}
Demonstração usando âncora com popover

Palavras-chave de inversão automática da posição da âncora

Se você tiver um ajuste básico, como virar de cima para baixo ou da esquerda para a direita (ou ambos), você poderá até pular a etapa de criação de declarações @position-try personalizadas e usar as palavras-chave de virada compatíveis com o navegador, como flip-block e flip-inline. Eles funcionam como substitutos para declarações @position-try personalizadas e podem ser usados em combinação:

position-try-options: flip-block, flip-inline, flip-block flip-inline;

As palavras-chave do Flip podem simplificar significativamente seu código de âncora. Com apenas algumas linhas, você pode criar uma âncora totalmente funcional com posições alternativas:

#my-tooltip {
  position-anchor: --question-mark;
  inset-area: top;
  position-try-options: flip-block;
}
Como usar a virada automática com position-try-options: flip-block

position-visibility para âncoras em subrolagens

Em alguns casos, você pode querer ancorar um elemento em uma subrolagem da página. Nesses casos, é possível controlar a visibilidade da âncora usando position-visibility. Quando o anúncio âncora permanece na visualização? Quando ela desaparece? Você tem controle sobre essas opções com esse recurso. Use position-visibility: anchors-visible quando quiser que o elemento posicionado fique visível até que a âncora saia:

#tooltip {
  position: fixed;
  position-anchor: --anchor-top-anchor;
  position-visibility: anchors-visible;
  bottom: anchor(top);
}
Demonstração do position-visibility: anchors-visible

Como alternativa, use position-visibility: no-overflow para evitar que a âncora ultrapasse o contêiner.

#tooltip {
  position: absolute;
  position-anchor: --anchor-top-anchor;
  position-visibility: no-overflow;
  bottom: anchor(top);
}
Demonstração do position-visibility: no-overflow

Detecção de recursos e polyfilling

Como o suporte a navegadores é limitado no momento, é recomendável usar essa API com algumas precauções. Primeiro, é possível verificar o suporte diretamente no CSS usando a consulta de recurso @supports. A maneira de fazer isso é envolver os estilos de âncora da seguinte maneira:

@supports (anchor-name: --myanchor) {

  /* Anchor styles here */

}

Além disso, você pode usar o polyfill no recurso de posicionamento de âncora com o polyfill de posicionamento de âncora CSS da Oddbird (link em inglês), que funciona no Firefox 54, no Chrome 51, no Edge 79 e no Safari 10. Esse polyfill é compatível com a maioria dos recursos básicos de posição da âncora, embora a implementação atual não esteja completa e contenha sintaxes desatualizadas. Você pode usar o link unpkg ou importá-lo diretamente em um gerenciador de pacotes.

Observação sobre acessibilidade

Embora a API de posicionamento de âncora permita que um elemento seja posicionado em relação a outros, ela não cria inerentemente nenhuma relação semântica significativa entre eles. Se realmente houver uma relação semântica entre o elemento de âncora e o elemento posicionado (por exemplo, o elemento posicionado é um comentário da barra lateral sobre o texto âncora), uma maneira de fazer isso é usar aria-details para apontar do elemento de âncora para os elementos posicionados. O software leitor de tela ainda está aprendendo a lidar com detalhes de aria, mas o suporte está melhorando.

<div class="anchor" aria-details="sidebar-comment">Main content</div>
<div class="positioned" id="sidebar-comment">Sidebar content</div>
.anchor {
  anchor-name: --anchor;
}

.positioned {
  position: fixed;
  position-anchor: --anchor;
}

Se você estiver usando o posicionamento de âncoras com o atributo popover ou com um elemento <dialog>, o navegador processará as correções de navegação de foco para garantir a acessibilidade adequada. Assim, você não precisa ter pop-ups ou caixas de diálogo na ordem do DOM. Leia mais na observação sobre acessibilidade na especificação.

Conclusão

Este é um recurso totalmente novo, e estamos animados para ver o que você vai criar com ele. Até agora, vimos alguns casos de uso realmente interessantes da comunidade, como rótulos dinâmicos em gráficos, linhas de conectores, notas de rodapé e referências cruzadas visuais. Enquanto você testa o posicionamento de âncoras, gostaríamos de saber sua opinião e, se encontrar algum bug, entre em contato conosco.

Leia mais