DEV Community

Cover image for Trabajando con múltiples anclajes CSS y popovers dentro del loop de WordPress
Sergio
Sergio

Posted on

Trabajando con múltiples anclajes CSS y popovers dentro del loop de WordPress

Sé que es un tema muy específico, pero en realidad podría aplicarse a cualquier loop. El desafío consiste en tener múltiples tooltips en la misma página que utilicen la API de Popover para alternarlos y el posicionamiento de anclajes en CSS para adjuntar un tooltip a su respectivo elemento ancla.

Cuando se trabaja con popovers, hay muchas piezas en movimiento:

  • Un popover necesita un ID (y, ya que estamos, un rol accesible).
  • Un popovertarget necesita hacer referencia a ese ID.
  • Los IDs deben ser únicos no solo por semántica, sino también para vincular correctamente un popover con su correspondiente popovertarget.

Y eso es solo la parte de la API de Popover. Si miramos los anclajes:

  • Un ancla necesita un anchor-name.
  • Un elemento de destino necesita hacer referencia a ese anchor-name.
  • Cada anchor-name debe ser único para que el objetivo se adjunte correctamente a su ancla.

Estos requisitos ya son desafiantes de por sí. Pero trabajar dentro de un loop lo hace aún más complicado, ya que se necesita una forma de generar IDs y nombres de anclaje únicos para que todo esté correctamente vinculado sin que los elementos entren en conflicto entre sí en la página.

En WordPress, consultamos un array de objetos de página así:

$property_query = new WP_Query(array(
  'post_type'      => 'page',
  'post_status'    => 'publish',
  'posts_per_page' => -1, // ¡Consultamos todas las páginas!
  'orderby'        => 'title',
  'order'          => "ASC"
));
Enter fullscreen mode Exit fullscreen mode

Estructura de HTML deseada

Antes de entrar en nuestro loop while(), me gustaría definir la estructura HTML deseada. Así es como quiero que se vea un objeto de página dentro de su contenedor:

<div class="almanac-group">
  <div class="group-letter"><a href="#">A</a></div>
  <div class="group-list">
    <details id="" class="group-item">
      <summary>
        <h2><code>accent-color</code></h2>
      </summary>
    </details>

    <!-- Se repite para todas las propiedades -->
  </div>
</div>

<!-- Se repite para todo el alfabeto -->
Enter fullscreen mode Exit fullscreen mode

Ahora definimos el tooltip dentro del <details>, ya que representa una única página:

<details id="page" class="group-item">
  <summary>
    <h2><code>accent-color</code></h2>

    <span id="tooltip" class="tooltip">
      <!-- Botón que activa el popover -->
      <button class="info-tip-button" aria-labelledby="experimental-label" popovertarget="experimental-label">  
        <!-- etc. -->
      </button>

      <!-- Contenedor del popover -->
      <div popover id="experimental-label" class="info-tip-content" role="tooltip">
        Característica experimental
      </div>
    </span>
  </summary>
</details>
Enter fullscreen mode Exit fullscreen mode

Estilos CSS básicos para popovers

El diseño no es el foco aquí, pero vale la pena restablecer algunos estilos de popover para evitar que tenga un borde por defecto o aparezca en el centro de la página. Puedes revisar el artículo de Michelle Barker para algunos buenos consejos sobre mejoras progresivas.

.info-tip {
  position: relative; /* Define el contexto de contención */

  /* En caso de que el navegador no soporte el posicionamiento de anclajes */
  [popovertarget] {
    display: none;
  }

  /* Si el navegador soporta anclajes CSS */
  @supports (anchor-name: --infotip) {
    [popovertarget] {
      display: inline;
      position: relative;
    }

    [popover] {
      border: 0; /* Elimina el borde por defecto */
      margin: 0; /* Ajusta la posición */
      position: absolute; /* Necesario */
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Actualmente, es recomendable usar Chrome, ya que Safari y Firefox todavía están trabajando en soportar esta funcionalidad.

Posicionando correctamente el tooltip con anclajes CSS

Para asegurarnos de que el contenido del tooltip aparezca junto al botón, podemos registrar el <button> como un ancla en CSS y hacer que el popover se posicione en relación con él:

.tooltip {
  position: relative;

  @supports (anchor-name: --tooltip) {
    [popovertarget] {
      anchor-name: --tooltip;
      display: inline;
      position: relative;
    }

    [popover] {
      border: 0;
      margin: 0;
      position: absolute;
      position-anchor: --tooltip;
      top: anchor(--tooltip -15%);
      left: anchor(--tooltip 110%);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Generando IDs únicos en WordPress

El problema ahora es que todos los tooltips están apuntando al mismo popover. Necesitamos IDs únicos:

<div popover id="experimental-label-1" class="info-tip-content" role="tooltip">...</div>
<div popover id="experimental-label-2" class="info-tip-content" role="tooltip">...</div>
<div popover id="experimental-label-3" class="info-tip-content" role="tooltip">...</div>
Enter fullscreen mode Exit fullscreen mode

Podemos hacer esto con get_the_id() en WordPress:

$html .= '<div popover id="experimental-label-' . get_the_id() . '" class="info-tip-content" role="tooltip">';
$html .= '<button class="info-tip-button" aria-labelledby="experimental-label-' . get_the_id() . '" popovertarget="experimental-label-' . get_the_id() . '">';
$html .= '<span id="tooltip-' . get_the_id() . '" class="tooltip">';
Enter fullscreen mode Exit fullscreen mode

IDs únicos en CSS

Necesitamos hacer lo mismo con los nombres de anclaje en CSS:

#info-tip-1 {
  [popovertarget] {
    anchor-name: --infotip-1;
  }
  [popover] {
    position-anchor: --infotip-1;
    top: anchor(--infotip-1 -15%);
    left: anchor(--infotip-1 100%);
  }
}

#info-tip-2 {
  [popovertarget] {
    anchor-name: --infotip-2;
  }
  [popover] {
    position-anchor: --infotip-2;
    top: anchor(--infotip-2 -15%);
    left: anchor(--infotip-2 100%);
  }
}
Enter fullscreen mode Exit fullscreen mode

Como alternativa, podríamos usar un <style> generado dinámicamente en PHP:

$html .= '
<style>
  #info-tip-' . get_the_id() . ' {
    [popovertarget] {
      anchor-name: --infotip-' . get_the_id() . ';
    }
    [popover] {
      position-anchor: --infotip-' . get_the_id() . ';
      top: anchor(--infotip-' . get_the_id() . ' -15%);
      left: anchor(--infotip-' . get_the_id() . ' 100%);
    }
  }
</style>';
Enter fullscreen mode Exit fullscreen mode

¿Hay una mejor solución?

Sí, pero todavía no está disponible. Bramus ha propuesto una función ident() para generar nombres de anclaje únicos automáticamente. Cuando se implemente, nos facilitará mucho la vida.

.group-item { 
  anchor-name: ident("--infotip-" attr(id) "-anchor");
}
Enter fullscreen mode Exit fullscreen mode

Hasta que eso suceda, esta solución funciona bastante bien.

Este artículo es una traducción del original en inglés escrito por Geoff Graham , y cuyo enlace es este:
https://css-tricks.com/working-with-multiple-css-anchors-and-popovers-inside-the-wordpress-loop/

Top comments (0)