предотвращение переполнения в сетке с ячейкой, содержащей shape-outside
Я пытаюсь построить сетку, в которой в некоторых ячейках есть элементы, сочетающие форму снаружи с некоторым содержанием фраз. Форма треугольная (для простоты), отзывчиво заполняющая половину ячейки.
Моя проблема в том, что содержимое фразы переполняет ячейку (и сетку), и мои попытки подогнать ячейку и сетку нарушают форму снаружи.
В примере я установил фиксированную ширину, чтобы показать проблему — на самом деле я хочу 100%.
2 ответа
Насколько мне известно, единственный способ сделать это именно программно, например, с помощью javascript.
Однако, если вас устраивает приближение, которое в основном работает, то в приведенном ниже коде используются только CSS и HTML.
Основная проблема заключается в том, что плавающий элемент не влияет на поток компоновки, т. е. не влияет на размер своего родителя. Это означает, что другой элемент, текст, используется браузером для определения размера родителя, но он делает это ДО того, как он будет обернут вокруг плавающего элемента, поэтому его кажущаяся высота — это то, что требуется для простого блока текста. В вашем случае прямоугольный треугольник, это означает, что высота составляет только половину от того, что должно быть.
В приведенном ниже коде используется хак, чтобы обойти это, используя фиктивный набор того же текста, но с меньшей шириной, чем половина, что означает, что это примерно приведет к удвоению высоты по сравнению с тем, что было бы в противном случае. Затем манекен скрывается из поля зрения. Затем манекен «покрывается» реальным текстом, помещая реальный текст и плавая в оболочку, содержимое, которое позиционируется абсолютно в 0 0, где поток макета манекена разместил манекен.
Манекен задает высоту, которая задает высоту своей родительской ячейки. Затем другой дочерний элемент, content, может установить свою высоту на 100% от родительской, что является двойной высотой, а затем float и shape-outside могут установить свою высоту на 100% от этой.
Чтобы должным образом содержать поплавок и реальный текст, для отображения их родителя, т. е. содержимого, необходимо установить значение flow-root, чтобы запустить новый блок управления потоком, в противном случае поплавок буквально уплывает в другие места.
Вы можете поиграть с шириной в фиктивных значениях, чтобы получить наилучшее значение для ваших нужд, а также рассмотреть, например, calc( nn% +- nnpx ). Другая тонкая настройка может включать использование box-size: border-box, иначе 100% не означает 100% и т. д.
Для такой адаптивной работы вам понадобится немного javascript.
Демо:
https://vandrieu.github.io/adaptative-shape-outside/
CSS-код:
То же, что и у вас, за исключением того, что я сделал ширину100%
вместо600px
HTML-код:
Только что добавилclass="text"
атрибут в текстовом div
Код JavaScript:
function resizeAllShapes() {
for (const cell of [...document.querySelectorAll('.cell')]) {
let currentCellHeight, textHeight
do {
currentCellHeight = Number(cell.style.height.replace('px', ''))
textHeight = cell.querySelector('.text').clientHeight
cell.style.height = `${textHeight}px`
} while (currentCellHeight !== textHeight)
}
}
new ResizeObserver(resizeAllShapes).observe(document.body)
По сути, для каждой ячейки мы увеличиваем высоту ячейки до тех пор, пока она не совпадет с высотой текста.
Это не работает на первой итерации, потому что, когда мы расширяем треугольник в первый раз, он изменяет макет текста, заставляя текст перетекать еще дальше вниз. Но это не тяжелый цикл процессора, всего после нескольких итераций он просто идеально подходит.
Наблюдатель изменения размера позволяет функции запускаться при загрузке страницы и каждый раз, когда изменяется размер окна.
Извините, я не могу предложить решение на чистом CSS, но я почти уверен, что его нет. Высота фигуры зависит от того, сколько текста должно поместиться, а сколько текста может поместиться, зависит от высоты фигуры, поэтому каждая переменная зависит от другой, поэтому нет декларативного способа сделать это, вам просто нужно декларативно увеличивайте размер фигуры до тех пор, пока она не станет идеальной.
Я надеюсь, что это может помочь.