Digamos que eu tenha algumas colunas, das quais gostaria de girar os valores de:
<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>
Com este CSS:
.statusColumn b {
writing-mode: tb-rl;
white-space: nowrap;
display: inline-block;
overflow: visible;
transform: rotate(-90deg);
transform-origin: 50% 50%;
}
Acaba ficando assim:
É possível escrever qualquer CSS que fará com que o elemento girado afete a altura de seu pai, de modo que o texto não se sobreponha aos outros elementos? Algo assim:
css
css-transforms
Chris
fonte
fonte
writing-mode
está disponível para a maioria dos navegadores, mas tem muitos erros. Sobre uma questão relacionada, passei por várias iterações tentando contornar bugs específicos do navegador antes de desistir; você pode ver minha sucessão de falhas em stackoverflow.com/posts/47857248/revisions , onde começo com algo que funciona no Chrome, mas não no Firefox ou Edge, em seguida, interrompo o Chrome no processo de consertar os outros dois e acabo revertendo meu responder e rotulá-lo como apenas Chrome. Seja cauteloso, se você quiser seguir este caminho. (Observe também que não é útil com elementos não textuais.)Respostas:
Supondo que você queira girar 90 graus, isso é possível, mesmo para elementos que não sejam de texto - mas, como muitas coisas interessantes em CSS, isso requer um pouco de astúcia. Minha solução também invoca tecnicamente o comportamento indefinido de acordo com as especificações CSS 2 - então, embora eu tenha testado e confirmado que funciona no Chrome, Firefox, Safari e Edge, não posso prometer que não vai quebrar no futuro versão do navegador.
Resposta curta
Dado um HTML como este, onde você deseja girar
.element-to-rotate
...... introduza dois elementos wrapper em torno do elemento que você deseja girar:
... e, em seguida, use o seguinte CSS para girar no sentido anti-horário (ou veja o comentado
transform
para ver uma maneira de mudar para a rotação no sentido horário):Demonstração de snippet de pilha
Exibir trecho de código
Como é que isso funciona?
A confusão diante dos encantamentos que usei acima é razoável; há muita coisa acontecendo e a estratégia geral não é direta e requer algum conhecimento de trivialidades de CSS para ser entendida. Vamos examinar isso passo a passo.
O cerne do problema que enfrentamos é que as transformações aplicadas a um elemento usando sua
transform
propriedade CSS acontecem após o layout ter ocorrido. Em outras palavras, usartransform
em um elemento não afeta o tamanho ou a posição de seu pai ou de quaisquer outros elementos. Não há absolutamente nenhuma maneira de mudar esse fato de comotransform
funciona. Assim, para criar o efeito de girar um elemento e fazer com que a altura de seu pai respeite a rotação, precisamos fazer o seguinte:.element-to-rotate
.element-to-rotate
modo a sobrepor exatamente no elemento da etapa 1.O elemento da etapa 1 deve ser
.rotation-wrapper-outer
. Mas como podemos fazer com que a sua altura para ser igual ao.element-to-rotate
de largura ?O principal componente de nossa estratégia aqui é o
padding: 50% 0
on.rotation-wrapper-inner
. Este exploit é um detalhe excêntrico da especificação parapadding
: os preenchimentos de porcentagem, mesmo parapadding-top
epadding-bottom
, são sempre definidos como porcentagens da largura do contêiner do elemento . Isso nos permite realizar o seguinte truque de duas etapas:display: table
em.rotation-wrapper-outer
. Isso faz com que ele tenha uma largura reduzida para caber , o que significa que sua largura será definida com base na largura intrínseca de seu conteúdo - ou seja, com base na largura intrínseca de.element-to-rotate
. (On suporte a navegadores, podemos conseguir isso de forma mais limpa comwidth: max-content
, mas a partir de Dezembro de 2017,max-content
é ainda não é suportado em Borda .)height
de.rotation-wrapper-inner
como 0 e, em seguida, definimos seu preenchimento como50% 0
(ou seja, 50% superior e 50% inferior). Isso faz com que ele ocupe um espaço vertical igual a 100% da largura de seu pai - que, por meio do truque da etapa 1, é igual à largura de.element-to-rotate
.Em seguida, tudo o que resta é executar a rotação e o posicionamento reais do elemento filho. Naturalmente,
transform: rotate(-90deg)
faz a rotação; usamostransform-origin: top left;
para fazer com que a rotação aconteça ao redor do canto superior esquerdo do elemento girado, o que torna a translação subsequente mais fácil de raciocinar, uma vez que deixa o elemento girado diretamente acima de onde, de outra forma, teria sido desenhado. Podemos então usartranslate(-100%)
para arrastar o elemento para baixo por uma distância igual à largura de pré-rotação.Isso ainda não acertou o posicionamento, porque ainda precisamos compensar para o preenchimento superior de 50% ativado
.rotation-wrapper-outer
. Conseguimos isso garantindo que.element-to-rotate
tenhadisplay: block
(para que as margens funcionem corretamente nele) e, em seguida, aplicando um -50%margin-top
- observe que as margens de porcentagem também são definidas em relação à largura do elemento pai.E é isso!
Por que isso não é totalmente compatível com as especificações?
Por causa da seguinte nota da definição de preenchimentos percentuais e margens na especificação (negrito):
Como todo o truque girava em torno de fazer o preenchimento do elemento de invólucro interno ser relativo à largura de seu contêiner que, por sua vez, dependia da largura de seu filho, estamos atingindo essa condição e invocando um comportamento indefinido. No momento, ele funciona em todos os quatro navegadores principais - ao contrário de alguns ajustes aparentemente compatíveis com as especificações para abordar que tentei, como mudar
.rotation-wrapper-inner
para ser irmão em.element-to-rotate
vez de pai.fonte
writing-mode
soluções serão a melhor abordagem se o IE 11 não precisar de suporte.Como o comentário de G-Cyr corretamente aponta, o suporte atual para
writing-mode
é mais do que decente . Combinado com uma rotação simples, você obtém o resultado exato que deseja. Veja o exemplo abaixo.fonte
writing-mode: vertical-lr; transform: rotate(180deg);
Infelizmente (?) É assim que deve funcionar, embora você gire seu elemento, ele ainda tem uma certa largura e altura, que não muda após a rotação. Você o altera visualmente, mas não há nenhuma caixa de embalagem invisível que muda seu tamanho quando você gira as coisas.
Imagine girá-lo menos de 90 ° (por exemplo
transform: rotate(45deg)
): você teria que introduzir essa caixa invisível que agora tem dimensões ambíguas com base nas dimensões originais do objeto que você está girando e no valor de rotação real.De repente, você não tem apenas o
width
eheight
do objeto que girou, mas também owidth
eheight
da "caixa invisível" ao seu redor. Imagine solicitar a largura externa desse objeto - o que ele retornaria? A largura do objeto ou nossa nova caixa? Como poderíamos distinguir entre os dois?Portanto, não há CSS que você possa escrever para corrigir esse comportamento (ou devo dizer, "automatize-o"). É claro que você pode aumentar o tamanho do seu container pai manualmente ou escrever algum JavaScript para lidar com isso.
(Só para ficar claro, você pode tentar usar
element.getBoundingClientRect
para obter o retângulo mencionado antes).Conforme descrito nas especificações :
Isso significa que nenhuma alteração será feita no conteúdo ao redor do objeto que você está transformando, a menos que você as faça manualmente.
A única coisa que é levada em consideração quando você transforma seu objeto é a área de estouro:
Veja este jsfiddle para saber mais.
Na verdade, é muito bom comparar esta situação a um deslocamento de objeto usando:
position: relative
- o conteúdo ao redor não muda, mesmo que você esteja movendo seu objeto ( exemplo ).Se você quiser lidar com isso usando JavaScript, dê uma olhada nesta questão.
fonte
Use porcentagens para
padding
e um pseudoelemento para enviar o conteúdo. No JSFiddle deixei o pseudo elemento vermelho para mostrá-lo e você terá que compensar o deslocamento do texto, mas acho que é o caminho a percorrer.http://jsfiddle.net/MTyFP/7/
Uma descrição desta solução pode ser encontrada aqui: http://kizu.ru/en/fun/rotated-text/
fonte
Por favor, veja a versão atualizada em minha outra resposta . Esta resposta não é mais válida e simplesmente não funciona mais. Vou deixar aqui por motivos históricos.
Esta questão é bastante antiga, mas com o suporte atual para o
.getBoundingClientRect()
objeto e suaswidth
eheight
valores, em combinação com a capacidade de usar este método puro juntamente comtransform
, eu acho que a minha solução deve ser mencionado também.Veja em ação aqui . (Testado no Chrome 42, FF 33 e 37.)
getBoundingClientRect
calcula a caixa real largura e a altura do elemento. Muito simplesmente, então, podemos percorrer todos os elementos e definir sua altura mínima para a altura real da caixa de seus filhos.(Com algumas modificações, você pode percorrer os filhos e descobrir qual é o mais alto e definir a altura do pai para o filho mais alto. No entanto, decidi tornar o exemplo mais direto. Você também pode adicionar preenchimento do pai ao altura se quiser, ou você pode usar um
box-sizing
valor relevante em CSS.)Observe, porém, que adicionei um
translate
etransform-origin
ao seu CSS para tornar o posicionamento mais flexível e preciso.fonte
Eu sei que é um post antigo, mas eu o encontrei enquanto lutava exatamente com o mesmo problema. A solução que funciona para mim é um método "de baixa tecnologia" bastante rudimentar, simplesmente circundando a div que giro em 90 graus com muitos
Sabendo a largura aproximada (que se torna altura após a rotação) de div, posso compensar a diferença adicionando br's ao redor desse div para que o conteúdo acima e abaixo seja empurrado de acordo.
fonte