Подтвердить что ты не робот

Повернутые элементы в 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%;
}

Он выглядит следующим образом:

A series of four block-level elements. The third element's text is rotated.

Можно ли написать любой CSS, который заставит повернутый элемент повлиять на его родительскую высоту, чтобы текст не перекрывал другие элементы? Что-то вроде этого:

The third column's text now affects its parent box's height such that the text fits within the box.

4b9b3361

Ответ 1

Предполагая, что вы хотите повернуть на 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;
}

Демо-версия

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>

Ответ 2

К сожалению (?), вот как он должен работать, даже если вы вращаете свой элемент, он все еще имеет определенную ширину и высоту, что не меняется после вращения. Вы визуально меняете его, но нет невидимой оберточной коробки, которая меняет свой размер при повороте вещей.

Представьте себе, что он вращается меньше 90 °; (например, transform: rotate(45deg)): вам нужно будет ввести такую ​​невидимую коробку, которая теперь имеет неоднозначные размеры, основанные на исходных размерах объекта, который вы вращаете, и фактическое значение вращения.

Rotated object

Внезапно у вас есть не только width, но и height объекта, который вы повернули, но у вас также есть width и height "невидимого окна" вокруг него. Представьте себе, запрашивая внешнюю ширину этого объекта - что бы он вернулся? Ширина объекта или наш новый ящик? Как мы будем различать оба?

Следовательно, CSS не существует, чтобы вы могли писать, чтобы исправить это поведение (или я должен сказать, "автоматизировать" его). Конечно, вы можете увеличить размер своего родительского контейнера вручную или написать для него JavaScript.

(Чтобы быть понятным, вы можете попробовать element.getBoundingClientRect, чтобы получить упомянутый выше прямоугольник).

Как описанный в спецификации:

В пространстве имен HTML свойство преобразования не влияет на поток содержимого, окружающего преобразованный элемент.

Это означает, что никакие изменения не будут внесены в контент, окружающий объект, который вы трансформируете, если вы не делаете это вручную.

Единственное, что учитывается при преобразовании объекта - это область переполнения:

(...) степень области переполнения учитывает преобразованные элементы. Это поведение похожее на, что происходит, когда элементы смещаются через относительное позиционирование.

Посмотрите этот jsfiddle, чтобы узнать больше.

На самом деле неплохо сравнить эту ситуацию с смещением объекта, используя: position: relative - окружающий контент не изменяется, даже если вы перемещаете свой объект ().


Если вы хотите обработать это с помощью JavaScript, просмотрите этот вопрос.

Ответ 3

Используйте проценты для 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>

Ответ 4

См. Обновленную версию в моем другом ответе. Этот ответ больше не действителен и просто больше не работает. Я оставлю его здесь по историческим причинам.


Этот вопрос довольно старый, но с текущей поддержкой объекта .getBoundingClientRect() и его значений width и height в сочетании с возможностью использования этого аккуратного метода вместе с 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-sizing в CSS.)

Заметьте, однако, что я добавил translate и transform-origin в ваш CSS, чтобы сделать позиционирование более гибким и точным.

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

Ответ 5

Как справедливо отмечает G-Cyr, текущая поддержка 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>

Ответ 6

Свойство режима записи будет делать это. Текущая поддержка 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>

Ответ 7

Основываясь на ответе Брэма Ванвиса, здесь представлен компонент RotatedImage React

https://codesandbox.io/s/42mo26oy5x

Ответ 8

Я знаю это старое сообщение, но я нашел его, борясь с одной и той же проблемой. Решение, которое работает для меня, является довольно грубым методом "низких технологий", просто окружая div, который я поворачиваю на 90 градусов с большим количеством

<br>

Зная приблизительную ширину (которая становится высотой после вращения) div, я могу компенсировать разницу, добавив br вокруг этого div, поэтому содержимое выше и ниже подталкивается соответственно.