
工具提示一词并没有唯一的英文翻译,它可以被描述为 "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>"]
在性能方面:
- 预载资产:预载图像和 CSS。
- 懒加载:图像属性加载="lazy",解码="async"。
- 条件加载:只有在使用简码时才加载 JS。
- 去抖动:优化调整大小和滚动事件。
- 优化 CSS:使用 will-change 和现代单位 (min())。
- 缓存版本:使用 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';
});
}
});
});