当前位置: 首页 > 面试题库 >

CSS中正确影响父级高度的旋转元素

鲁钱明
2023-03-14
问题内容

假设我有几列,我想旋转其中的一些值:

<div class="container">
    <div class="statusColumn"><span>Normal</span></div>
    <div class="statusColumn"><a>Normal</a></div>
    <div class="statusColumn"><b>Rotated</b></div>
    <div class="statusColumn"><abbr>Normal</abbr></div>
</div>

使用此CSS:

.statusColumn b {
  writing-mode: tb-rl;
  white-space: nowrap;
  display: inline-block;
  overflow: visible;
  transform: rotate(-90deg);
  transform-origin: 50% 50%;
}

问题答案:

假设您希望旋转90度,即使对于非文本元素也可以旋转-但是像CSS中许多有趣的事情一样,它需要一些技巧。根据CSS 2规范,我的解决方案还会从技术上调用未定义的行为-因此,尽管我已经测试并确认它可以在Chrome,Firefox,Safari和Edge中使用,但我不能保证将来不会损坏浏览器版本。

Short answer

给定这样的HTML,您想在其中旋转 .element-to-rotate

<div id="container">
  <something class="element-to-rotate">bla bla bla</something>
</div>

… 在要旋转的元素周围引入两个包装器元素:

<div id="container">
  <div class="rotation-wrapper-outer">
    <div class="rotation-wrapper-inner">
      <something class="element-to-rotate">bla bla bla</something>
    </div>    
  </div>
</div>

…,然后使用以下CSS逆时针旋转(或参阅注释以transform了解将其更改为顺时针旋转的方法):

.rotation-wrapper-outer {
  display: table;
}
.rotation-wrapper-inner {
  padding: 50% 0;
  height: 0;
}
.element-to-rotate {
  display: block;
  transform-origin: top left;
  /* Note: for a CLOCKWISE rotation, use the commented-out
     transform instead of this one. */
  transform: rotate(-90deg) translate(-100%);
  /* transform: rotate(90deg) translate(0, -100%); */
  margin-top: -50%;

  /* Not vital, but possibly a good idea if the element you're rotating contains
     text and you want a single long vertical line of text and the pre-rotation
     width of your element is small enough that the text wraps: */
  white-space: nowrap;
}

堆栈片段演示

p {

  /* Tweak the visuals of the paragraphs for easier visualiation: */

  background: pink;

  margin: 1px 0;

  border: 1px solid black;

}

.rotation-wrapper-outer {

  display: table;

}

.rotation-wrapper-inner {

  padding: 50% 0;

  height: 0;

}

.element-to-rotate {

  display: block;

  transform-origin: top left;

  /* Note: for a CLOCKWISE rotation, use the commented-out

     transform instead of this one. */

  transform: rotate(-90deg) translate(-100%);

  /* transform: rotate(90deg) translate(0, -100%); */

  margin-top: -50%;



  /* Not vital, but possibly a good idea if the element you're rotating contains

     text and you want a single long vertical line of text and the pre-rotation

     width of your element is small enough that the text wraps: */

  white-space: nowrap;

}


<div id="container">

  <p>Some text</p>

  <p>More text</p>

  <div class="rotation-wrapper-outer">

    <div class="rotation-wrapper-inner">

      <p class="element-to-rotate">Some rotated text</p>

    </div>

  </div>

  <p>Even more text</p>

  <img src="https://i.stack.imgur.com/ih8Fj.png">

  <div class="rotation-wrapper-outer">

    <div class="rotation-wrapper-inner">

      <img class="element-to-rotate" src="https://i.stack.imgur.com/ih8Fj.png">

    </div>

  </div>

  <img src="https://i.stack.imgur.com/ih8Fj.png">

</div>

这是如何运作的?

我上面使用的魔咒面对的困惑是合理的;发生了很多事情,总体策略并不简单,需要一些CSS琐事知识才能理解。让我们逐步进行。

我们面临的问题的核心是,使用其transformCSS属性对元素进行的转换都是在布局发生后进行的。换句话说,transform在元素上使用完全不影响其父元素或任何其他元素的大小或位置。绝对没有办法改变这种transform工作方式。因此,为了产生旋转元素并使其父代的高度尊重旋转的效果,我们需要执行以下操作:

以某种方式构造其他元素的高度等于元素的宽度.element-to-rotate
编写我们的转换,.element-to-rotate以便将其准确地覆盖在步骤1的元素上。
步骤1中的元素应为.rotation-wrapper-outer。但是,如何使它的高度等于.element-to-rotate的宽度呢?

我们策略中的关键部分是padding: 50% 0on .rotation-wrapper-inner。此漏洞利用是该规范的怪异细节padding:即使对于padding-top和padding-bottom,填充百分比也总是定义为元素容器宽度的百分比。这使我们能够执行以下两步技巧:

我们设定display: table的.rotation-wrapper-outer。这将导致其具有“ 收缩至适合”宽度,这意味着将根据其内容的固有宽度(即基于的固有宽度)来设置其宽度.element-to-rotate。(在支持的浏览器,我们可以更干净地做到这一点width: max-content,但截至2017年12月,max-content是仍然不支持边)。
我们将heightof 设置.rotation-wrapper-inner为0,然后将其填充设置为50% 0(即50%顶部和50%底部)。这将导致它占用等于其父级宽度100%的垂直空间-通过第1步中的技巧,它等于的宽度.element-to-rotate。
接下来,剩下的就是执行子元素的实际旋转和定位。自然地,transform: rotate(-90deg)旋转;我们transform-origin: top left;通常使旋转围绕旋转元素的左上角发生,这使得随后的平移更容易推论,因为它使旋转元素直接位于原本应绘制的位置上方。然后,我们可以使用translate(-100%)向下拖动元素,使其距离等于其预旋转宽度。

那仍然不能完全正确地定位,因为我们仍然需要为上的50%顶部填充补偿.rotation-wrapper-outer。我们通过确保.element-to-rotate具有display: block(使边距在其上正常工作)然后应用-50%来实现这一点margin-top-请注意,还相对于父元素的宽度定义了边距百分比。

就是这样!

为什么不完全符合规范?
由于以下规范中的填充百分比和边距定义(注释矿井),请注意以下几点:

即使对于’padding-top’和’padding-bottom’而言,百分比也是相对于所生成的盒子的包含块的宽度来计算的。如果包含块的宽度取决于此元素,则结果布局在CSS 2.1中未定义。

由于整个技巧都围绕着使内部包装器元素的填充相对于其容器的宽度而定,而容器的宽度又取决于其子容器的宽度,因此我们遇到了这种情况并调用了不确定的行为。不过,它目前可在所有4种主要浏览器中使用-与我尝试过的一些看似符合规范的调整方法不同,例如更改.rotation-wrapper-inner为同级.element-to-rotate而不是父级。



 类似资料:
  • 问题内容: 我怎样才能改变父母的背景的时候或者是:focus’d(或任何其他动态伪类? 例如 问题答案: 不幸的是,css不支持父选择器。 因此,唯一的方法就是像jQuery父方法那样使用javascript 。 更新: CSS选择器第4级将支持父选择器

  • 问题内容: 我的页面结构为: 现在,DIV将具有更多内容,因此DIV的高度将根据子DIV的增加而增加。 但是问题是身高没有增加。如何使它的高度等于父代的高度? 问题答案: 对于元素,添加以下属性: 然后针对这些:

  • 这样一段代码 ,如果设置 span的display为inline-block 则div的高度为30px; 如果设置span的display为inline 则div的高度为0. 请问这是什么原因? 我的思路: 我知道行框盒子 和 幽灵空白节点。 对于display为inline-block 我能理解div的高度为什么是30px。每个行框盒子都以一个零宽度,带有元素字体以及行高属性的内框开始,我们称这

  • 问题内容: 如何从指令内部获取和设置元素的父级高度? 这就是我现在所拥有的,显然没有用。 问题答案: 您可以使用jqLit​​e / jQuery的和方法: 或者,您也可以使用带有属性的纯JavaScript来实现,该属性是对父元素的引用: 还要注意,由于这里是一个jqLit​​e / jQuery实例,它是一个元素的类似数组的集合,因此您需要使用它来访问原始HTMLElement。

  • 我有一个公式来获得旋转矩形的高度和宽度,如下所示: 因此,x,y值是旋转后的新高度和宽度。 示例矩形旋转成15度,高度74和宽度110是旋转后的值,我想从这些转换后的值中找出矩形的原点高度(50)和宽度(100),我需要通过公式找出这个像上面一样,所以我可以用不同的值替换。旋转矩形的示例图像

  • 我正在尝试使用绝对定位将标签文本与其相应的输入字段对齐。然而,标签并没有将我的输入div识别为其父级,而似乎是相对于外部登录div定位标签文本。 HTML: CSS: 登录名和密码塞进表单的一角,而不是输入字段