此前写过一个使用flex布局实现html文件中的双行混排,但是感觉效果不佳。经过几天思考,我认为双行混排的要点其实是两个:
1、正文和批注的文字大小不同;
2、正文和批注的行距相互配合进行设定。
正文和批注的文字大小及行距都可以在css中设定。正文元素的宽度无需限制,真正有点难度的是设定批注元素的宽度。因为每个批注文字数量不同,如果宽度太小,批注将无法完整显示,如果根据每条批注手动设置宽度,在批注太多的时候工作量不小,而且每条批注设置多大的宽度还需要多次测试,非常麻烦,所以应该考虑使用javascript自动计算出合理的宽度并设置。计算批注元素合理的宽度很简单,只需用批注文字长度除以2并向上取整,算出这个数量后求出其宽度即可。根据上述思路,制作示例页面如下:
1、html
<!DOCTYPE html>
<html lang="zh-cn"><head><title>混排效果</title><link rel="stylesheet" type="text/css" href="style.css" /><script src="main.js"></script><script>window.onload = function(){var comments = document.querySelectorAll('.comment');comments.forEach(setCommentWidth);}
</script>
</head>
<body><span class="content">这是一段正文文本</span> <span class="comment" >这是双行夹批混排的注释文本。</span><span class="content">文本。</span><span class="comment">这是一段注释文本</span><span class="content">这是一段比较长的正文文本这是一段比较长的正文文本这是一段比较长的正文文本这是一段比较长的正文文本</span> <span class="comment" >这是一段比较长的注释文本。这是一段比较长的注释文本。这是一段比较长的注释文本。</span><span class="content">这是一段比较长的正文文本这是一段比较长的正文文本这是一段比较长的正文文本这是一段比较长的正文文本</span> <span class="comment" >这是一段比较长的注释文本。这是一段比较长的注释文本。</span></body>
</html>
2、css:
.content {font-size:2em;line-height:1.5em;
}
.comment {font-size:1em;line-height:1em;display:inline-block;
}
3、js:
function setCommentWidth(item, index){var width = item.innerText.length / 2 + 1item.style.width = width + 'em';
}
上面的css在定义宽度时直接使用了em做单位,这样做是比较简单的,因为1个字符宽度就是1em,中间不需要任何转换。如果用px做单位,很可能需要在em与px之间进行转换,这样算出字符数量后才方便计算出px。不影响文档DOM结构的前提下求出em与px转换系数的方法是:
function em2px(DOMElement){return Number(getComputedStyle(DOMElement, "").fontSize.match(/(\d+)px/)[1]);
}
上述页面在edge中的显示效果如下:
调整一下浏览器显示区域的大小,显示效果如下:
可以看到,正文和批注可以比较好地随着显示区域的宽度改变而自动适应,双行假皮的效果也完全显示出来了,批注元素的宽度也可以随内容的长度不同而自动设置为比较合适的值。但是还可以进一步改进。从上面的截图可以看出,有一行正文文本后面有比较大的空白,而批注却从下一行开头了。这主要是因为正文文本后的空白长度小于后面的批注元素计算的长度。如果可以求出正文后面空白的长度,那么将这一条批注截断成两条批注,其中一部分紧接前面的正文,另一部分转入下一行,效果就更好了。但目前还没有想到求出正文最后一行右边空白长度的方法。