【问题标题】:Parent of two rotated divs to take width and height of resulting transformed div两个旋转 div 的父级以获取转换后 div 的宽度和高度
【发布时间】:2018-03-24 17:54:15
【问题描述】:

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

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 的所有宽度/高度之后应用的。我个人认为这种行为违背了任何人的预期,但也许非常了解规格的人可以解释为什么会这样?但最后,我更想知道是否有解决我试图实现的目标(谢谢)。

编辑

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

  • 您有 2 个连续旋转 90 度(或超过 2 个)的 div
  • 包装容器需要承担:
    • 宽度
    • 和子旋转元素的高度

上述问题只问高度,并没有解决宽度问题。此外,jsfiddle 也不起作用。

关于这个其他问题的唯一好处是writing-mode 的 cmets 中提到的,但我也没有设法使它与这个问题一起工作。我试过这个选项,虽然我可以解决高度问题,但我无法解决宽度问题......

<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/Browsers 不支持开箱即用。我通过编写一个小的 JS 函数解决了这个问题,该函数为我提供了水平时 div 的确切宽度和高度,并使用这些值来设置 div 旋转 90 度后的宽度(使用writing-mode: vertical-rl)。

【问题讨论】:

  • @Ncardeli:不是,请参阅我上面的编辑。如果旧问题有一个可行的解决方案(这不是黑客),那么一个问题只能被认为是重复的,而您指出的问题不是这种情况(我之前看过)。谢谢
  • hacky $('parent').height($('selector').width()+border)
  • 谢谢乔希。是的,这是一个 hack,并且使用 jquery ......但是确实使用 JS 可以做到这一点,但这绝对是一个 hack。
  • 你能添加一张你想要实现的布局的图片吗!

标签: html css flexbox css-transitions


【解决方案1】:

可能有 hacky 解决方案,但我想说 CSS 转换不是为这样的事情而构建的。

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

来源:MDN

(请参阅this post 了解缩放 变换问题。)


CSS 编写模式

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

writing-mode 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 项目 在垂直书写模式下表现不佳 - 存在未解决的问题:

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

【讨论】:

  • 非常感谢,我已经尝试过我的帖子中提到的写作模式,虽然我得到它的工作高度不能解决宽度问题,如您的代码 sn-p 所示.这个问题可能没有解决方案。我也会说,正如帖子中提到的,CSS 转换和写作模式应该是这样的。它应该开箱即用,并且现在的行为与您将块嵌入 HTML 中的块的方式不一致。
  • @user18490 更新答案以反映当前情况,谢谢!
【解决方案2】:

我怀疑这个任务可以在没有 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 以获得动态工作解决方案。我认为这是最好的答案,尽管必须混合 JS 和 CSS。从转换中交换高度和宽度的问题弄乱了我的解决方案。
【解决方案3】:

这是我的解决方法:

我在容器和 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>

【讨论】:

  • 我在 Linux 的 Firefox(57.0b7) 和 Chrome(59.0.3071.115) 上试了一下。
  • 这是一个很好的努力,但你强制旋转 div 的宽度。这个我也可以。我对无需修改 div 高度和宽度的解决方案感兴趣。我的观点是,默认情况下正确的行为是父宽度和高度应该“环绕”在子边界框周围。这是 UI 构建的简单基本原则。所以我的问题是:要么这是可能的,我不知道怎么做,要么根本不可能,我想在这篇文章中指出,在我看来,这不是标准行为应该是的。
【解决方案4】:

我修改了你的代码,下面是 CSS 和 HTML sn-p.

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

【讨论】:

  • 感谢您的努力。请在上面和下面查看我的 cmets。我寻找一种自动的解决方案,而不是您在 CSS 中看到 div 的宽度或高度的解决方案。谢谢
【解决方案5】:

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

带有样式标签变体的 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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-30
    • 1970-01-01
    相关资源
    最近更新 更多