TL;DR – See Adam’s answer (accepted) or Update #5 in my
question for the current solution. My question shows my journey
getting to that solution in a rather long but explanatory way,
describing pitfalls and limitations.
我正在创建一个模块,为文本中使用的相应单词添加术语表术语描述.使用纯文本描述一切正常.例如,如果有onomasticon(同义词的另一个词)的描述,则使用以下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,例如,< strong>同义词库< / 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>中标签:
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;但这也不起作用(也没有内联),它是无效的HTML5.
虽然在语义上不正确,但我试图转向< dfn>进入< div class =“dfn”>和里面< span>到< 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>或者<引用> – 仅使用CSS.
在我现在研究基于javascript的解决方案之前,我的问题是我是否错过了满足下面列出的要求的选项?
>仅限CSS
>工具提示必须添加到< dfn>,< abbr>或者<引用>一段内
>工具提示内容可能包含以下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块元素进行hacky重写.
更新3:ChristianF的答案有一个非常重要的线索,如何在词汇表术语定义中保留HTML.如果描述不是dfn标签内的元素而是后面的兄弟,我们仍然可以隐藏并显示它,例如使用CSS选择器dfn div.dfn-tooltip.但是,由于大多数词汇表术语都会在一个词组上下文中找到,这将再次打破布局,因为段落中不允许使用div.
所以我们需要一个元素,它既可以用在短语上下文中,也可以包含块元素.根据这个beautiful HTML structure diagram,< 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(最后):亚当的回答提出了一些很好的技巧,以结合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; }
<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>
顺便说一句,如果有人感兴趣,我在一个名为Onomasticon的模块中使用它,它为Drupal 8提供基本的词汇表功能.
Defining term: If the dfn element has a title attribute,then the exact value of that attribute is the term being defined.
因此,您可以有一个简单的解决方案,您可以在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>
我找不到任何标签可以替换这里似乎是唯一一个在这里工作的按钮元素.
因此,我们必须将disabled属性添加到button元素以禁用其按钮行为(焦点)并在dfn元素上设置tabindex以启用箭头导航.