Dengan asumsi Anda ingin memutar 90 derajat, hal ini dimungkinkan, bahkan untuk elemen non-teks - tetapi seperti banyak hal menarik lainnya di CSS, ini membutuhkan sedikit kecerdikan. Solusi saya juga secara teknis memanggil perilaku tidak terdefinisi sesuai dengan spesifikasi CSS 2 - jadi sementara saya telah menguji dan mengonfirmasi bahwa ini berfungsi di Chrome, Firefox, Safari, dan Edge, saya tidak dapat menjanjikan kepada Anda bahwa itu tidak akan rusak di masa mendatang rilis browser.
Jawaban singkat
Diberikan HTML seperti ini, dimana Anda ingin merotasi .element-to-rotate
...
<div id="container">
<something class="element-to-rotate">bla bla bla</something>
</div>
... perkenalkan dua elemen pembungkus di sekitar elemen yang ingin Anda putar:
<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>
... lalu gunakan CSS berikut, untuk memutar berlawanan arah jarum jam (atau lihat komentar transform
untuk cara mengubahnya menjadi rotasi searah jarum jam):
.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;
}
Demo cuplikan tumpukan
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>
Bagaimana cara kerjanya?
Kebingungan dalam menghadapi mantra yang saya gunakan di atas adalah wajar; ada banyak hal yang terjadi, dan keseluruhan strategi tidak langsung dan membutuhkan pengetahuan tentang CSS trivia untuk memahaminya. Mari kita bahas langkah demi langkah.
Inti dari masalah yang kita hadapi adalah bahwa transformasi yang diterapkan ke elemen menggunakan transform
properti CSS -nya semuanya terjadi setelah tata letak dilakukan. Dengan kata lain, penggunaan transform
pada elemen sama sekali tidak mempengaruhi ukuran atau posisi induknya atau elemen lainnya. Sama sekali tidak ada cara untuk mengubah fakta tentang cara transform
kerja ini. Jadi, untuk membuat efek memutar elemen dan tinggi induknya mengikuti rotasi, kita perlu melakukan hal-hal berikut:
- Entah bagaimana membangun beberapa elemen lain yang tingginya sama dengan lebar
.element-to-rotate
- Tuliskan transformasi kita
.element-to-rotate
seperti untuk melapisinya persis pada elemen dari langkah 1.
Elemen dari langkah 1 harus .rotation-wrapper-outer
. Tapi bagaimana kita bisa menyebabkan nya tinggi untuk menjadi sama dengan .element-to-rotate
's lebar ?
Komponen kunci dalam strategi kami di sini adalah padding: 50% 0
aktif .rotation-wrapper-inner
. Eksploitasi ini adalah detail eksentrik dari spesifikasi untukpadding
: padding persentase itu, bahkan untuk padding-top
dan padding-bottom
, selalu ditentukan sebagai persentase lebar wadah elemen . Ini memungkinkan kami untuk melakukan trik dua langkah berikut:
- Kami menetapkan
display: table
pada .rotation-wrapper-outer
. Ini menyebabkannya memiliki lebar menyusut agar pas , yang berarti lebarnya akan diatur berdasarkan lebar intrinsik isinya - yaitu, berdasarkan lebar intrinsik .element-to-rotate
. (Pada mendukung browser, kita bisa mencapai hal ini lebih bersih dengan width: max-content
, tetapi sebagai Desember 2017, max-content
yang masih belum didukung di Ujung .)
- Kami mengatur
height
of .rotation-wrapper-inner
ke 0, lalu mengatur paddingnya ke 50% 0
(yaitu, 50% atas dan 50% bawah). Ini menyebabkannya mengambil ruang vertikal sama dengan 100% lebar induknya - yang, melalui trik di langkah 1, sama dengan lebarnya .element-to-rotate
.
Selanjutnya, yang tersisa hanyalah melakukan rotasi dan pemosisian elemen turunan yang sebenarnya. Secara alami, transform: rotate(-90deg)
melakukan rotasi; kita gunakan transform-origin: top left;
untuk menyebabkan rotasi terjadi di sekitar sudut kiri atas elemen yang diputar, yang membuat terjemahan selanjutnya lebih mudah untuk dipikirkan, karena ia meninggalkan elemen yang diputar tepat di atas tempat yang seharusnya digambar. Kita kemudian dapat menggunakan translate(-100%)
untuk menyeret elemen ke bawah dengan jarak yang sama dengan lebar pra-rotasinya.
Itu masih belum mendapatkan posisi yang benar, karena kita masih perlu mengimbangi untuk 50% padding atas .rotation-wrapper-outer
. Kami mencapai itu dengan memastikan bahwa .element-to-rotate
has display: block
(sehingga margin akan bekerja dengan baik di atasnya) dan kemudian menerapkan -50% margin-top
- perhatikan bahwa persentase margin juga ditentukan relatif terhadap lebar elemen induk.
Dan itu dia!
Mengapa ini tidak sepenuhnya sesuai dengan spesifikasi?
Karena berikut catatan dari definisi persentase paddings dan margin di spec (bolding mine):
Persentase dihitung sehubungan dengan lebar blok berisi kotak yang dihasilkan , bahkan untuk 'padding-top' dan 'padding-bottom' . Jika lebar blok penampung bergantung pada elemen ini, maka tata letak yang dihasilkan tidak ditentukan di CSS 2.1.
Karena seluruh trik berputar di sekitar membuat bantalan elemen pembungkus bagian dalam menjadi relatif terhadap lebar wadahnya yang pada gilirannya bergantung pada lebar anaknya, kami mencapai kondisi ini dan menjalankan perilaku yang tidak ditentukan. Saat ini bekerja di semua 4 browser utama, meskipun - tidak seperti beberapa tweak yang tampaknya sesuai dengan spesifikasi untuk pendekatan yang saya coba, seperti mengubah .rotation-wrapper-inner
menjadi saudara kandung .element-to-rotate
alih-alih orang tua.