如何使用内联元素的 HTML 内容创建纯 CSS 工具提示

2024-01-08

TL;DR - See 亚当的回答(已接受)或更新#5在我的 当前解决方案的问题。我的问题展示了我的旅程 以相当长但解释性的方式找到解决方案, 描述陷阱和限制。

我正在创建一个模块,将术语表术语描述添加到文本中使用的各个单词中。纯文本描述一切正常。例如,如果有 onomaasticon(同义词库的另一个词)的描述,则以下 HTML

<p>An onomasticon is not a dinosaur.</p>

被转换为

<p>An <dfn title="Another word for thesaurus">onomasticon</dfn> is not a dinosaur.</p>

由于内容(文章文本和术语表术语描述)来自允许用户使用 HTML 的 CMS,因此术语的描述可能包含 HTML,例如Another word for <strong>thesaurus</strong>。使用上述技术,事情开始变得混乱:

<p>An <dfn title="Another word for <strong>thesaurus</strong>">onomasticon</dfn> is not a dinosaur.</p>

这是默认情况,因为标签属性可能不包含标签本身。可以通过在内部添加附加元素来绕过此限制dfn标签并添加一些 CSS 来最初隐藏元素:

dfn span {
  display: none;
}
dfn:hover span {
  display: block;
  position: absolute;
  top: 2.2em;
  background: #ccc;
}
<p>An <dfn><span>Another word for <strong>thesaurus</strong></span>onomasticon</dfn> is not a dinosaur.</p>

但现在到了我无法克服的部分。 HTML 标签如<strong>是不会造成问题的内联元素。但是,如果术语的描述包含块元素,则此操作会失败,例如如果描述本身包含在<p> tag:

dfn span {
  display: none;
}
dfn:hover span {
  display: block;
  position: absolute;
  top: 2.2em;
  background: #ccc;
}
<p>An <dfn><span><p>Another word for <strong>thesaurus</strong></p></span>onomasticon</dfn> is not a dinosaur.</p>

这里会发生什么?好吧,由于大多数内联元素中不允许出现块元素,因此外部内联元素将被终止,而内部块元素将放置在紧随其后的位置。因此,CSS 选择器不再起作用,而且最终会出现额外的换行符。当然,人们可能会考虑添加类似的内容dfn span p { display: inline-block; }但这也不起作用(也不起作用inline),这是无效的 HTML5。

虽然语义上不正确,但我尝试转向<dfn> into <div class="dfn">和里面<span> to a <div>同样,因为 dfn、abbr 和 cite 元素也可能只包含短语上下文(就像 span 一样)。这再次失败,因为<div>不被允许进入<p>,再次添加不需要的换行符:

.dfn > div {
  display: none;
}
.dfn:hover div {
  display: inline-block;
  position: absolute;
  top: 2.2em;
  background: #ccc;
}
<p>An <div class="dfn"><div><p>Another word for <strong>thesaurus</strong></p></div>onomasticon</div> is not a dinosaur.</p>

这是我迄今为止旅程的总结,试图实现向内联元素添加工具提示(包含 HTML)的圣杯,例如<dfn>, <abbr> or <cite>- 仅使用 CSS。

在我现在研究基于 javascript 的解决方案之前,我的问题是我是否错过了满足我的要求的选项,如下所列?

  • CSS only
  • 工具提示必须添加到<dfn>, <abbr> or <cite>在一个段落内
  • 工具提示内容可能包含以下 HTML 标签:div、p、h2、img、figure、ul、ol、li

更新1:由于我编写了该模块(PHP),我当然能够操纵该术语的描述。然而,我不只是想剥离一切<p>标签,但尽量保留预期的标记。

更新2:我找到了一个相当粗糙的解决方案。让我们说一下描述onomasticon是一些 HTML 片段,例如:

<p>Another word for <strong>thesaurus</strong></p>
<p><img src="thesaurus.png" /></p>

我的模块现在会将所有块元素转换为具有适当类名的跨度,因此描述变为

<span class="p">Another word for <strong>thesaurus</strong></span>
<span class="p"><img src="thesaurus.png" /></span>

这样,我就有了不应该破坏措辞上下文的内联元素。添加更多 CSS 来设计工具提示并制作span.p表现得有点像p再次,一切都以这样的结果告终。

dfn {
  display: inline-block;
  position: relative;
}
dfn > span {
  display: none;
}
dfn:hover > span {
  display: block;
  position: absolute;
  top: calc(1em + 5px);
  max-width: 20em;
  background: #ccc;
  padding: .5em;
}
dfn img {
  max-width: 12em;
}
dfn > span span.p {
  display: block;
  margin-bottom: .5em;
}
<p>An <dfn><span><span class="p">Another word for <strong>thesaurus</strong></span>
    <span class="p"><img src="http://i.imgur.com/G0bl4k7.png" /></span></span></span>onomasticon</dfn> is not a dinosaur.</p>

这是迄今为止我最好看的选项,支持内联元素工具提示的有限 HTML。然而,它可能不是最好的选择,因为它需要对 HTML 块元素进行黑客重写。

更新3:ChristianF 的回答提供了如何在术语表定义中保留 HTML 的非常重要的线索。如果描述不是元素insidedfn 标签但后面的同级标签,我们仍然可以隐藏和显示它,例如使用 CSS 选择器dfn + div.dfn-tooltip。然而,由于大多数术语表术语都可以在短语上下文中找到,这将再次破坏布局,因为段落内不允许使用 div。

所以我们需要一个可以在短语上下文中使用的元素and包含块元素。根据这个漂亮的HTML结构图 https://i.stack.imgur.com/eFpyI.jpg, the <button>标签将是唯一合适的。

p {
  display: relative;
}
dfn + .dfn-tooltip {
  display: none;
}
dfn:hover + .dfn-tooltip {
  display: block;
  position: absolute;
  top: 3em;
  max-width: 20em;
  background: #ccc;
  padding: .5em;
  border: none;
}
.dfn-tooltip img {
  max-width: 12em;
}
<p>An <dfn>onomasticon</dfn><button class="dfn-tooltip"><p>Another word for <strong>thesaurus</strong></p><p><img src="http://i.imgur.com/G0bl4k7.png" /></p></button> is not a dinosaur.</p>

这看起来很有希望。当然,有两个主要缺点:(1) 这个地方的按钮元素在语义上不正确,(2) 工具提示在悬停时不会保持打开状态,因为它不再是 dfn 标签的子级。

更新4:为了避免第二个缺点,再向前迈出一小步,只需将按钮元素移回到 dfn 标记中,因为上下文是相同的。

dfn {
  position: relative;
  display: inline-block;
}
dfn > .dfn-tooltip {
  display: none;
}
dfn:hover > .dfn-tooltip {
  display: block;
  position: absolute; 
  top: calc(1em + 5px);
  max-width: 20em;
  background: #ccc;
  padding: .5em;
  border: none;
}
.dfn-tooltip img {
  max-width: 12em;
}
<p>An <dfn>onomasticon<button class="dfn-tooltip"><p>Another word for <strong>thesaurus</strong></p><p><img src="http://i.imgur.com/G0bl4k7.png" /></p></button></dfn> is not a dinosaur.</p>

更新 5(最终):Adam的回答提出了一些很好的技巧来融入标题属性的初衷,将所有内容放在一起,这就是我最终得到的结果。

dfn {
  position: relative;
  display: inline-block;
  cursor: help;
}
dfn:before {
  content: attr(title);
}
dfn > .dfn-tooltip {
  display: none;
}
dfn:hover > .dfn-tooltip {
  display: block;
  position: absolute; 
  top: calc(1em + 5px);
  max-width: 20em;
  background: #ccc;
  padding: .5em;
  border: none;
  cursor: help;
}
.dfn-tooltip img {
  max-width: 12em;
}
<p>An <dfn title="onomasticon"><button disabled class="dfn-tooltip"><p>Another word for <strong>thesaurus</strong></p><p><img src="http://i.imgur.com/G0bl4k7.png" /></p></button></dfn> is not a dinosaur.</p>

顺便说一句,如果有人感兴趣,我正在一个名为的模块中使用它拟名词 https://www.drupal.org/project/onomasticon,它为 Drupal 8 提供了基本的术语表功能。


请注意 W3C 说:

定义术语:如果 dfn 元素具有 title 属性,则该属性的确切值就是正在定义的术语.

因此,您可以有一个简单的解决方案,将定义的术语放在title属性,以及里面的定义

dfn::before {content: attr(title);padding: 0 0 1em;}      
dfn button {display: none; position: absolute}
dfn:hover button, dfn:focus button {display: block;}
<p>An
     <dfn title="onomasticon" tabindex="0"><button disabled>
       <p>Another word for <strong>thesaurus</strong></p>
       <p><img src="http://i.imgur.com/G0bl4k7.png" /></p>
      </button></dfn> is not a dinosaur.
</p>

我没有找到任何可以替代这里的标签button元素似乎是唯一在这里工作的元素。

所以我们必须添加disabled归因于button元素以禁用其button行为(焦点)并设置tabindex on the dfn元素以启用箭头导航。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用内联元素的 HTML 内容创建纯 CSS 工具提示 的相关文章

随机推荐