我正在将莎士比亚剧本格式化为 HTML。因为莎士比亚用韵律写作,所以习惯上缩进不在韵律第一拍开始的行,如下所示:
p.indent { padding-left: 100pt; }
<h4>HERMIA</h4>
<p>O me!</p>
<h5>[To Helena]</h5>
<p class="indent">You juggler, you cankerblossom,</p>
<p>You thief of love! What, have you come by night</p>
<p>And stol’n my love’s heart from him?</p>
<h4>HELENA</h4>
<p class="indent">Fine, i’ faith.</p>
<p>Have you no modesty, no maiden shame,</p>
<p>No touch of bashfulness? What, will you tear</p>
<p>Impatient answers from my gentle tongue?</p>
<p>Fie, fie, you counterfeit, you puppet, you!</p>
赫米亚
我啊!
[致海伦娜]
你这个杂耍者,你这个腐烂花,
你这个爱情小偷!怎么,你晚上来了吗
还偷走了我爱人的心?海伦娜
好吧,我相信。
你有没有矜持,没有少女羞,
没有一点羞涩的感觉吗?什么,你会流泪吗
我温柔的舌头不耐烦地回答?
呸呸你个冒牌货你个傀儡你!
但是,最好缩进到前一行的宽度,而不是缩进固定的量。这会产生更接近这个的外观:
赫米亚
我啊!
[致海伦娜]
你这个杂耍者,你这个腐烂花,
你这个爱情小偷!怎么,你晚上来了吗
还偷走了我爱人的心?海伦娜
好吧,我相信。
你有没有矜持,没有少女羞,
没有一点羞涩的感觉吗?什么,你会流泪吗
我温柔的舌头不耐烦地回答?
呸呸你个冒牌货你个傀儡你!
在所需的解决方案中,每个
p.indent
元素的左填充量应等于最近的先前 p
元素的宽度(通常不是最近的先前元素,如 h4
或h5
元素可能会介入)。
我认为我不能用纯 CSS 做到这一点,但我之前对此感到惊讶。如果没有,那么简单的JS?
起初,我以为我可以只读取标题 / 中单词的长度,但如果它是大写或小写,那其实并不相同,而且这不是一个成功的方法。
您确定要手动放置那些“.indent”类吗?标题后面的任何内容怎么样?任何标题后的第一段?无论哪种方式,您使用的工具都是相同的。
对于每个 .indent 段落,确定最近的前一个同级标题 ( 到 ) 您可以使用 .previousSibling https://developer.mozilla.org/en-US/docs/Web/API/Element/previousElementSibling - - 然后要获取标题中实际字体/文本的宽度 - 你有点需要一个跨度或一些不是块级元素(非全角)的子元素/所以,你可以把渲染时就在那里 - 或者用 JS 添加它。然后您可以使用 getBoundingClientRect() https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect 检查它们 - 然后您可以检查该宽度并使用它来设置缩进它的同级段落。我认为这就像您所得到的一样简单。或者,您可以抓取所有元素,然后向下使用 nextSibling 并获取标题后的第一段。
我怀疑这是否可以单独使用 css 来实现。
应用缩进相当简单。 IE 设置
padding-left
值。<p>
标签对是什么。 一旦我们收集了所有对,我们就可以找出最后一个字符的位置并使用它来缩进下一行。
function getLastCharacterCoordinates(element) {
const textNode = element.firstChild;
const textLength = textNode.length;
if (textLength === 0) return null;
const range = document.createRange();
// Set the range to select only the last character
range.setStart(textNode, textLength - 1);
range.setEnd(textNode, textLength);
const rect = range.getBoundingClientRect();
return {
x: rect.left,
y: rect.top
};
}
function setIndent(element, indentSize) {
element.style.paddingLeft = `${indentSize}px`
}
function findPairs() {
// returns an array of pairing <p> tags,
// where the next line should start at the end of the previous line.
const boundary = document.getElementById("boundary");
const children = Array.from(boundary.children);
// Reduce to find pairs of <p> tags separated by any other tag
const result = children.reduce((acc, child, index, arr) => {
// If the current element is <p> and there is a next element
if (child.tagName === 'P' && index < arr.length - 2) {
const nextTag = arr[index + 1].tagName; // Check the tag in between
const nextP = arr[index + 2]; // The tag two steps ahead
// If the element two steps ahead is also a <p> and there is another tag in between
if (nextP.tagName === 'P' && nextTag !== 'P') {
// we found a pair
acc.push([child, nextP]);
}
}
return acc;
}, []);
return result;
}
// call the functions and apply the indents:
const pairs = findPairs()
pairs.forEach(pair => {
const cord = getLastCharacterCoordinates(pair[0])
setIndent(pair[1], cord.x)
})
p,
h1,
h2,
h3,
h4,
h5 {
/* remove default browser margins */
margin: 0;
}
<div id="boundary">
<h4>HERMIA</h4>
<p>O me!</p>
<h5>[To Helena]</h5>
<p>You juggler, you cankerblossom,</p>
<p>You thief of love! What, have you come by night</p>
<p>And stol’n my love’s heart from him?</p>
<h4>HELENA</h4>
<p>Fine, i’ faith.</p>
<p>Have you no modesty, no maiden shame,</p>
<p>No touch of bashfulness? What, will you tear</p>
<p>Impatient answers from my gentle tongue?</p>
<p>Fie, fie, you counterfeit, you puppet, you!</p>
</div>