Поворот элементов в CSS, которые правильно влияют на их родительскую высоту

Предположим, у меня есть несколько столбцов, из которых некоторые я хотел бы повернуть значения:

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

Normal
Rotated
Normal

С помощью этого CSS:

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

Это выглядит так:

Серия из четырех элементов уровня блока. Текст третьего элемента вращается.

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

Текст третьего столбца теперь влияет на высоту родительского блока таким образом, что текст помещается в поле.

Предполагая, что вы хотите повернуть на 90 gradleусов, это возможно даже для нетекстовых элементов, но, как и многие интересные вещи в CSS, это требует немного хитрости. Мое решение также технически вызывает неопределенное поведение в соответствии со спецификацией CSS 2, поэтому, пока я тестировал и подтвердил, что он работает в Chrome, Firefox, Safari и Edge, я не могу обещать, что он не сломается в будущем релиз браузера.

Короткий ответ

Учитывая такой HTML, где вы хотите повернуть .element-to-rotate

 
bla bla bla

… ввести два элемента оболочки вокруг элемента, который вы хотите повернуть:

 
bla bla bla

… и затем используйте следующий CSS, чтобы повернуть против часовой стрелки (или увидеть пропущенное transform для способа изменить его на rotation по часовой стрелке):

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

Some text

More text

Some rotated text

Even more text

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

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

Повернутый объект

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

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

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

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

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

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

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

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

См. Этот 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 } 
 
Normal
Rotated
Normal

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


Этот вопрос довольно старый, но с текущей поддержкой объекта .getBoundingClientRect() и его значений width и height в сочетании с возможностью использования этого аккуратного метода вместе с transform , я думаю, что мое решение также следует упомянуть.

Смотрите здесь в действии. (Протестировано в Chrome 42, FF 33 и 37.)

getBoundingClientRect вычисляет фактическую ширину и высоту windows элемента. Проще говоря, мы можем прокрутить все элементы и установить его минимальную высоту в фактическую высоту windows своих детей.

 $(".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; 

Как справедливо отмечает G-Cyr , текущая поддержка writing-mode более чем достойна . В сочетании с простым rotationм вы получаете точный результат, который вы хотите. См. Пример ниже.

 .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; } 
 
Normal
Rotated
Normal

Свойство режима записи будет делать это. Текущая поддержка writing-mode более чем достойна . В сочетании с простым rotationм вы получаете точный результат, который вы хотите. См. Пример ниже.

 .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; } 
 
Normal
Rotated
Normal

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

 

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

  • Arrow Box с CSS
  • Как нарисовать круг в CSS?
  • css3 переход анимации при загрузке?
  • Активировать анимацию CSS3 при просмотре содержимого
  • Селектор CSS для имен атрибутов на основе шаблона
  • Заказ объявлений с конкретными поставщиками CSS
  • Выберите каждый элемент N в CSS
  • Являются ли CSS3 :: before и :: после псевдоэлементов, поддерживаемых IE9, или нет?
  • Создайте сетку масонства с помощью flexbox (или другого CSS)
  • Эффект Fade CSS3
  • Фоновое изображение в ключевом кадре не отображается в Firefox или Internet Explorer
  • Давайте будем гением компьютера.