Добавление всплывающих подсказок в WordPress без плагинов

Seleccionar idioma
Добавление всплывающих подсказок в WordPress без плагинов
Пример всплывающей подсказки, используемой здесь

Термин "подсказка" не имеет однозначного перевода на английский язык, его можно описать как "tooltip", "help balloon", "pop-up description" или даже "help text" в зависимости от контекста, в котором он используется.

Подсказка - это всплывающее сообщение, которое появляется при взаимодействии с элементом, либо при нажатии на него, либо при наведении курсора мыши. Эти всплывающие подсказки используются для предоставления дополнительной информации, не занимая постоянного пространства. Идеально подходят для объяснения иконок, технических терминов или действий в интерфейсе.

Вредят ли всплывающие подсказки SEO или приносят пользу?

Как и почти во всем, ответ всегда зависит от ситуации. Хотя SEO-пуристы предупреждают, что Google не любит "скрытый" или замаскированный контент и жестко наказывает за его использование, это было бы крайностью для случаев злоупотребления , которое могло бы "каннибализировать" ваш контент. Однако всплывающие подсказки, используемые с определенным балансом и минимумом логики, могут быть полезны.

Преимущества использования всплывающих подсказок

В целом эти сообщения, если они дружелюбны и ненавязчивы, могут способствовать улучшению различных аспектов пользовательского опыта. Среди прочего, они снижают процент отказов и улучшают доступность. Кроме того, они дают возможность использовать дополнительные ключевые слова, которые не вписываются в основной контент, что помогает в семантическом SEO.

Кроме того, они могут улучшить показатели кликов. Предлагая всплывающие подсказки в навигации или кнопки призыва к действию, они могут более эффективно направлять пользователей, что приведет к увеличению количества кликов. Но чтобы все это стало возможным, необходимо соблюдать несколько минимальных правил.

Рекомендации по внешнему виду, содержанию и эксплуатации

  • Использование элементов HTML и атрибутов ARIA для обеспечения доступа к содержащейся в них информации с помощью программ чтения с экрана и поисковых систем.
  • Всплывающая подсказка должна быть краткой. Очевидно, что никто не будет читать огромный объем информации во всплывающем окне, и вы будете закрывать большую часть контента. Она должна содержать минимальную, точную и необходимую информацию, и это не должно быть критичным для пользователя при выполнении или завершении какого-либо действия.
  • Контент не должен быть избыточным или повторяющимся, убедитесь, что вы предоставляете дополнительную полезную и необходимую информацию и что она не повторяется в вашем контенте, чтобы избежать "дублирования контента".
  • Старайтесь по возможности избегать всплывающих подсказок, которые исчезают при наведении курсора, или используйте их только в сообщениях, не содержащих большого количества информации и/или контента. В идеале они должны отображаться при нажатии и закрываться при повторном нажатии в любом месте экрана.
  • Убедитесь, что они разборчивы и имеют правильный размер.
  • Не добавляйте двадцать различных дизайнов иконок или ссылок на всплывающие подсказки, это только внесет путаницу. Фиксированный и последовательный дизайн поможет вашим посетителям распознать их с первого взгляда.
  • Не переусердствуйте, хорошо спланируйте свою стратегию, чтобы добавлять их только там, где, по вашему мнению, они облегчают доступ к релевантной и/или необходимой дополнительной информации.

Особенности и функциональные возможности кода

Для этого случая было использовано изображение в формате .png с прозрачным фоном.

Здесь вы можете проверить, как работает конечный результат [tooltip text="Пример всплывающей подсказки, используемой в jrmora.com" position="auto"].

URL-адрес изображения добавляется между одинарными кавычками в этой строке:

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

Если вы решите изменить код, чтобы использовать SVG HTML иконку, как эта, вы сможете легче играть с цветом, фоном, толщиной и т.д.

Интеллектуальная автоматическая настройка положения, чтобы избежать краев экрана. То есть при приближении к верхнему краю всплывающая подсказка отображается внизу, и вивечерса.

Во всплывающую подсказку можно добавить полнофункциональные ссылки с настраиваемыми стилями. Хотя добавлять ссылки не рекомендуется, в некоторых случаях это может понадобиться. В случае, если всплывающая подсказка содержит ссылку, она автоматически скрывается с задержкой в 200 мс, чтобы облегчить нажатие.

Поддержка безопасного 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