プラグインなしでWordPressにツールチップを追加する

Seleccionar idioma
プラグインなしでWordPressにツールチップを追加する
ツールチップの例

ツールチップという用語は、英語への独特の訳語を持っているわけではなく、使用される文脈によって、「ツールチップ」、「ヘルプバルーン」、「ポップアップ説明」、あるいは「ヘルプテキスト」と表現されることもある。

ツールチップは、要素をクリックしたりマウスを置いたりすることで表示されるポップアップメッセージです。これらのツールチップは、永続的なスペースを取ることなく追加情報を提供するために使用されます。アイコンや専門用語、インターフェースのアクションを説明するのに理想的です。

ツールチップはSEOに有害か有益か?

まあ、ほとんどすべてのことに言えることだが、答えはいつも「 場合による」だ。SEOの純粋主義者は、Googleは「隠された」またはマスクされたコンテンツを好まず、その使用には厳しいペナルティを課すと警告しているが、これはコンテンツを「共食い」させる可能性のある乱用のケースでは 極端だろう。しかし、ツールチップは、一定のバランスと最小限のロジックで使用することで、有益なものになります。

ツールチップを使う利点

大まかに言えば、これらのメッセージは、友好的で控えめであれば、ユーザーエクスペリエンスのさまざまな側面の改善に貢献することができる。とりわけ、直帰率を下げ、アクセシビリティを向上させる。また、メインコンテンツに自然になじまないキーワードを追加で使用する機会を提供することもでき、セマンティックSEOに役立ちます。

さらに、クリックスルー率を向上させることもできる。ナビゲーションやコールトゥアクションボタンにツールチップを提供することで、ユーザーをより効果的に誘導し、クリック率の向上につなげることができる。しかし、これらすべてを可能にするためには、いくつかの最低限のガイドラインに従わなければならない。

外観、内容、運営に関する推奨事項

  • HTML要素とARIA属性を使用し、スクリーン・リーダーや検索エンジンがその要素に含まれる情報にアクセスできるようにする。
  • ツールチップは簡潔でなければならない。明らかに、誰もポップアップバナーで膨大な量の情報を読もうとはしませんし、コンテンツの大部分をカバーすることにもなります。 ツールチップには、最小限の、正確で必要な情報が含まれているべきであり、これは、ユーザーが何らかのアクションを実行または完了する際に重要なものであってはなりません。
  • コンテンツは冗長であったり、繰り返されるべきではありません。「重複コンテンツ」を避けるために、有益で必要な追加情報を提供し、それがコンテンツ内で繰り返されていないことを確認してください。
  • カーソルを動かすと消えてしまうようなツールチップはできるだけ避けるか、多くの情報や内容を含まないメッセージにのみ使用するようにしてください。理想的には、クリックするごとに表示され、画面上のどこかを再度クリックすると閉じるようにすることです。
  • 読みやすく、サイズが合っていることを確認する。
  • ツールチップアイコンやツールチップリンクのデザインを20種類も増やさないでください。固定された一貫性のあるデザインは、訪問者が一目でそれらを識別するのに役立ちます。
  • やりすぎは禁物で、関連情報や必要な補足情報へのアクセスを容易にすると思われるところだけに追加するよう、戦略をよく練ること。

コードの特徴と機能

この場合、背景が透明な.png画像が使用されています。

tooltip text="jrmora.comで使用されているツールチップの例" position="auto"]。

画像のURLは、この行のシングルクォーテーションの間に追加される:

$default_image = 'URL-de-tu-imagen';

このようにSVGのHTMLアイコンを使うようにコードを変更すれば、色、背景、太さなどをより簡単に変更できる。

画面端を避けるインテリジェントな自動位置調整。例えば、上端に近づくと、ツールチップは下端に表示されます。

カスタマイズ可能なスタイルで、ツールチップ内に完全に機能するリンクを追加することができます。リンクを追加することはお勧めしませんが、時折必要になることがあるかもしれません。ツールチップにリンクが含まれている場合、クリックしやすくするために、自動的に非表示になるのに200msの遅延があります。

安全なHTMLをサポートします。サポートしています:

<strong>, <em>, <a>, <br>, <span>

ポジション、固定属性、適応属性

Atributos de posición disponibles:  position="auto" (default), top, bottom, left, right

ARIA属性(aria-expanded, role="tooltip")。

レスポンシブデザイン

モバイル対応(クリックで切り替え可能)。

サイズ変更、回転、移動時のリセット

主なCSSクラス

.tooltip-container /* Contenedor principal */
.tooltip-trigger  /* Botón/icono que activa el tooltip */
.tooltip          /* Caja del mensaje emergente */
.tooltip-arrow    /* Flecha indicadora */

JSの主な機能

calculateBestPosition() // Determina si colocar el tooltip arriba, abajo, etc.
showTooltip()          // Muestra el tooltip
hideTooltip()          // Oculta el tooltip con retraso

ショートコードの例

[tooltip text="Texto a mostrar"] 

[tooltip text="Texto a mostrar <strong>en negrita</strong> donde sea" position="auto"] 

[tooltip text="Texto <strong>importante</strong> y <em>énfasis</em>"]

[tooltip text="<a href='https://ejemplo.com' target='_blank'>Visite nuestro sitio</a>"]

このコードは、私が特定のニーズに合わせて使用したものだ。出発点として理解してほしい。これは非常に改良可能です。CSSとJSを分離して(あるいはJavascriptを使わずに)、アイコンを表示せずにコンテンツ内の単語にも適用できるようにすることもできます。

使い方はいつも通り、テンプレートのfunctions.phpに追加するか、テンプレートが更新されても変更を維持したい場合は子テーマに追加するだけです。

コード

/**
 * Shortcode para tooltip con ajuste automático 
 * Un ejemplo de uso: [tooltip text="Texto <a href='#'>enlace</a>" position="auto"]
 */
function custom_tooltip_shortcode($atts) {
    $default_image = 'URL-de-tu-imagen';
    
    $atts = shortcode_atts(
        array(
            'text' => __('Información adicional', 'text-domain'),
            'position' => 'auto',
            'color' => '#6a0000',
            'shadow' => '#9c9c9c',
            'width' => '18px',
            'id' => 'tooltip-' . uniqid()
        ),
        $atts,
        'tooltip'
    );

    // HTML permitido
    $allowed_html = array(
        'strong' => array(),
        'b' => array(),
        'em' => array(),
        'i' => array(),
        'br' => array(),
        'span' => array(
            'style' => array(),
            'class' => array()
        ),
        'a' => array(
            'href' => array(),
            'title' => array(),
            'target' => array(),
            'style' => array(),
            'rel' => array()
        )
    );
    
    $text = wp_kses($atts['text'], $allowed_html);
    $position = in_array($atts['position'], ['top', 'bottom', 'left', 'right', 'auto']) ? $atts['position'] : 'auto';
    $color = sanitize_hex_color($atts['color']);
    $shadow = sanitize_hex_color($atts['shadow']);
    $width = esc_attr($atts['width']);
    $id = sanitize_html_class($atts['id']);

    $output = '
    <span class="tooltip-container" data-position="' . esc_attr($position) . '">
        <button class="tooltip-trigger" aria-describedby="' . $id . '" aria-expanded="false">
            <img src="' . esc_url($default_image) . '" width="' . $width . '" alt="" aria-hidden="true"/>
        </button>
        <span id="' . $id . '" role="tooltip" class="tooltip" style="background-color: ' . $color . '; box-shadow: 0 5px 10px ' . $shadow . ';">
            ' . $text . '
            <span class="tooltip-arrow"></span>
        </span>
    </span>';

    return $output;
}
add_shortcode('tooltip', 'custom_tooltip_shortcode');

/**
 * Estilos CSS optimizados para enlaces
 */
function add_tooltip_styles() {
    echo '
    <style>
    .tooltip-container {
        display: inline-block;
        position: relative;
        vertical-align: middle;
    }

    .tooltip-trigger {
        background: none;
        border: none;
        padding: 0;
        margin: 0 2px;
        cursor: pointer;
        line-height: 1;
    }

    .tooltip {
        position: absolute;
        color: #fff;
        padding: 10px 12px;
        border-radius: 4px;
        font-size: 14px;
        line-height: 1.5;
        width: 220px;
        max-width: 90vw;
        text-align: left;
        visibility: hidden;
        opacity: 0;
        transition: opacity 0.25s ease;
        z-index: 100000;
        pointer-events: none;
    }

    .tooltip a {
        color: #fff !important;
        text-decoration: underline;
        pointer-events: auto !important;
    }

    .tooltip * {
        pointer-events: auto;
    }

    .tooltip-arrow {
        position: absolute;
        width: 0;
        height: 0;
        border: 7px solid transparent;
    }

    /* Posiciones dinámicas */
    .tooltip[data-position="top"] {
        bottom: 100%;
        left: 50%;
        transform: translateX(-50%);
        margin-bottom: 10px;
    }
    .tooltip[data-position="top"] .tooltip-arrow {
        top: 100%;
        left: 50%;
        transform: translateX(-50%);
        border-top-color: inherit;
    }

    .tooltip[data-position="bottom"] {
        top: 100%;
        left: 50%;
        transform: translateX(-50%);
        margin-top: 10px;
    }
    .tooltip[data-position="bottom"] .tooltip-arrow {
        bottom: 100%;
        left: 50%;
        transform: translateX(-50%);
        border-bottom-color: inherit;
    }

    .tooltip[data-position="left"] {
        top: 50%;
        right: 100%;
        transform: translateY(-50%);
        margin-right: 10px;
    }
    .tooltip[data-position="left"] .tooltip-arrow {
        top: 50%;
        right: 0;
        transform: translate(50%, -50%);
        border-left-color: inherit;
    }

    .tooltip[data-position="right"] {
        top: 50%;
        left: 100%;
        transform: translateY(-50%);
        margin-left: 10px;
    }
    .tooltip[data-position="right"] .tooltip-arrow {
        top: 50%;
        left: 0;
        transform: translate(-50%, -50%);
        border-right-color: inherit;
    }

    /* Interacción */
    .tooltip-trigger:hover + .tooltip,
    .tooltip-trigger:focus + .tooltip,
    .tooltip-trigger[aria-expanded="true"] + .tooltip {
        visibility: visible;
        opacity: 1;
    }
    </style>
    ';
}
add_action('wp_head', 'add_tooltip_styles');

/**
 * JavaScript corregido para enlaces clickeables con retraso
 */
function add_tooltip_scripts() {
    echo '
    <script>
    document.addEventListener("DOMContentLoaded", function() {
        // Configurar todos los tooltips
        document.querySelectorAll(".tooltip-container").forEach(function(container) {
            const tooltip = container.querySelector(".tooltip");
            const trigger = container.querySelector(".tooltip-trigger");
            let hoverTimeout;
            let isMouseInTooltip = false;
            const position = container.getAttribute("data-position");

            // Función para calcular posición automática
            function calculateBestPosition() {
                const rect = trigger.getBoundingClientRect();
                const viewportHeight = window.innerHeight;
                const viewportWidth = window.innerWidth;
                const tooltipHeight = 150; // Altura estimada
                const tooltipWidth = 220; // Ancho estimado
                
                const space = {
                    top: rect.top,
                    bottom: viewportHeight - rect.bottom,
                    left: rect.left,
                    right: viewportWidth - rect.right
                };
                
                // Determinar mejor posición disponible
                if (space.top >= tooltipHeight || (space.top >= space.bottom && space.top > 50)) {
                    return "top";
                } else if (space.bottom >= tooltipHeight) {
                    return "bottom";
                } else if (space.right >= tooltipWidth) {
                    return "right";
                } else if (space.left >= tooltipWidth) {
                    return "left";
                }
                return "top"; // Default
            }

            // Actualizar posición (solo para "auto")
            function updatePosition() {
                if (position === "auto") {
                    tooltip.setAttribute("data-position", calculateBestPosition());
                }
            }

            // Mostrar tooltip
            function showTooltip() {
                clearTimeout(hoverTimeout);
                tooltip.style.visibility = "visible";
                tooltip.style.opacity = "1";
                trigger.setAttribute("aria-expanded", "true");
            }

            // Ocultar tooltip con retraso de 200ms
            function hideTooltip() {
                if (!isMouseInTooltip) {
                    hoverTimeout = setTimeout(() => {
                        tooltip.style.visibility = "hidden";
                        tooltip.style.opacity = "0";
                        trigger.setAttribute("aria-expanded", "false");
                    }, 200); // Retraso clave para enlaces
                }
            }

            // Inicializar posición
            updatePosition();

            // Eventos para el botón
            trigger.addEventListener("mouseenter", showTooltip);
            trigger.addEventListener("mouseleave", hideTooltip);
            trigger.addEventListener("focus", showTooltip);
            trigger.addEventListener("blur", hideTooltip);

            // Eventos para el tooltip (mejorados para enlaces)
            tooltip.addEventListener("mouseenter", function() {
                isMouseInTooltip = true;
                clearTimeout(hoverTimeout); // Cancelar ocultamiento
            });

            tooltip.addEventListener("mouseleave", function() {
                isMouseInTooltip = false;
                hideTooltip(); // Iniciar retraso para ocultar
            });

            // Click en el botón (para móviles)
            trigger.addEventListener("click", function(e) {
                e.preventDefault();
                if (tooltip.style.visibility === "visible") {
                    hideTooltip();
                } else {
                    showTooltip();
                }
            });

            // Reajustar posición en eventos
            if (position === "auto") {
                window.addEventListener("resize", updatePosition);
                window.addEventListener("scroll", updatePosition, { passive: true });
            }
        });

        // Cerrar tooltips al hacer clic fuera (excepto en enlaces)
        document.addEventListener("click", function(e) {
            if (!e.target.closest(".tooltip-container") && !e.target.closest(".tooltip a")) {
                document.querySelectorAll(".tooltip").forEach(function(tooltip) {
                    tooltip.style.visibility = "hidden";
                    tooltip.style.opacity = "0";
                });
                document.querySelectorAll(".tooltip-trigger").forEach(function(trigger) {
                    trigger.setAttribute("aria-expanded", "false");
                });
            }
        });
    });
    </script>
    ';
}
add_action('wp_footer', 'add_tooltip_scripts');

関連記事

Este blog se aloja en LucusHost

LucusHost, el mejor hosting