[css] 부모의 높이에 올바르게 영향을 미치는 CSS의 회전 된 요소

몇 개의 열이 있으며 그중 일부는 다음 값을 회전하고 싶습니다.

http://jsfiddle.net/MTyFP/1/

<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%;
}

다음과 같이 보입니다.

일련의 4 개의 블록 수준 요소.  세 번째 요소의 텍스트가 회전됩니다.

회전 된 요소가 부모의 높이에 영향을 주어 텍스트가 다른 요소와 겹치지 않도록하는 CSS를 작성할 수 있습니까? 이 같은:

이제 세 번째 열의 텍스트가 상위 상자의 높이에 영향을 미치므로 텍스트가 상자 안에 맞습니다.



답변

90도 회전을 원한다고 가정하면 텍스트가 아닌 요소의 경우에도 가능하지만 CSS의 많은 흥미로운 것들과 마찬가지로 약간의 교활함이 필요합니다. 내 솔루션은 기술적으로 CSS 2 사양에 따라 정의되지 않은 동작을 호출하므로 Chrome, Firefox, Safari 및 Edge에서 작동하는지 테스트하고 확인했지만 향후 중단되지 않을 것이라고 약속 할 수 없습니다. 브라우저 릴리스.

짧은 답변

이와 같은 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;
}

스택 스 니펫 데모

어떻게 작동합니까?

위에서 사용한 주문에 대한 혼란은 합리적입니다. 많은 일이 진행되고 있으며 전반적인 전략은 간단하지 않으며 이해하려면 CSS 퀴즈에 대한 지식이 필요합니다. 단계별로 살펴 보겠습니다.

우리가 직면 한 문제의 핵심은 transformCSS 속성을 사용하여 요소에 적용된 변환이 모두 레이아웃이 발생한 후에 발생 한다는 것입니다. 즉, transform요소를 사용하더라도 부모 또는 다른 요소의 크기 나 위치에는 전혀 영향을주지 않습니다. transform작동 방식에 대한이 사실을 변경할 수있는 방법은 전혀 없습니다 . 따라서 요소를 회전하는 효과를 만들고 부모의 높이가 회전을 고려하도록하려면 다음을 수행해야합니다.

  1. 어떻게 든 높이가 너비와 같은 다른 요소를 구성 하십시오..element-to-rotate
  2. .element-to-rotate1 단계의 요소에 정확히 오버레이하도록 변환을 작성합니다 .

1 단계의 요소는 .rotation-wrapper-outer. 그러나 어떻게 그것의 높이.element-to-rotate‘의 과 같게 만들 수 있습니까?

여기서 우리 전략의 핵심 요소는 padding: 50% 0on .rotation-wrapper-inner입니다. 이 익스플로잇 은 스펙의 특이한 세부 사항입니다.paddingpadding-toppadding-bottom에 대한 백분율 패딩 은 항상 요소 컨테이너 너비의 백분율로 정의됩니다 . 이를 통해 다음 2 단계 트릭을 수행 할 수 있습니다.

  1. 우리는 설정 display: table에서 .rotation-wrapper-outer. 이로 인해 너비맞게 축소 됩니다. 즉, 너비가 콘텐츠의 기본 너비 , 즉 기본 너비를 기반으로 설정됩니다 .element-to-rotate. (브라우저를 지원, 우리는 더 깨끗하게에이를 수 width: max-content, 12 월까지는 2017로 max-content되어 여전히 에지에서 지원되지 않습니다 .)
  2. 우리는 설정 height.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-rotatedisplay: block(그래서 마진이 제대로 작동합니다) 후 50 % 적용 margin-top비율 마진이 참고 – 또한 부모 요소의 너비를 기준으로 정의합니다.

그리고 그게 다야!

이것이 사양을 완전히 준수하지 않는 이유는 무엇입니까?

때문에의 사양에서 비율 패딩과 마진의 정의에서 다음 주 (굵은 글자 광산) :

백분율은 ‘padding-top’‘padding-bottom’의 경우에도 생성 된 상자의 포함 블록 너비 를 기준으로 계산됩니다 . 컨테 이닝 블록의 너비가이 요소에 의존하는 경우 결과 레이아웃은 CSS 2.1에서 정의되지 않습니다.

전체 트릭은 내부 래퍼 요소의 패딩이 자식의 너비에 따라 달라지는 컨테이너의 너비에 상대적이되도록하는 것이므로이 조건에 도달하고 정의되지 않은 동작을 호출합니다. 하지만 현재는 4 개의 주요 브라우저 모두에서 작동합니다. 겉보기에는 사양을 준수 하여 부모 대신 .rotation-wrapper-inner형제로 변경 하는 것과 같이 제가 시도한 접근 방식을 변경하는 것과는 다릅니다 .element-to-rotate.


답변

으로 G-시르에 의해 댓글이 정당하게 지적, 현재 지원은 writing-mode괜찮은 이상입니다 . 간단한 회전과 결합하면 원하는 정확한 결과를 얻을 수 있습니다. 아래 예를 참조하십시오.

.statusColumn {
  position: relative;
  border: 1px solid #ccc;
  padding: 2px;
  margin: 2px;
  width: 200px;
}

.statusColumn i,
.statusColumn b,
.statusColumn em,
.statusColumn strong {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  white-space: nowrap;
  display: inline-block;
  overflow: visible;
}
<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>


답변

불행히도 (?) 이것은 요소를 회전하더라도 여전히 일정한 너비와 높이를 가지며 회전 후에도 변경되지 않는 작동 방식이라고 가정합니다. 시각적으로 변경하지만 사물을 회전 할 때 크기가 변경되는 보이지 않는 포장 상자는 없습니다.

90 ° 미만으로 회전한다고 상상해보십시오 (예 🙂 transform: rotate(45deg): 회전하는 물체의 원래 치수와 실제 회전 값을 기반으로 한 모호한 치수를 가진 보이지 않는 상자를 도입해야합니다.

회전 된 개체

갑자기, 당신은 단지이없는 width그리고 height당신이 회전 한 개체의,하지만 당신은 또한이 width하고 height주변의 “보이지 않는 상자”의. 이 객체의 외부 너비를 요청한다고 상상해보세요. 무엇을 반환할까요? 개체의 너비 또는 새 상자? 둘을 어떻게 구별 할 수 있습니까?

따라서이 동작을 수정하기 위해 작성할 수있는 CSS가 없습니다 (또는 “자동화”라고 말해야 함). 물론 부모 컨테이너의 크기를 직접 늘리거나이를 처리하기 위해 JavaScript를 작성할 수 있습니다.

(명확하게 말하면을 사용하여 element.getBoundingClientRect이전에 언급 한 사각형을 얻을 수 있습니다 .)

으로 사양 설명 :

HTML 네임 스페이스에서 transform 속성은 변형 된 요소를 둘러싼 콘텐츠의 흐름에 영향을주지 않습니다.

즉, 손으로 변경하지 않는 한 변형중인 개체를 둘러싼 내용이 변경되지 않습니다.

객체를 변환 할 때 고려되는 유일한 것은 오버플로 영역입니다.

(…) 오버플로 영역의 범위는 변환 된 요소를 고려합니다. 이 동작은 요소가 상대 위치 지정을 통해 오프셋 될 때 발생하는 것과 유사합니다 .

자세한 내용은이 jsfiddle을 참조하십시오.

실제로 다음을 사용하여이 상황을 개체 오프셋과 비교하는 것이 좋습니다 position: relative.-개체를 이동하더라도 주변 콘텐츠가 변경되지 않습니다 ( ).

JavaScript를 사용하여이를 처리하려면 질문을 살펴보십시오 .


답변

padding콘텐츠를 푸시 하려면 비율 및 의사 요소를 사용 합니다. JSFiddle에서는이를 표시하기 위해 의사 요소를 빨간색으로 남겨두고 텍스트 이동을 보정해야하지만 그게 갈 길이라고 생각합니다.

.statusColumn {
    position: relative;
    border: 1px solid #ccc;
    padding: 2px;
    margin: 2px;
    width: 200px;
}

.statusColumn i, .statusColumn b, .statusColumn em, .statusColumn strong {
  writing-mode: tb-rl;
  white-space: nowrap;
  display: inline-block;
  overflow: visible;
  -webkit-transform: rotate(-90deg);
  -moz-transform: rotate(-90deg);
  -ms-transform: rotate(-90deg);
  -o-transform: rotate(-90deg);
  transform: rotate(-90deg);
  -webkit-transform: rotate(-90deg);

  /* also accepts left, right, top, bottom coordinates; not required, but a good idea for styling */
  -webkit-transform-origin: 50% 50%;
  -moz-transform-origin: 50% 50%;
  -ms-transform-origin: 50% 50%;
  -o-transform-origin: 50% 50%;
  transform-origin: 50% 50%;

  /* Should be unset in IE9+ I think. */
  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
}
.statusColumn b:before{ content:''; padding:50% 0; display:block;  background:red; position:relative; top:20px
}
<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>

http://jsfiddle.net/MTyFP/7/

이 솔루션에 대한 글은 http://kizu.ru/en/fun/rotated-text/ 에서 찾을 수 있습니다.


답변

다른 답변 에서 업데이트 된 버전을 참조하십시오 . 이 답변은 더 이상 유효하지 않으며 더 이상 작동하지 않습니다. 나는 역사적인 이유로 여기에 두겠습니다.


이 질문은 꽤 오래지만, 현재 지원 .getBoundingClientRect()객체와 그 widthheight함께이 깔끔한 방법을 사용할 수있는 능력과 함께 값 transform, 내 솔루션에 언급되어야한다고 생각합니다.

여기 에서 실제로 확인 하십시오 . (Chrome 42, FF 33 및 37에서 테스트되었습니다.)

getBoundingClientRect요소 의 실제 상자 너비와 높이를 계산합니다 . 간단히 말해서 모든 요소를 ​​반복하고 최소 높이를 자식의 실제 상자 높이로 설정할 수 있습니다.

$(".statusColumn").each(function() {
    var $this = $(this),
        child = $this.children(":first");
    $this.css("minHeight", function() {
        return child[0].getBoundingClientRect().height;
    });
});

(일부 수정을 통해 하위 항목을 반복하여 어떤 것이 가장 큰지 알아 내고 부모의 키를 가장 큰 자녀로 설정할 수 있습니다. 그러나 예제를 더 간단하게 만들기로 결정했습니다. 또한 부모의 패딩을 추가 할 수 있습니다. 원하는 경우 높이 또는 box-sizingCSS에서 관련 값을 사용할 수 있습니다 .)

참고하지만, 그게 내가 추가 translate하고 transform-origin당신의 CSS에이 위치는보다 유연하고 정확하게 할 수 있습니다.

transform: rotate(-90deg) translateX(-100%);
transform-origin: top left;


답변

나는 그것이 오래된 게시물이라는 것을 알고 있지만 똑같은 문제로 고투하면서 그것을 발견했습니다. 나를 위해 작동하는 솔루션은 단순히 90deg로 회전하는 div를 둘러싼 다소 조잡한 “낮은 기술”방법입니다.

<br>

div의 대략적인 너비 (회전 후 높이가 됨)를 알면이 div 주위에 br을 추가하여 차이를 보정 할 수 있으므로 그에 따라 위와 아래의 콘텐츠가 푸시됩니다.


답변