两个旋转div的父级,用于获取生成的变换div的宽度和高度

问题描述 投票:14回答:5

似乎有很多关于同一问题的问题,但似乎找不到满意的答案......我有:

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>

enter image description here

这有可能吗?

默认情况下,在计算完所有div的所有宽度/高度后,似乎应用旋转。我个人认为这种行为与任何人的期望相反,但也许有人非常了解这些规格可以解释为什么会如此?但最后,我更感兴趣的是知道我试图实现的是否有解决方案(thx)。

EDIT

Rotate elements in CSS that affect their parents...正在询问关于旋转的问题,但解释并不令人满意,问题略有不同,因为它只是确保旋转的孩子的div考虑到旋转的孩子的高度。这篇文章中提出的问题有3个限制:

  • 你有2个div旋转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>

enter image description here

https://jsfiddle.net/dyae4xru/

为清楚起见,这就是我想要的:

enter image description here

ANSWER / EDIT 2

目前还没有解决这个问题的方法。 CSS / HTML /浏览器不支持开箱即用。我通过编写一个小的JS函数来解决这个问题,该函数在水平时给出了div的精确宽度和高度,并使用这些值设置div旋转90度后的宽度(使用writing-mode: vertical-rl)。

html css css3 flexbox css-transitions
5个回答
4
投票

可能有hacky解决方案,但我会说CSS转换不是为这样的东西构建的。

如果属性的值不是none,则将创建堆叠上下文。在这种情况下,对象将充当位置的包含块:它包含的固定元素。

资料来源:MDN

(有关缩放变换问题,请参阅this post。)


CSS写作模式

我建议你使用更新的CSS writing mode - 请参阅here以获得浏览器支持:

写入模式CSS属性定义文本行是水平放置还是垂直放置以及块进展的方向。

在div上使用writing-mode: vertical-lr - 请参阅下面适用于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>

Firefox中的问题

请注意,这在Firefox中不起作用,因为Flex项目在垂直书写模式下表现不佳 - 存在未解决的问题:

Flexbox中垂直模式的上述问题已在Firefox 60中得到修复,现在您可以看到上述演示适用于Chrome和Firefox。


3
投票

我怀疑没有JavaScript可以解决这个任务,因为转换后的元素是在不同的“层”上绘制的,它们的视觉外观不会影响DOM属性。但是,由于您的转换已修复 - 您可以计算元素的结果可视大小并相应地更新父元素的大小。此外,如果容器的内容将在运行时更改,您可以使用mutation observers更新容器的大小。此示例显示正确的容器大小,并对菜单项的运行时突变做出反应。测试了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>

1
投票

这是我解决方案的方法:

我在容器和LEFT BOX上使用flex,然后用户书写模式从左到右垂直,最后是flex方向列,以便它们堆叠。

*,
*: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>

1
投票

我修改了你的代码,下面是CSS和HTML snippetenter image description here

*,
*: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>

1
投票

答案是问题的writing-mode解决方案的编辑答案。唯一的问题是红色边框div上的flex: 1 1 auto样式,删除它解决了宽度问题。

带有/ Style Tag Variant的HTML

<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>

CSS类变体

#container
{
  display: flex;
  flex-direction: row;
  border: 3px solid green;
}

#leftbox
{
  display: flex;
  flex-direction: column;
  border: 3px solid red;
}

#inner-leftbox
{
  display: inline-block;
  flex-direction: row;
  flex: 0 0 auto;
  writing-mode: vertical-rl;
  border: 3px solid black;
}

#rightbox
{
  display: flex;
  flex: 1 1 auto;
  border: 3px solid orange;
}

.menu
{
  display: inline-block;
  flex: 0 0 auto;
  border: 1px solid green;
}
<div id="container">
    <div id="leftbox">
        <div id="inner-leftbox">
            <div class="menu">menu 1</div>
            <div class="menu">menu 2</div>
        </div>
    </div>
    <div id="rightbox">
        Right Box
    </div>
</div>
© www.soinside.com 2019 - 2024. All rights reserved.