如何为内联元素创建包含HTML内容的纯CSS工具提示

Pau*_*aul 9 html css php tooltip css3

TL; DR - 在我的问题中查看Adam的答案(已接受)或更新#5以获取当前解决方案.我的问题表明我的旅程以相当长但解释的方式达到了解决方案,描述了陷阱和局限.

我正在创建一个模块,为文本中使用的相应单词添加术语表术语描述.使用纯文本描述一切正常.例如,如果有onomasticon(同义词的另一个词)的描述,则使用以下HTML

<p>An onomasticon is not a dinosaur.</p>
Run Code Online (Sandbox Code Playgroud)

转换为

<p>An <dfn title="Another word for thesaurus">onomasticon</dfn> is not a dinosaur.</p>
Run Code Online (Sandbox Code Playgroud)

由于内容(文章文本和术语表术语描述)来自允许用户使用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>
Run Code Online (Sandbox Code Playgroud)

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

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

但现在来了,我没有克服.HTML标记就像<strong>内联元素一样,不会造成问题.但是,如果术语的描述包含块元素,则会失败,例如,如果描述本身包含在<p>标记中:

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

这里发生了什么?好吧,由于大多数内联元素中不允许使用块元素,因此外部内联元素将被终止,内部块元素将被放置在其后.因此,CSS选择器不再工作,加上你最终会有额外的换行符.当然,人们可能会考虑添加类似的东西,dfn span p { display: inline-block; }但这也不起作用(两者都没有inline),它是无效的HTML5.

虽然语义上不正确,我试图把<dfn>进入<div class="dfn">和内部<span><div>,以及因为DFN,缩写和引用元素可能只包含措辞方面,以及(就像跨度).由于<div>不允许进入内部<p>,这再次失败,再次添加了不需要的换行符:

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

这是我到目前为止的旅程总结,试图达到将包含HTML的工具提示添加到内联元素(例如<dfn>,<abbr><cite>仅使用CSS)的圣杯.

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

  • 仅限CSS
  • 提示必须添加到<dfn>,<abbr><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>
Run Code Online (Sandbox Code Playgroud)

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

<span class="p">Another word for <strong>thesaurus</strong></span>
<span class="p"><img src="thesaurus.png" /></span>
Run Code Online (Sandbox Code Playgroud)

这样,我有内联元素,不应该破坏措辞上下文.添加一些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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

到目前为止,这是我最好看的选项,支持内联元素工具提示的有限HTML.但是,它可能不是最佳选择,因为它需要对HTML块元素进行hacky重写.

更新3: ChristianF的答案有一个非常重要的线索,如何在词汇表术语定义中保留HTML.如果描述不是dfn标签的元素而是后面的兄弟,我们仍然可以隐藏并显示它,例如使用CSS选择器dfn + div.dfn-tooltip.但是,由于大多数词汇表术语都会在词组上下文中找到,这将再次打破布局,因为段落中不允许使用div.

因此,我们需要的元素,即可以在措辞方面都使用包含块元素.根据这个漂亮的HTML结构图,<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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

这看起来很有希望.当然,有两个主要的缺点:(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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

更新5(最后):亚当的答案提出了一些很好的技巧,以结合title属性的初衷,把所有东西放在一起,这就是我最终的结果.

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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

顺便说一句,如果有人感兴趣,我在一个名为Onomasticon的模块中使用它,它为Drupal 8提供基本的词汇表功能.

Ada*_*dam 5

请注意,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;}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

我找不到任何可以在这里替换button元素的标签,该元素似乎是唯一在这里工作的元素。

因此,我们必须将disabled属性添加到button元素以禁用其button行为(焦点)并tabindexdfn元素上设置以启用箭头导航。