Cuando colocas una sugerencia o un menú desplegable, a menudo quieres posicionarlo en relación con otro elemento de la página. Si bien existen formas de lograr este efecto con el posicionamiento absoluto, históricamente los requisitos más complejos recurrieron al posicionamiento de elementos con JavaScript.
El posicionamiento de anclaje de CSS proporciona una forma de posicionar de forma declarativa un elemento en relación con otro.
Elementos de amarre
Para convertir un elemento en un ancla, asígnale un valor anchor-name
de cualquier cadena que comience con dos guiones. Este es el identificador que usará el elemento posicionado para encontrar su ancla, y es útil darle un nombre descriptivo. Incluso puedes asignar varios nombres de anclaje a un elemento si se usará como anclaje de diferentes maneras.
Deberás establecer algunas propiedades en el elemento posicionado para que se pueda vincular. Primero, debes sacar el elemento del flujo del documento para que flote. Para ello, configura position: absolute
o position: fixed
.
A continuación, deberás establecer a qué ancla deseas vincular el objeto estableciendo position-anchor
en el nombre del ancla que estableciste en el ancla.
Por último, deberás establecer la posición del ancla. Obtendrás más información sobre position-area
más adelante en este módulo.
#anchor {
anchor-name: --my-anchor;
}
#positionedElement {
position: absolute;
position-anchor: --my-anchor;
position-area: end;
}
Amarres implícitos
Los elementos emergentes son aún más fáciles de vincular. Cuando abres una ventana emergente con un botón que tiene un popovertarget
o cuando configuras un source
con showPopover({source})
, la ventana emergente ya tiene un "anclaje implícito" establecido. Dado que, de forma predeterminada, un elemento emergente ya flota con position: fixed
, para posicionarlo, solo debes establecer la posición.
#anchor{}
#positionedElement {
position-area: end;
margin: unset;
}
Cómo definir el alcance de los posibles anclajes
Puedes implementar el posicionamiento de anclaje como parte de un componente, de modo que puedas usar un patrón como un menú desplegable en varios lugares. Si usas el mismo anchor-name
varias veces, ¿cómo te aseguras de que cada elemento posicionado encuentre el anclaje correcto?
Las soluciones de JavaScript implican agregar IDs únicos a cada ancla y, luego, hacer referencia a ellos desde el elemento posicionado. Esto se vuelve engorroso, y CSS tiene una solución más simple con anchor-scope
.
La propiedad anchor-scope
establece qué nombres de anclaje se compararán solo entre un elemento y sus elementos secundarios. Acepta una lista de uno o más nombres de anclaje o la palabra clave all
para limitar el alcance de todos los nombres de anclaje definidos.
Lo ideal es agregar un anchor-scope
a un elemento superior tanto del elemento posicionado como del elemento de anclaje que no contenga otros elementos de anclaje con el mismo nombre. A menudo, se encuentra en la raíz del componente reutilizable.
En el siguiente ejemplo, se muestra la diferencia que genera anchor-scope
cuando se aplica a elementos repetidos con el mismo anchor-name
. En el ejemplo, todos los elementos <img>
y los banners de imágenes hacen referencia al nombre de anclaje --image
. Cuando se aplica anchor-scope
a los elementos <li>
, position-anchor: --image
solo coincidirá con el elemento <img>
dentro del mismo elemento <li>
que el banner. De lo contrario, coincidirá con el último elemento <img>
renderizado.
Posicionamiento
Ahora que ya uniste el elemento a tu ancla, es momento de posicionarlo. El posicionamiento de anclaje proporciona dos métodos de posicionamiento: position-area
y la función anchor()
.
position-area
La propiedad position-area
te permite posicionar un elemento alrededor del ancla especificando una o dos palabras clave. Esto abarca muchos casos de uso comunes y, a menudo, es un buen punto de partida.
Cómo funciona position-area
position-area
funciona creando un nuevo bloque contenedor para el elemento posicionado en un área generada por los bordes del ancla y el bloque contenedor original del elemento posicionado.
Si bien hay muchas palabras clave disponibles para position-area
, se pueden dividir en algunas categorías para que sean más fáciles de comprender. Anchor-tool.com es una excelente herramienta para explorar la sintaxis.
Palabras clave físicas
Puedes usar las palabras clave físicas top
, left
, bottom
, right
y center
. Por ejemplo, position-area: top right
colocará el elemento posicionado arriba y a la derecha del elemento de anclaje. Estas palabras clave también tienen equivalentes de ejes físicos: y-start
, x-start
, y-end
y x-end
.
Palabras clave lógicas
También puedes usar palabras clave lógicas, block-start
, block-end
, inline-start
y inline-end
. Por ejemplo, position-area: block-end inline-start
colocará el elemento posicionado debajo y a la izquierda del elemento de anclaje en idiomas como el inglés, o después del elemento de anclaje en el eje de bloque y antes del elemento de anclaje en el eje intercalado en el modo de escritura del documento. center
también se puede usar con una palabra clave lógica.
También puedes omitir el eje si especificas palabras clave lógicas, con el eje de bloqueo primero y el eje intercalado segundo. position-area: start end
es lo mismo que position-area: block-start inline-end
o incluso position-area: inline-end block-start
.
Abarca varias áreas de la cuadrícula
Hasta ahora, es posible que hayas notado que estas opciones solo te permiten colocar el elemento posicionado dentro de un solo espacio de cuadrícula. Agregar el prefijo span
a las propiedades físicas o lógicas agrega el espacio de la cuadrícula central adyacente. position-area: span-top right
se posicionará a la derecha del ancla y desde la parte inferior del ancla hasta la parte superior del bloque contenedor original del elemento posicionado.
Una posición y un área comunes para un menú desplegable son position-area: block-end span-inline-end
.
La palabra clave span-all
abarca 3 filas o columnas.
Palabra clave única
Si solo estableces una palabra clave, el otro eje se configurará automáticamente. En gran medida, funciona como esperarías, pero puede ser útil comprender cómo funciona.
Si la palabra clave proporcionada es clara sobre su eje, el otro eje se calcula como span-all
. Esto significa que position-area: bottom
es equivalente a position-area: bottom span-all
, y el elemento posicionado estará debajo del elemento de anclaje y tendrá disponible todo el ancho del bloque contenedor.
Por otro lado, si la palabra clave no indica claramente un eje, se repite. position-area: start
es equivalente a start start
y se coloca en la parte superior izquierda del anclaje en los idiomas que se leen de izquierda a derecha.
La función anchor()
Para casos de uso más avanzados, es posible que position-area
no cumpla con tus requisitos. La función anchor()
te permite establecer propiedades de inserción individuales según la posición de otro elemento. Esto se resuelve en una longitud de CSS, lo que significa que puedes usarla en cálculos y con otras funciones de CSS. Además, también puedes unir diferentes lados a diferentes anclajes.
La función anchor()
toma un nombre de anclaje y un lado de anclaje. Si tu elemento tiene un anclaje predeterminado, ya sea establecido con position-anchor
o de forma implícita, por ejemplo, con un elemento emergente, puedes omitir el nombre del anclaje.
.positionedElement {
block-start: anchor(--my-anchor start);
/* OR */
position-anchor: --my-anchor;
block-start: anchor(start);
}
Valores de resguardo
Si no se puede encontrar un anclaje para una función anchor()
, toda la declaración no será válida. Esto puede suceder si el ancla se renderiza después del elemento posicionado o si no hay un elemento con un anchor-name
coincidente. Para controlar esto, puedes establecer una duración o un porcentaje de resguardo.
.positionedElement {
block-start: anchor(--my-anchor, 100px)
}
En el ejemplo anterior, el valor izquierdo del elemento posicionado está anclado a --focused-anchor
, pero ese anchor-name
solo existe cuando se coloca el cursor sobre el primer botón o se enfoca en él. Dado que una función anchor()
se resuelve en una longitud, puedes usar otro anclaje como alternativa. Si no proporcionamos una alternativa, el elemento posicionado no se posicionaría.
Palabras clave de la posición lateral del ancla
El valor del lado de anclaje elige contra cuál de los bordes del anclaje se posicionará. De manera similar a position-area
, el valor del lado de anclaje admite varios tipos diferentes de sintaxis.
Tipo | Valores | Descripción |
---|---|---|
Físico | top , left , bottom , right |
Las palabras clave físicas corresponden a un lado específico del anclaje, pero solo se pueden usar en el mismo eje que la inserción del elemento posicionado que estás configurando. Por ejemplo, |
Margen | inside , outside |
La palabra clave Por ejemplo, |
Lógico | start , end , self-start , self-end |
Las palabras clave lógicas hacen referencia a los lados del ancla según el modo de escritura del elemento posicionado con |
Porcentaje | 0% a 100% |
Un valor de porcentaje coloca el elemento posicionado a lo largo del eje desde el inicio hasta el final del anclaje en el eje especificado. |
En este ejemplo, se muestra cómo un valor de porcentaje siempre va del inicio al final en el eje especificado:
Usa anchor()
Como anchor()
es una longitud, es muy flexible. Puedes manipular el valor con funciones de CSS como max()
y calc()
.
Una limitación es que solo puedes usar funciones anchor()
en propiedades de inserción.
En el ejemplo anterior, se agrega un fondo detrás del panel de detalles abierto que se anima de forma fluida cuando se abre un panel diferente y se estira para incluir un panel de detalles sobre el que se coloca el cursor. Para lograrlo, usa min()
para elegir la longitud más corta entre dos anclajes.
#indicator{
/* Use the smaller of the 2 values: */
inset-block-start: min(
/* 1. The start side of the default anchor, which is the open `<details>` element */
anchor(start),
/* 2. The start side of the hovered `<details>` element. */
anchor(--hovered start,
/* If no `<details>` element is hovered, this falls back to infinity px, so that the other value is smaller, and therefore used. */
var(calc(1px * infinity)))
);
}
En el ejemplo, también se usa calc()
para agregar espacio intercalado alrededor del panel abierto.
Cómo usar el tamaño del ancla
También puedes usar la función anchor-size()
para usar las dimensiones del anclaje para el tamaño, la posición o el margen de tu elemento posicionado.
anchor-size()
toma un nombre de anclaje o usa el anclaje predeterminado. De forma predeterminada, usará el tamaño del anclaje en el eje en el que se usa, por lo que width: anchor-size()
devolverá el ancho del anclaje. También puedes usar el otro eje especificando la longitud que desees, con las palabras clave físicas width
y height
, o las palabras clave lógicas block
, inline
, self-block
y self-inline
.
Cómo controlar el desbordamiento
Creaste un componente de menú desplegable y usaste el posicionamiento de anclaje para colocarlo donde querías. Sin embargo, luego moviste el menú al otro lado de la pantalla o lo usaste para un menú de usuario, y el nombre del usuario es muy largo. De repente, el menú desplegable desaparece de la pantalla. ¿Qué sigue?
El posicionamiento de anclaje de CSS tiene un sistema integrado que te permite crear rápidamente un conjunto sólido de alternativas cuando el elemento posicionado termina fuera de su bloque contenedor.
Opciones de resguardo
La regla position-try-fallbacks
toma una lista de opciones de resguardo. Cuando la posición predeterminada se desborda, se probará cada opción en orden hasta que haya una posición que no se desborde.
Puedes usar cualquier valor de position-area
como opción de resguardo. En este ejemplo, en los modos de escritura de izquierda a derecha, como el inglés, el elemento posicionado intentará ubicarse en la parte inferior del elemento de anclaje, abarcando las columnas central y derecha. Si se desborda, intentará posicionarse en la parte inferior del elemento de anclaje y abarcará las columnas izquierda y central. Si también se desborda, la posición volverá a la posición predeterminada, aunque también se desborde.
.positioned-element {
position-area: block-end span-inline-end;
position-try-fallbacks: block-end span-inline-start;
}
También hay varias palabras clave de flip-
que controlan casos de resguardo comunes. flip-block
y flip-inline
intentan voltear el elemento sobre los ejes de bloque y en línea. También se pueden combinar con flip-block flip-inline
para invertir ambos ejes. El valor flip-start
voltea el elemento posicionado sobre una línea diagonal desde las esquinas inicial y final del elemento de anclaje.
También puedes crear una opción de resguardo personalizada con @position-try
, lo que te permite establecer los márgenes, la alineación y hasta cambiar el anclaje.
@position-try --menu-below {
position-area: bottom span-right;
margin-top: 1em;
}
#positioned-element {
position-try: --menu-below;
}
Se pueden agregar flip-block
y flip-inline
a las opciones de resguardo de @position-try
para crear una variante.
#positioned-element {
position-try: --menu-below, flip-inline --menu-below;
}
En el ejemplo anterior, el navegador sigue estos pasos y se detiene en cuanto encuentra una solución que no desborda.
- El elemento se coloca con
position-area: end
, en la parte inferior derecha del ancla. - Si se desborda, el elemento se coloca con la opción de resguardo personalizada llamada
--bottom-span-right
, que lo coloca conposition-area: bottom span-right
, con un margen adicional debajo. - Si se desborda, el elemento se coloca con
flip-inline --bottom-span-right
, que combina la opción de resguardo personalizada conflip-inline
, que es esencialmenteposition-area: bottom span-left
. - Si se desborda, el elemento se coloca con la opción de resguardo personalizada
--use-alternate
, que lo coloca debajo de un anclaje completamente diferente. - Si se desborda, el elemento vuelve a su ubicación original, con
position-area: end
, aunque se sabe que se desborda.
Pedido de resguardo
De forma predeterminada, cuando la posición inicial se desborda, el navegador probará cada opción en position-try-fallbacks
hasta que encuentre una posición que no se desborde. Puedes anular este comportamiento con position-try-order
para probar cada opción de resguardo y usar la que tenga más espacio en un eje especificado.
Puedes especificar el eje con las palabras clave lógicas, most-block-size
y most-inline-size
, o con las palabras clave físicas most-height
y most-width
.
position-try-order
y position-try-fallbacks
se pueden combinar con la abreviatura position-try
, y el orden se indica primero.
Desplazamiento
Cuando un usuario se desplaza, espera que la página se mueva con fluidez. Para lograr esto, los navegadores tienen límites sobre cómo se puede usar el posicionamiento de anclaje durante el desplazamiento.
Si bien puedes vincular un elemento posicionado a anclajes en diferentes contenedores de desplazamiento, el elemento solo se moverá en respuesta al desplazamiento de uno de los anclajes. Este será el anclaje predeterminado, que puede ser el anclaje implícito de una ventana emergente o el valor de position-anchor
.
Observarás que el elemento posicionado permanece visible incluso cuando el elemento de anclaje se desplaza fuera de la vista. Para ocultar el elemento posicionado cuando se oculta el elemento de anclaje, establece position-visibility: anchors-visible
. Esto no solo se aplica cuando se desplaza en exceso el ancla, sino también si se oculta de otras maneras, por ejemplo, con visibility: hidden
.
Verifica tus conocimientos
¿Cuáles son los valores válidos para el lado en anchor()
?
inside
25%
25px
25px
como valor de resguardo, solo se pueden usar porcentajes para el lado.block-start
start
¿Cuáles son los valores válidos para position-area
?
top
block-end inline-end
block-start block-end
¿Qué propiedades admiten la función anchor()
?
top
margin-left
inset-block-start
transform
¿Qué sucede si hay varios anclajes con el mismo anchor-name
?