A API de posicionamento de âncora do CSS

A API CSS Anchor Positioning permite posicionar elementos em relação a outros elementos, conhecidos como âncoras. Essa API simplifica os requisitos de layout complexos para muitos recursos de interface, como menus e submenus, dicas de ferramentas, opções, rótulos, cards, caixas de diálogo de configurações e muito mais. Com o posicionamento de âncora integrado ao navegador, é possível criar interfaces do usuário em camadas sem depender de bibliotecas de terceiros, abrindo um mundo de possibilidades criativas.

Compatibilidade com navegadores

  • Chrome: 125.
  • Edge: 125.
  • Firefox: não é compatível.
  • Safari: não é compatível.

Origem

Conceitos básicos: elementos ancorados e posicionados

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

Elementos de ancoragem e elementos posicionados.

Configurar âncoras

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

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

Depois de receber um nome de âncora, .anchor-button serve como uma âncora, pronta para orientar a colocação 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 abaixo. A propriedade position-anchor é adicionada ao elemento que você quer conectar à âncora e tem o nome da âncora (neste caso, --anchor-el) como valor.

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

Com uma relação de âncora implícita, é possível 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, use o nome da âncora diretamente na função de âncora (por exemplo, top: anchor(--anchor-el bottom). Isso é chamado de âncora explícita e pode ser útil se você quiser ancorar vários elementos. Confira um exemplo a seguir.

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

Posicionar elementos em relação a âncoras

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

O posicionamento de âncora é baseado no posicionamento absoluto do CSS. Para usar valores de posicionamento, adicione position: absolute ao elemento posicionado. Em seguida, use a função anchor() para aplicar 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 de posicionamento das bordas 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 o centro do elemento posicionado 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 o anterior usando justify-self: anchor-center para centralizar o elemento posicionado na parte de cima da â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 sejam posicionados em relação a mais de uma âncora. Para fazer isso, use a função anchor() e especifique explicitamente qual âncora você está referenciando no primeiro argumento. No exemplo abaixo, o canto superior esquerdo de um elemento posicionado é ancorado no canto inferior direito de uma âncora, e o canto inferior direito do elemento posicionado é ancorado no canto superior esquerdo da segunda âncora:

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

Captura de tela da demonstração.

Posição com position-area

A API de ancoragem inclui um novo mecanismo de layout usando a propriedade position-area.

Essa propriedade permite posicionar elementos posicionados em relação às respectivas âncoras e funciona em uma grade de 9 células com o elemento de ancoragem no centro.

Para usar position-area em vez de posicionamento absoluto, use a propriedade position-area com valores físicos ou lógicos. Exemplo:

  • Parte de cima, no centro: position-area: top ou position-area: block-start
  • Esquerda-centro: position-area: left ou position-area: inline-start
  • Parte inferior central: position-area: bottom ou position-area: block-end
  • Centro-direita: position-area: right ou position-area: inline-end
Demonstração mostrando várias âncoras.

Captura de tela da demonstração.

Para saber mais sobre essas posições, confira esta ferramenta:

Ferramenta de âncora para posições de área de posição.

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 com base no tamanho da âncora (largura, altura ou tamanhos inline e de bloco).

O CSS a seguir mostra um exemplo de uso para altura,usando anchor-size(height) em uma função calc() para definir a altura máxima da dica de ferramenta como o dobro da altura do â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 de anchor-size

Captura de tela da demonstração.

Use a â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 do subárvore DOM, o posicionamento de âncora permite que você os amarre de volta e role com elementos que não estão na camada superior. Essa é uma grande vitória para interfaces em camadas.

No exemplo abaixo, um conjunto de popovers de dica é aberto usando um botão. O botão é a âncora, e a dica é o elemento posicionado. É possível estilizar o elemento posicionado como qualquer outro elemento ancorado. Neste exemplo específico, anchor-name e position-anchor são estilos inline no botão e na dica. Como cada âncora precisa de um nome exclusivo, ao gerar conteúdo dinâmico, o inline é a maneira mais fácil de fazer isso.

Demonstração de uso de âncora com popover

Captura de tela da demonstração.

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

Depois de definir a posição inicial da âncora, ajuste a posição se ela chegar às bordas do bloco que a contém. Para criar posições de âncora alternativas, use a diretiva @position-try com a propriedade position-try-fallbacks.

No exemplo abaixo, um submenu aparece à direita de um menu. Menus e submenus são ótimos usos da API de posicionamento de âncora com o atributo de pop-up, já que tendem a ser ancorados a um botão de acionamento.

Para esse submenu, se não houver espaço suficiente na horizontal, você pode 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);
  position-area: right span-bottom;
}

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

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

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

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

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

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

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

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

Inverter palavras-chave pode simplificar bastante o código de âncora. Com apenas algumas linhas, é possível criar uma âncora totalmente funcional com posições alternativas:

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

position-visibility para âncoras em subrolagens

Em alguns casos, talvez você queira ancorar um elemento em um subrolagem da página. Nesses casos, é possível controlar a visibilidade da âncora usando position-visibility. Quando a âncora fica visível? Quando ele desaparece? Você tem controle sobre essas opções com esse recurso. Use position-visibility: anchors-visible quando quiser que o elemento posicionado permaneça visível até que a âncora fique fora da tela:

#tooltip {
  position: fixed;
  position-anchor: --anchor-top-anchor;
  position-visibility: anchors-visible;
  bottom: anchor(top);
}
position-visibility: anchors-visible Demo

Você também pode usar position-visibility: no-overflow para impedir que a âncora ultrapasse o contêiner.

#tooltip {
  position: absolute;
  position-anchor: --anchor-top-anchor;
  position-visibility: no-overflow;
  bottom: anchor(top);
}
position-visibility: no-overflow Demo

Detecção de recursos e polyfilling

Como o suporte a navegadores é limitado no momento, é recomendável usar essa API com algumas precauções. Primeiro, você pode verificar o suporte diretamente no CSS usando a consulta de recurso @supports. Para fazer isso, envolva os estilos de âncora no seguinte:

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

  /* Anchor styles here */

}

Além disso, é possível usar o polyfill do recurso de posicionamento de âncora com o polyfill de posicionamento de âncora do CSS da Oddbird, que funciona no Firefox 54, Chrome 51, Edge 79 e Safari 10. Esse polyfill oferece suporte à maioria dos recursos básicos de posição de âncora, embora a implementação atual não esteja completa e contenha algumas 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 houver uma relação semântica entre o elemento âncora e o posicionado (por exemplo, o elemento posicionado é um comentário na barra lateral sobre o texto âncora), uma maneira de fazer isso é usar aria-details para apontar do elemento âncora para os elementos posicionados. Os leitores de tela ainda estão aprendendo a lidar com o atributo aria-details, 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 âncora com o atributo popover ou com um elemento <dialog>, o navegador vai processar as correções de navegação de foco para acessibilidade adequada. Assim, não é necessário ter seus popovers ou caixas de diálogo na ordem do DOM. Leia mais sobre a observação sobre acessibilidade na especificação.

Leitura adicional