Родитель двух вращающихся 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>