Скажем, у меня есть пара столбцов, в некоторых из которых я бы хотел повернуть значения:
<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%;
}
В итоге это выглядит так:
Можно ли написать какой-либо CSS, который заставит повернутый элемент влиять на высоту своего родительского элемента, чтобы текст не перекрывал другие элементы? Что-то вроде этого:
css
css-transforms
Крис
источник
источник
writing-mode
это доступно для большинства браузеров, но ужасно глючит. По поводу связанного с этим вопроса я прошел несколько итераций, пытаясь обойти специфичные для браузера ошибки, прежде чем сдаться; вы можете увидеть мою последовательность сбоев на stackoverflow.com/posts/47857248/revisions , где я начинаю с чего-то, что работает в Chrome, но не с Firefox или Edge, затем ломаю Chrome в процессе исправления двух других и в конечном итоге возвращаю свой ответьте и отметив его как Chrome-only. Будьте осторожны, если хотите пойти по этому пути. (Также обратите внимание, что это бесполезно с нетекстовыми элементами.)Ответы:
Предполагая, что вы хотите повернуть на 90 градусов, это возможно даже для нетекстовых элементов, но, как и многие другие интересные вещи в CSS, это требует некоторой хитрости. Мое решение также технически вызывает неопределенное поведение в соответствии со спецификацией CSS 2 - поэтому, хотя я протестировал и подтвердил, что оно работает в Chrome, Firefox, Safari и Edge, я не могу обещать вам, что оно не сломается в будущем. выпуск браузера.
Короткий ответ
Учитывая такой HTML, где вы хотите повернуть
.element-to-rotate
...... введите два элемента-оболочки вокруг элемента, который вы хотите повернуть:
... а затем используйте следующий CSS для вращения против часовой стрелки (или посмотрите закомментированный
transform
способ изменить его на вращение по часовой стрелке):Демонстрация фрагмента стека
Показать фрагмент кода
Как это работает?
Замешательство перед заклинаниями, которые я использовал выше, разумно; там много всего происходит, и общая стратегия непростая и требует некоторых знаний в мелочах CSS для понимания. Давайте рассмотрим это шаг за шагом.
Суть проблемы, с которой мы сталкиваемся, заключается в том, что все преобразования, применяемые к элементу с использованием его
transform
свойства CSS, происходят после того, как произошел макет. Другими словами, использованиеtransform
элемента не влияет на размер или положение его родительского элемента или любых других элементов. Нет абсолютно никакого способа изменить этот фактtransform
работы. Таким образом, чтобы создать эффект вращения элемента и чтобы высота его родительского элемента соответствовала повороту, нам необходимо сделать следующее:.element-to-rotate
.element-to-rotate
так, чтобы оно было точно наложено на элемент из шага 1.Элемент из шага 1 должен быть
.rotation-wrapper-outer
. Но как мы можем вызвать его высота будет равна.element-to-rotate
«s ширина ?Ключевым компонентом нашей стратегии здесь является
padding: 50% 0
включение.rotation-wrapper-inner
. Этот эксплойт представляет собой эксцентричную деталь спецификацииpadding
: процентные отступы, даже дляpadding-top
иpadding-bottom
, всегда определяются как проценты от ширины контейнера элемента . Это позволяет нам выполнить следующий двухэтапный трюк:display: table
на.rotation-wrapper-outer
. Это приводит к тому, что он имеет ширину , уменьшающуюся до размера , что означает, что его ширина будет установлена на основе внутренней ширины его содержимого, то есть на основе внутренней ширины.element-to-rotate
. (Что касается поддержки браузеров, мы могли бы добиться этого более четкоwidth: max-content
, но по состоянию на декабрь 2017 годаmax-content
он все еще не поддерживается в Edge .)height
of.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
- обратите внимание, что процентные поля также определяются относительно ширины родительского элемента.И это все!
Почему это не полностью соответствует спецификации?
Из-за следующего примечания из определения процентных отступов и полей в спецификации (выделено жирным шрифтом):
Поскольку весь трюк сводился к тому, чтобы заполнение внутреннего элемента оболочки было относительно ширины его контейнера, который, в свою очередь, зависел от ширины его дочернего элемента, мы выполняем это условие и вызываем поведение undefined. Однако в настоящее время он работает во всех 4 основных браузерах - в отличие от некоторых, казалось бы, совместимых со спецификациями настроек подхода, которые я пробовал, таких как изменение
.rotation-wrapper-inner
на родство,.element-to-rotate
а не на родительский.источник
writing-mode
решения будут наилучший подход , если IE 11 не нуждается в поддержке.Как справедливо указывает комментарий G-Cyr , текущая поддержка
writing-mode
более чем приличная . В сочетании с простым поворотом вы получите именно тот результат, который хотите. См. Пример ниже.источник
writing-mode: vertical-lr; transform: rotate(180deg);
К сожалению (?) Именно так это должно работать, даже если вы поворачиваете свой элемент, он все еще имеет определенную ширину и высоту, которые не меняются после вращения. Вы визуально меняете его, но нет невидимой обертки, которая меняет свой размер при повороте вещей.
Представьте, что вы поворачиваете его менее чем на 90 ° (например
transform: rotate(45deg)
): вам нужно будет ввести такой невидимый прямоугольник, который теперь имеет неоднозначные размеры, основанные на исходных размерах объекта, который вы вращаете, и фактическом значении поворота.Внезапно у вас появляется не только
width
иheight
объекта, который вы повернули, но такжеwidth
иheight
«невидимая рамка» вокруг него. Представьте, что вы запрашиваете внешнюю ширину этого объекта - что он вернет? Ширина объекта или наш новый бокс? Как бы нам провести различие между ними?Следовательно, не существует CSS, который можно было бы написать, чтобы исправить это поведение (или, лучше сказать, «автоматизировать» его). Конечно, вы можете вручную увеличить размер родительского контейнера или написать код JavaScript для этого.
(Для ясности, вы можете попробовать использовать,
element.getBoundingClientRect
чтобы получить прямоугольник, упомянутый ранее).Как описано в спецификации :
Это означает, что никакие изменения не будут внесены в контент, окружающий объект, который вы трансформируете, если вы не сделаете их вручную.
Единственное, что принимается во внимание при трансформации объекта, это область переполнения:
См. Этот jsfiddle, чтобы узнать больше.
На самом деле неплохо сравнить эту ситуацию со смещением объекта, используя:
position: relative
- окружающее содержимое не изменяется, даже если вы перемещаете свой объект ( пример ).Если вы хотите решить эту проблему с помощью JavaScript, взгляните на этот вопрос.
источник
Используйте проценты для
padding
и псевдоэлемент для продвижения содержимого. В JSFiddle я оставил псевдоэлемент красным, чтобы показать его, и вам придется компенсировать сдвиг текста, но я думаю, что это правильный путь.http://jsfiddle.net/MTyFP/7/
Описание этого решения можно найти здесь: http://kizu.ru/en/fun/rotated-text/
источник
Пожалуйста, посмотрите обновленную версию в моем другом ответе . Этот ответ больше не действителен и просто больше не работает. Я оставлю это здесь по историческим причинам.
Этот вопрос довольно старый, но с текущей поддержкой
.getBoundingClientRect()
объекта и егоwidth
иheight
ценность, в сочетании с возможностью использовать этот аккуратный метод вместе сtransform
, я думаю , что мое решение следует упомянуть также.Посмотрите это в действии здесь . (Проверено в Chrome 42, FF 33 и 37.)
getBoundingClientRect
вычисляет фактическую ширину рамки и высоту элемента. Итак, очень просто, мы можем перебрать все элементы и установить его min-height на фактическую высоту блока их дочерних элементов.(С некоторыми изменениями вы можете перебрать дочерние элементы и выяснить, какой из них самый высокий, и установить высоту родительского элемента на самый высокий дочерний элемент. Однако я решил упростить пример. Вы также можете добавить отступ родительского элемента к height, если хотите, или можете использовать соответствующее
box-sizing
значение в CSS.)Однако обратите внимание, что я добавил
translate
иtransform-origin
в ваш CSS, чтобы сделать позиционирование более гибким и точным.источник
Я знаю, что это старый пост, но я нашел его, борясь с той же проблемой. Решение, которое работает для меня, - это довольно грубый "низкотехнологичный" метод, просто окружив div, который я поворачиваю на 90 градусов, большим количеством
Зная приблизительную ширину (которая становится высотой после поворота) div, я могу компенсировать разницу, добавив br вокруг этого div, чтобы содержимое сверху и снизу перемещалось соответственно.
источник