Родитель двух вращающихся divs, чтобы получить ширину и высоту полученного преобразованного div
Кажется, что есть много вопросов по одной и той же проблеме, но не может найти удовлетворительного ответа... У меня есть:
1 container (flex) (green)
2 columns (block) -> left: red, right: orange
in the left column, I have two divs (green) who follow each other 'menu1''menu2'
Эти два меню сами обернуты в div (черный), так что, когда я поворачиваю его, два меню являются вертикальными, а не горизонтальными (вращение на 90 градусов)
Цель состоит в том, чтобы верхняя оболочка/контейнер (зеленая) занимала высоту вертикальной черной обертки, а оболочка левого столбца была не больше ширины развернутой черной обертки.
То, что я получаю, проиллюстрировано в следующем примере:
https://jsfiddle.net/pg373473/
<div id='container' style='display: flex; border: 3px solid green; flex-direction=row'>
<div id='leftbox' style='position: relative; display: block; border: 3px solid red'>
<div id='textwrapper' style='transform-origin: bottom left; transform: translateY(-100%) rotate(90deg); border: 2px solid black;'>
<div style='border: 3px solid green; display: inline-block'>menu 1</div>
<div style='border: 3px solid green; display: inline-block'>menu 2</div>
</div>
</div>
<div id='rightbox' style='position: relative; display: flex; flex: 1 1 auto; border: 3px solid orange';>
xx
</div>
</div>
![введите описание изображения здесь]()
Возможно ли это вообще?
По умолчанию, кажется, что поворот будет применен после, будет рассчитана вся ширина/высота для всех div. Я лично считаю, что это поведение противоречит ожиданиям любого, но может быть, кто-то, кто хорошо знает спецификации, может объяснить, почему это так? Но, в конце концов, мне больше интересно узнать, есть ли решение того, что я пытаюсь достичь (спасибо).
ИЗМЕНИТЬ
Поворот элементов в CSS, которые влияют на их родителей... спрашивает что-то о поворотах, но объяснение не является удовлетворительным, и проблема немного отличается, поскольку она касается только того, чтобы быть уверенным что div от повернутого ребенка учитывает высоту повернутого ребенка. Вопросы, заданные в этом сообщении, имеют 3 ограничения:
- у вас есть 2 divs в строке, которые повернуты на 90 градусов (или более 2)
- контейнер-упаковщик должен принимать:
- ширина
- и высота вращающихся элементов детей.
Вышеупомянутый вопрос задает только высоту и не решает проблему ширины. Кроме того, jsfiddle также не работает.
Единственная хорошая часть этого вопроса - упомянутая в комментариях writing-mode
, но мне также не удалось заставить ее работать с этим. Я пробовал эту опцию, и, хотя я могу исправить проблему с высотой, я не могу заставить ее работать, чтобы исправить проблему с шириной...
<div id='container' style='display: flex; border: 3px solid green; flex-direction: row'>
<div style='display: flex; flex-direction: column; border: 3px solid red; flex: 1 1 auto;'>
<div style='flex: 0 0 auto; display: inline-block; flex-direction: row; writing-mode: vertical-rl; border: 3px solid black;'>
<div style='flex: 0 0 auto; border: 1px solid green; display: inline-block'>menu 1</div>
<div style='flex: 0 0 auto; border: 1px solid green; display: inline-block'>menu 2</div>
</div>
</div>
<div id='rightbox' style='display: flex; flex: 1 1 auto; border: 3px solid orange';>
Right Box
</div>
</div>
![введите описание изображения здесь]()
https://jsfiddle.net/dyae4xru/
Для ясности вот что я хочу:
![введите описание изображения здесь]()
ОТВЕТ/РЕДАКТИРОВАТЬ 2
На данный момент решения этой проблемы нет. CSS/HTML/Браузеры не поддерживают это из коробки. Я исправил проблему, написав небольшую JS-функцию, которая дает мне точную ширину и высоту div при горизонтальной настройке и использует значения для установки ширины div, повернутого на 90 градусов (используя writing-mode: vertical-rl
).
Ответы
Ответ 1
Могут быть хакерские решения, но я бы сказал, что CSS-преобразования не созданы для чего-то вроде этого.
Если свойство имеет значение, отличное от none, то контекст стекирования будут созданы. В этом случае объект будет действовать как содержащий блок для позиции: фиксированные элементы, которые он содержит.
Источник: MDN
(см. этот пост для вопроса масштабирования преобразования.)
Я предлагаю вам использовать новый CSS writing mode
- см. здесь для поддержки браузера:
Свойство CSS в режиме записи определяет, будут ли уложены строки текста горизонтально или вертикально и направление, в котором блоки прогресс.
Используйте writing-mode: vertical-lr
в div - см. демонстрацию ниже, которая работает в Chrome:
#container {
display: flex;
border: 1px solid green;
flex-direction: row;
}
#container>div:first-child {
position: relative;
display: block;
border: 1px solid red;
writing-mode: vertical-lr; /* ADDED */
-webkit-writing-mode: vertical-lr;
}
#container>div>div {
/*transform-origin: bottom left;
transform: translateY(-100%) rotate(90deg);*/
border: 2px solid black;
}
#container>div>div>div {
border: 1px solid green;
display: inline-block;
}
#rightbox {
position: relative;
display: flex;
flex: 1 1 auto;
border: 1px solid orange;
}
<div id='container'>
<div>
<div>
<div>menu 1</div>
<div>menu 2</div>
</div>
</div>
<div id='rightbox'>
xx
</div>
</div>
Ответ 2
Я сомневаюсь, что эта задача может быть решена без JavaScript, потому что преобразованные элементы рисуются на отдельных "слоях", и их внешний вид не влияет на свойства DOM. Однако, поскольку ваша трансформация исправлена, вы можете соответствующим образом вычислить приведенный визуальный размер элемента и размер обновления родительского элемента. Кроме того, вы можете использовать наблюдатели мутации для обновления размера вашего контейнера в случае, если его содержимое будет изменено во время выполнения. В этом примере отображается правильный размер контейнера и реагирует на мутации времени выполнения элементов меню. Протестировано в Firefox и Chrome
document.addEventListener('DOMContentLoaded', function () {
const container = document.querySelector('#container .menu-container');
const menu = document.querySelector('#container .menu-items');
let items = [];
const updateItems = () => {
const nodes = document.querySelectorAll('#container .menu-item');
for (let node of nodes) {
if (items.indexOf(node) === -1) {
items.push(node);
new MutationObserver(updateSize).observe(node, {attributes: true, characterData: true, subtree: true});
}
}
updateSize();
}
const updateSize = () => {
container.style.width = menu.offsetHeight + 'px';
container.style.height = menu.offsetWidth + 'px';
}
new MutationObserver(updateSize).observe(menu, {attributes: true, characterData: true});
new MutationObserver(updateItems).observe(menu, {childList: true});
updateItems();
updateSize();
});
#container {
display: flex;
border: 1px solid green;
flex-direction: row;
}
.menu-container {
position: relative;
display: block;
border: 1px solid red;
}
.menu-items {
transform-origin: bottom left;
transform: translateY(-100%) rotate(90deg);
border: 2px solid black;
display: flex;
position: absolute;
}
.menu-item {
border: 1px solid green;
display: inline-block;
white-space: nowrap;
}
#rightbox {
position: relative;
display: flex;
flex: 1 1 auto;
border: 1px solid orange;
}
<div id="container">
<div class="menu-container">
<div class="menu-items">
<div class="menu-item">menu 1</div>
<div class="menu-item">menu 2</div>
</div>
</div>
<div id="rightbox">
xx
</div>
</div>
Ответ 3
Вот мой подход к решению:
Я использую flex на контейнере, а также LEFT BOX, затем пользовательский режим записи вертикальный слева направо и, наконец, гибкий столбец направления, чтобы они складывались.
*,
*:before,
*:after {
/* So 100% means 100% */
box-sizing: border-box;
margin: 0;
padding: 0;
}
.container {
display: flex;
border: 2px solid tomato;
}
.box-left {
flex: 0 2.5%; // change % value for the size you want it!
}
.box-right {
flex: 1 auto;
border: 2px solid green;
}
.box-left ul {
display: flex;
flex-direction: column;
border: 2px solid blue;
}
.box-left ul li {
list-style: none;
writing-mode: vertical-lr;
margin-bottom: 0.5em;
}
<div class="container">
<div class="box-left">
<ul>
<li>menu01</li>
<li>menu02</li>
</ul>
</div>
<div class="box-right">
box right
</div>
</div>
Ответ 4
Я изменил ваш код, и ниже приведен фрагмент CSS и HTML
.
*,
*:before,
*:after {box-sizing: border-box;margin: 0;padding: 0;}
.container {display: flex;border: 2px solid green;}
.left-box {flex: 0 2.5%;}
.right-box {flex: 1 auto;border: 2px solid orange;}
.left-box {flex: 0 5.5%;border: 2px solid red;}
.menu {border: 1.5px solid green;}
.inner-left-box ul {display: flex;flex-direction: column;border: 2px solid black;}
.inner-left-box ul li {list-style: none;writing-mode: vertical-lr;}
<div class="container">
<div class="left-box">
<div class="inner-left-box">
<ul>
<li class="menu">menu 1</li>
<li class="menu">menu 2</li>
</ul>
</div>
</div>
<div class="right-box">Right Box</div>
</div>
Ответ 5
Ответ на вопрос отредактирован для решения writing-mode
. Единственной проблемой был стиль flex: 1 1 auto
на красном граничном div, и его устранение устраняет проблему ширины.
HTML w/Вариант тега стиля
<div id='container' style='display: flex; border: 3px solid green; flex-direction: row'>
<div style='display: flex; flex-direction: column; border: 3px solid red;'>
<div style='flex: 0 0 auto; display: inline-block; flex-direction: row; writing-mode: vertical-rl; border: 3px solid black;'>
<div style='flex: 0 0 auto; border: 1px solid green; display: inline-block'>
menu 1
</div>
<div style='flex: 0 0 auto; border: 1px solid green; display: inline-block'>
menu 2
</div>
</div>
</div>
<div id='rightbox' style='display: flex; flex: 1 1 auto; border: 3px solid orange';>
Right Box
</div>
</div>