无需插件即可在 WordPress 中添加工具提示

Seleccionar idioma
无需插件即可在 WordPress 中添加工具提示
此处使用的工具提示示例

工具提示一词并没有唯一的英文翻译,它可以被描述为 "tooltip"、"help balloon"、"pop-up description",甚至 "help text",这取决于使用它的语境。

工具提示是与元素交互时出现的弹出信息,可以是点击元素,也可以是鼠标悬停。这些工具提示用于提供额外信息,而不会占用永久空间。非常适合解释界面中的图标、专业术语或操作。

工具提示对搜索引擎优化有利还是有害?

对于几乎所有问题,答案都是 " 视情况而定"。虽然搜索引擎优化纯粹主义者警告说,谷歌不喜欢 "隐藏 "或掩盖的内容,并会严厉惩罚使用这些内容的行为,但这对于可能 "蚕食 "你的内容的滥用情况 来说是极端的。然而,工具提示在使用时保持一定的平衡和最低限度的逻辑性,也是有益的。

使用工具提示的优势

从广义上讲,这些信息如果友好而不突兀,就能有助于改善用户体验的各个方面。其中包括降低跳出率和提高可访问性。它还可以提供机会,使用与主要内容不自然匹配的其他关键词,从而有助于语义搜索引擎优化。

此外,它们还能提高点击率。通过在导航或行动号召按钮中提供工具提示,可以更有效地引导用户,从而提高点击率。但要做到这一切,必须遵循一些最基本的准则。

关于外观、内容和操作的建议

  • 使用 HTML 元素和 ARIA 属性,确保屏幕阅读器和搜索引擎可以访问其中包含的信息。
  • 工具提示必须简短。很明显,没有人会在弹出窗口中阅读大量信息,而你将涵盖大部分内容。 它应包含最基本、准确和必要的信息,而这些信息对于用户执行或完成任何操作都不应是至关重要的。
  • 内容不应多余或重复,确保您提供了更多有用和必要的信息,并且在内容中没有重复,以避免 "重复内容"。
  • 尽量避免在移动光标时消失的工具提示,或者只在信息和/或内容不多的信息中使用工具提示。理想情况下,工具提示应在每次点击时显示,并在您再次点击屏幕上的任何位置时关闭。
  • 确保字迹清晰,尺寸正确。
  • 不要添加二十种不同设计的工具提示图标或工具提示链接,这样只会造成混乱。固定且一致的设计会让访问者一眼就能识别它们。
  • 不要做得太过分,好好规划一下你的策略,只在你认为有助于获取相关和/或必要补充信息的地方添加它们。

代码的特点和功能

本案例使用的是透明背景的 .png图片

在此,您可以测试最终的工作结果 [tooltip text="Example tooltip used in 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 属性(ria-expanded、role="tooltip")。

更新。为图像添加了aria-hidden="true"role="presentation",并为屏幕阅读器隐藏了装饰图标。

通过 aria-label,可以自定义通过简码访问的文本,从而避免重复。

[tooltip text="Contenido" aria_label="Ver detalles sobre este elemento"]

该解决方案符合 WCAG 2.1 AA 标准,并解决了 PageSpeed Insights 关于按钮没有可访问名称的警告。

响应式设计

移动适应性(可点击切换)。

调整大小、旋转或移动时重新设置

主要 CSS 类

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

联署材料的主要功能

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>"]

在性能方面:

  1. 预载资产:预载图像和 CSS。
  2. 懒加载:图像属性加载="lazy",解码="async"。
  3. 条件加载:只有在使用简码时才加载 JS。
  4. 去抖动:优化调整大小和滚动事件。
  5. 优化 CSS:使用 will-change 和现代单位 (min())。
  6. 缓存版本:使用 filemtime() 避免过时缓存。

这套代码是我根据自己的具体需要使用的。请将它作为一个起点。它可以改进。您甚至可以考虑不使用 Javascript,并对其进行调整,以便在不显示图标的情况下也能应用于内容中的单词。

要使用它,只需一如既往地将其添加到 functions.php,以及模板或子主题的assets/css/asstes/js/ 文件夹中(如果想在更新模板时保留更改)。

代码

这就是文件的结构:

your-template/
├── functions.php(在末尾添加 PHP 代码)
├── 资产/
│ ├─── css/
│ │ └└── tooltip.css (CSS 样式)
│ └└─── js/
│ └└─── tooltip.js (JavaScript)

在模板functions.php中添加代码

/**
 * Shortcode para tooltip accesible y optimizado
 * Uso: [tooltip text="Texto" position="auto" color="#6a0000" aria_label="Descripción"]
 */
function accessible_tooltip_shortcode($atts) {
    $default_image = 'https://jrmora.com/wp-content/uploads/2025/07/tooltip-negro.png';
    
    $atts = shortcode_atts(
        array(
            'text' => __('Información adicional', 'text-domain'),
            'position' => 'auto',
            'color' => '#6a0000',
            'shadow' => '#9c9c9c',
            'width' => '18px',
            'id' => 'tooltip-' . uniqid(),
            'aria_label' => __('Mostrar información adicional', 'text-domain')
        ),
        $atts,
        'tooltip'
    );

    // HTML permitido (seguro)
    $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']);
    $aria_label = esc_attr($atts['aria_label']);

    // Preload para la imagen (mejora rendimiento)
    add_action('wp_head', function() use ($default_image) {
        echo '<link rel="preload" href="' . esc_url($default_image) . '" as="image">';
    });

    return '
    <span class="tooltip-container" data-position="' . esc_attr($position) . '">
        <button class="tooltip-trigger" 
                aria-describedby="' . $id . '" 
                aria-expanded="false"
                aria-label="' . $aria_label . '">
            <img src="' . esc_url($default_image) . '" 
                 width="' . $width . '" 
                 alt=""
                 aria-hidden="true"
                 loading="lazy"
                 decoding="async"
                 role="presentation"/>
        </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>';
}
add_shortcode('tooltip', 'accessible_tooltip_shortcode');

/**
 * Carga optimizada de assets
 */
function load_tooltip_assets() {
    global $post;
    
    // CSS externo
    wp_enqueue_style(
        'tooltip-css',
        get_theme_file_uri('/assets/css/tooltip.css'),
        array(),
        filemtime(get_theme_file_path('/assets/css/tooltip.css'))
    );
    
    // JS solo si se usa el shortcode
    if (is_a($post, 'WP_Post') && has_shortcode($post->post_content, 'tooltip')) {
        wp_enqueue_script(
            'tooltip-js',
            get_theme_file_uri('/assets/js/tooltip.js'),
            array(),
            filemtime(get_theme_file_path('/assets/js/tooltip.js')),
            true
        );
    }
}
add_action('wp_enqueue_scripts', 'load_tooltip_assets');

CSS/ tooltip.css(必须保存在此路径 /assets/css/tooltip.css 中)

/* Contenedor principal */
.tooltip-container {
    display: inline-block;
    position: relative;
    vertical-align: middle;
}

/* Botón activador */
.tooltip-trigger {
    background: none;
    border: none;
    padding: 0;
    margin: 0 2px;
    cursor: pointer;
    line-height: 1;
}

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

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

/* Posiciones */
.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;
}

/* Interacción */
.tooltip-trigger:hover + .tooltip,
.tooltip-trigger:focus + .tooltip,
.tooltip-trigger[aria-expanded="true"] + .tooltip {
    visibility: visible;
    opacity: 1;
}

/* Enlaces dentro del tooltip */
.tooltip a {
    color: #fff !important;
    text-decoration: underline;
    pointer-events: auto !important;
}

/* Focus para accesibilidad */
.tooltip-trigger:focus {
    outline: 2px solid #005fcc;
    outline-offset: 2px;
}

Javascript/ Tooltip.js(必须保存在 /assets/js/tooltip.js 路径下)

document.addEventListener("DOMContentLoaded", () => {
    const tooltips = document.querySelectorAll('.tooltip-container[data-position="auto"]');
    if (!tooltips.length) return;

    // Debounce para optimización
    const debounce = (func, wait = 50) => {
        let timeout;
        return (...args) => {
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(this, args), wait);
        };
    };

    // Configurar cada tooltip
    tooltips.forEach(container => {
        const tooltip = container.querySelector('.tooltip');
        const trigger = container.querySelector('.tooltip-trigger');
        let hoverTimeout;
        let isMouseIn = false;

        // Calcular mejor posición
        const calculatePosition = () => {
            const rect = trigger.getBoundingClientRect();
            const viewportHeight = window.innerHeight;
            return (rect.top < viewportHeight / 2) ? 'bottom' : 'top';
        };

        // Actualizar posición (optimizado)
        const updatePosition = debounce(() => {
            tooltip.dataset.position = calculatePosition();
        });

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

        // Ocultar con retraso (para enlaces)
        const hideTooltip = () => {
            if (!isMouseIn) {
                hoverTimeout = setTimeout(() => {
                    tooltip.style.visibility = 'hidden';
                    tooltip.style.opacity = '0';
                    trigger.setAttribute('aria-expanded', 'false');
                }, 200);
            }
        };

        // Eventos
        trigger.addEventListener('mouseenter', showTooltip);
        trigger.addEventListener('mouseleave', hideTooltip);
        trigger.addEventListener('focus', showTooltip);
        trigger.addEventListener('blur', hideTooltip);

        tooltip.addEventListener('mouseenter', () => {
            isMouseIn = true;
            clearTimeout(hoverTimeout);
        });

        tooltip.addEventListener('mouseleave', () => {
            isMouseIn = false;
            hideTooltip();
        });

        // Inicialización
        updatePosition();
        window.addEventListener('resize', updatePosition);
        window.addEventListener('scroll', updatePosition, { passive: true });
    });

    // Cerrar al hacer clic fuera
    document.addEventListener('click', (e) => {
        if (!e.target.closest('.tooltip-container') && !e.target.closest('.tooltip a')) {
            document.querySelectorAll('.tooltip').forEach(t => {
                t.style.visibility = 'hidden';
                t.style.opacity = '0';
            });
        }
    });
});

相关文章

Este blog se aloja en LucusHost

LucusHost, el mejor hosting