Есть ли в моем абзаце разрыв столбца? Сколько строк в нем?
В CSS есть концепция вдов и сирот, поэтому в браузере есть способ узнать, сколько строк пересекают границу столбца (или, если печатается, страницы).
Есть ли способ узнать это в JavaScript?
Это может быть сделано очень неприятным и хрупким способом с использованием геометрии элементов, но это кажется довольно нежелательным результатом.
Например: https://codepen.io/notionparallax/pen/BvLZeB
document.querySelectorAll("p, h1, h2, h3, h4, h5").forEach(
(x) => {
let boxW = Math.round(x.getBoundingClientRect().width);
let clientW = Math.round(x.clientWidth);
if (boxW !== clientW) {
console.log(x);
x.classList.add("has-break");
}
try {
if (x.nextElementSibling.offsetLeft !== x.offsetLeft) {
console.log(x);
x.classList.add("end-of-column");
}
} catch(error) {}
}
)
В библиотеке, такой как Paged.js, есть концепция токена разрыва, который указывает, где в элементе происходит разрыв (если действительно есть разрыв). Я полагаю, что такого рода вещи могли бы стать возможными благодаря Гудини. Мне интересно посмотреть, есть ли способ опроса элемента, чтобы увидеть, переносится ли он на следующую страницу/столбец, используя обычные методы.
Случай использования
Я хочу знать, где происходит разрыв элемента, чтобы я мог увидеть, должен ли я вернуться к DOM и поставить разрыв перед предшествующим заголовком. Это частично обрабатывается вдовами и сиротами для самого элемента, но я хотел бы иметь возможность иметь более тонкое управление, чтобы, например, глава не начиналась прямо внизу страницы. Я бы согласился с двумя строками абзаца между двумя абзацами, но абзац, следующий за заголовком, должен получить немного больше передышки.
Обновить
Меня не интересуют решения для варианта использования, меня интересуют ответы на вопрос в заголовке. Вариант использования иллюстрирует одно из возможных применений интересующей меня информации, а не единственную причину вопроса.
Ответы
Ответ 1
Вы можете добавить page-break-before: always;
для тега, это установит разрыв страницы перед тегом. Например, добавление этого CSS в h1 создаст новую страницу перед каждым заголовком h1
h1 {
page-break-before: always;
}
<div>
<h1>Page 1</h1>
<p>content here</p>
<h1>Page 2</h1>
<p>content here</p>
</div>
Ответ 2
🎈 Простое решение
Во-первых, давайте исправим правило для сирот для абзацев, например:
p {
orphans: 2;
}
Тогда сироты правят для заголовков:
h1 + p {
orphans: 4;
}
.new-chapter {
break-before: column;
}
Наконец, нам нужно js, чтобы добавить класс new-chapter
в h1, чтобы предотвратить new-chapter
заголовков от абзаца:
document.querySelectorAll("h1 + p").forEach(p => {
const h1 = p.previousElementSibling
if (h1.offsetLeft !== p.offsetLeft) {
h1.classList.add('new-chapter')
h1.style.opacity = 0.99
}
// after inserting css class need to refresh dom
setTimeout(() => {
h1.style.opacity = 1
}, 2000)
})
Проверьте EMDEMO
Ответ 3
Добавление этого ответа только для будущих читателей в том случае, если API, упомянутый ниже, становится стандартной реализацией в основных браузерах и упрощает js, необходимые для идентификации разрывов столбцов в элементах. Нижеследующее в настоящее время не полезно в производственном коде, поскольку ни один из основных браузеров, о котором я знаю, полностью не реализует приведенный ниже API на момент ответа.
Существует API объектной модели CSS под названием GeometryUtils с getBoxQuads()
который возвращает объекты, представляющие каждый фрагмент CSS узла. Единственный браузер, о котором я знаю, где он в основном реализован во время этого ответа - это Firefox Nightly.
Этот метод позволяет довольно просто идентифицировать разрывы внутри элемента, поскольку он возвращает объект DOMQuad для каждого фрагмента CSS узла, поэтому вы можете сделать что-то вроде...
let frags = document.querySelector('p').getBoxQuads().length;
... где frags
представляет количество фрагментов CSS для выбранного элемента. Если элемент имеет более 1 фрагмента, то происходит разрыв. Вам все еще потребуются дополнительные js для определения количества строк и т.д., Но это позволит вам отделить эти усилия от элементов с разрывом. Если вы заинтересованы в экспериментировании с getBoxQuads()
как показано выше, вам необходимо загрузить Firefox Nightly.