<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 标签内部添加一个额外的元素,并添加一些 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>
但现在有个问题,我无法克服。像<strong>
这样的HTML标签是内联元素,不会造成问题。但是,如果该术语的描述包含块级元素,则会失败,例如,如果描述本身包含在<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; }
的东西,但这也不起作用(inline
也是如此),它是无效的 HTML5。
虽然这样语义上不正确,但我尝试将 <dfn>
改为 <div class="dfn">
,内部的 <span>
也改为 <div>
,因为 dfn、abbr 和 cite 元素只能包含短语内容(就像 span 一样)。但由于 <p>
不允许包含 <div>
,所以还是会加入不需要的换行符:
.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>
这是我迄今为止的旅程总结,试图通过仅使用CSS将包含HTML的工具提示添加到行内元素(如<dfn>
、<abbr>
或<cite>
)。
现在,在我查看基于javascript的解决方案之前,我的问题是是否错过了符合我以下要求的选项?
- CSS only
- 必须将工具提示添加到段落中的
<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>
我的模块现在将所有块级元素转换为带有适当类名的,因此描述变为
<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块元素进行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;
}
<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>
顺便说一下,如果有人感兴趣的话,我正在一个名为Onomasticon的模块中使用它,该模块为Drupal 8提供了基本的词汇表功能。
br
标签代替p
标签吗?诚然,从语义上讲不是最干净的解决方案,但它完全合法。 - ChristianF<p>
替换为<span class="p">
,并添加以下CSS:span.p {display: block; margin-bottom: .5em;}
- Paul