Powiedzmy, że mam kilka kolumn, z których niektóre chciałbym obracać wartościami:
<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>
Z tym CSS:
.statusColumn b {
writing-mode: tb-rl;
white-space: nowrap;
display: inline-block;
overflow: visible;
transform: rotate(-90deg);
transform-origin: 50% 50%;
}
Kończy się tak:
Czy można napisać dowolny CSS, który spowoduje, że obrócony element wpłynie na wysokość swojego rodzica, tak że tekst nie będzie zachodził na inne elementy? Coś takiego:
css
css-transforms
Chris
źródło
źródło
writing-mode
jest dostępny dla większości przeglądarek, ale ma straszne błędy. Wracając do pokrewnego pytania, przeszedłem przez wiele iteracji, próbując obejść błędy specyficzne dla przeglądarki, zanim się poddałem; możesz zobaczyć moją serię niepowodzeń na stackoverflow.com/posts/47857248/revisions , gdzie zaczynam od czegoś, co działa w Chrome, ale nie w Firefoksie lub Edge, a następnie psuję Chrome w trakcie naprawiania pozostałych dwóch i kończę na odwróceniu mojego odpowiedzieć i oznaczyć go jako tylko Chrome. Bądź ostrożny, jeśli chcesz iść tą ścieżką. (Zauważ również, że nie ma to sensu w przypadku elementów nietekstowych.)Odpowiedzi:
Zakładając, że chcesz obrócić o 90 stopni, jest to możliwe, nawet w przypadku elementów nietekstowych - ale podobnie jak wiele interesujących rzeczy w CSS wymaga odrobiny sprytu. Moje rozwiązanie również technicznie wywołuje niezdefiniowane zachowanie zgodnie ze specyfikacją CSS 2 - więc chociaż przetestowałem i potwierdziłem, że działa w Chrome, Firefox, Safari i Edge, nie mogę obiecać, że nie zepsuje się w przyszłości wydanie przeglądarki.
Krótka odpowiedź
Biorąc pod uwagę taki kod HTML, w którym chcesz obrócić
.element-to-rotate
...... wprowadź dwa elementy opakowujące wokół elementu, który chcesz obrócić:
... a następnie użyj poniższego CSS, aby obrócić w lewo (lub zobacz komentarz w komentarzu,
transform
aby dowiedzieć się, jak zmienić go na obrót w prawo):Demo fragmentu stosu
Pokaż fragment kodu
Jak to działa?
Zamieszanie w obliczu zaklęć, których użyłem powyżej, jest uzasadnione; dużo się dzieje, a ogólna strategia nie jest prosta i wymaga znajomości zagadnień CSS, aby ją zrozumieć. Przejdźmy przez to krok po kroku.
Sedno problemu polega na tym, że transformacje zastosowane do elementu za pomocą jego
transform
właściwości CSS następują po utworzeniu układu. Innymi słowy, użycietransform
na elemencie w ogóle nie wpływa na rozmiar ani położenie jego rodzica ani żadnych innych elementów. Nie ma absolutnie żadnego sposobu, aby zmienić ten fakt, jaktransform
działa. Tak więc, aby stworzyć efekt obracania elementu i uwzględnienia jego wysokości nadrzędnej względem obrotu, musimy wykonać następujące czynności:.element-to-rotate
.element-to-rotate
tak, aby nałożyć ją dokładnie na element z kroku 1.Elementem z kroku 1 będzie
.rotation-wrapper-outer
. Ale jak możemy spowodować jego wysokość była równa.element-to-rotate
jest szerokości ?Kluczowym elementem naszej strategii jest tu
padding: 50% 0
na.rotation-wrapper-inner
. Ten exploit jest ekscentrycznym szczegółem specyfikacjipadding
: że procent wypełnienia, nawet dlapadding-top
ipadding-bottom
, jest zawsze definiowany jako procent szerokości kontenera elementu . Dzięki temu możemy wykonać następującą dwuetapową sztuczkę:display: table
na.rotation-wrapper-outer
. Powoduje to, że ma szerokość zmniejszania, aby dopasować , co oznacza, że jego szerokość zostanie ustawiona na podstawie wewnętrznej szerokości jego zawartości - to znaczy na podstawie wewnętrznej szerokości.element-to-rotate
. (Na wsparcie przeglądarek, możemy osiągnąć więcej z czystowidth: max-content
, ale w grudniu 2017 roku,max-content
jest nadal nie jest obsługiwana w Krawędzi ).height
of.rotation-wrapper-inner
na 0, a następnie ustawiamy jego dopełnienie na50% 0
(czyli 50% na górze i 50% na dole). To powoduje, że zajmuje on w pionie przestrzeń równą 100% szerokości swojego rodzica - która, poprzez sztuczkę z kroku 1, jest równa szerokości.element-to-rotate
.Następnie pozostaje tylko wykonać faktyczny obrót i pozycjonowanie elementu potomnego. Oczywiście,
transform: rotate(-90deg)
czy rotacja; używamytransform-origin: top left;
do wywoływania obrotu wokół lewego górnego rogu obracanego elementu, co sprawia, że późniejsze tłumaczenie jest łatwiejsze do rozważenia, ponieważ pozostawia on obrócony element bezpośrednio nad miejscem, w którym zostałby narysowany. Następnie możemytranslate(-100%)
przeciągnąć element w dół o odległość równą szerokości przed obróceniem.To wciąż nie do końca zapewnia prawidłowe pozycjonowanie, ponieważ nadal musimy przesunąć 50% górnego dopełnienia
.rotation-wrapper-outer
. Osiągamy to, upewniając się, że.element-to-rotate
madisplay: block
(aby marginesy działały poprawnie), a następnie stosując -50%margin-top
- zwróć uwagę, że marginesy procentowe są również definiowane w stosunku do szerokości elementu nadrzędnego.I to wszystko!
Dlaczego nie jest to w pełni zgodne ze specyfikacjami?
Ze względu na następującą uwagę z definicji procentowych wypełnień i marginesów w specyfikacji (moje pogrubienie):
Ponieważ cała sztuczka polegała na tym, aby wypełnienie wewnętrznego elementu opakowania było zależne od szerokości jego pojemnika, co z kolei zależało od szerokości jego elementu potomnego, trafiamy w ten warunek i wywołujemy niezdefiniowane zachowanie. Obecnie działa jednak we wszystkich 4 głównych przeglądarkach - w przeciwieństwie do niektórych pozornie zgodnych ze specyfikacją poprawek, które próbowałem, takich jak zmiana
.rotation-wrapper-inner
na rodzeństwo.element-to-rotate
zamiast rodzica.źródło
writing-mode
rozwiązania będą najlepsze podejście, jeśli IE 11 nie muszą być obsługiwane.Jak słusznie zwraca uwagę G-Cyr , obecne poparcie
writing-mode
jest więcej niż przyzwoite . W połączeniu z prostym obróceniem uzyskasz dokładnie taki wynik, jaki chcesz. Zobacz poniższy przykład.źródło
writing-mode: vertical-lr; transform: rotate(180deg);
Niestety (?) Tak to ma działać, mimo że obrócisz element, który nadal ma określoną szerokość i wysokość, która nie zmienia się po obróceniu. Zmieniasz to wizualnie, ale nie ma niewidocznego pudełka do pakowania, które zmienia swój rozmiar, gdy obracasz rzeczy.
Wyobraź sobie, że obracasz go o mniej niż 90 ° (np.
transform: rotate(45deg)
): Musiałbyś wprowadzić takie niewidoczne pudełko, które ma teraz niejednoznaczne wymiary w oparciu o oryginalne wymiary obracanego obiektu i rzeczywistą wartość obrotu.Nagle, nie masz tylko
width
iheight
obiektu zostały obrócone, ale mieć równieżwidth
iheight
z „niewidzialnym polu” wokół niego. Wyobraź sobie, że żądasz zewnętrznej szerokości tego obiektu - co by to zwróciło? Szerokość obiektu czy nasze nowe pudełko? Jak rozróżnilibyśmy oba?Dlatego nie istnieje CSS, który można by napisać, aby naprawić to zachowanie (a raczej „zautomatyzować” to). Oczywiście możesz ręcznie zwiększyć rozmiar swojego kontenera nadrzędnego lub napisać JavaScript, aby to obsłużyć.
(Dla jasności możesz spróbować użyć,
element.getBoundingClientRect
aby uzyskać wspomniany wcześniej prostokąt).Jak opisano w specyfikacji :
Oznacza to, że nie zostaną wprowadzone żadne zmiany w zawartości otaczającej obiekt, który przekształcasz, chyba że zrobisz to ręcznie.
Jedyną rzeczą, która jest brana pod uwagę podczas przekształcania obiektu, jest obszar przepełnienia:
Zobacz to jsfiddle, aby dowiedzieć się więcej.
Właściwie całkiem dobrze jest porównać tę sytuację z przesunięciem obiektu za pomocą:
position: relative
- otaczająca zawartość nie zmienia się, nawet jeśli poruszasz obiektem ( przykład ).Jeśli chcesz sobie z tym poradzić za pomocą JavaScript, spójrz na to pytanie.
źródło
Użyj wartości procentowych dla
padding
i pseudoelementu, aby przekazać zawartość. W JSFiddle zostawiłem pseudoelement czerwony, aby go pokazać i będziesz musiał skompensować przesunięcie tekstu, ale myślę, że to jest droga.http://jsfiddle.net/MTyFP/7/
Opis tego rozwiązania można znaleźć tutaj: http://kizu.ru/en/fun/rotated-text/
źródło
Proszę zobaczyć zaktualizowaną wersję w mojej drugiej odpowiedzi . Ta odpowiedź jest już nieaktualna i po prostu nie działa. Zostawię to tutaj z powodów historycznych.
To pytanie jest dość stary, ale z bieżącego wsparcia dla
.getBoundingClientRect()
obiektu i jegowidth
andheight
wartości, w połączeniu z możliwością wykorzystania tej metody wraz z schludnytransform
, myślę, że moje rozwiązanie należy wspomnieć również.Zobacz to w akcji tutaj . (Testowane w Chrome 42, FF 33 i 37.)
getBoundingClientRect
oblicza rzeczywistą szerokość i wysokość pudełka elementu. Po prostu możemy więc przejść przez wszystkie elementy i ustawić jego minimalną wysokość na rzeczywistą wysokość pudełka ich dzieci.(Z pewnymi modyfikacjami możesz przeglądać dzieci i dowiedzieć się, który z nich jest najwyższy, i ustawić wzrost rodzica dla najwyższego dziecka. Postanowiłem jednak uczynić przykład prostszym. Możesz również dodać wypełnienie rodzica do wysokość, jeśli chcesz, lub możesz użyć odpowiedniej
box-sizing
wartości w CSS).Zwróć jednak uwagę, że dodałem
translate
itransform-origin
do twojego CSS, aby pozycjonowanie było bardziej elastyczne i dokładne.źródło
Wiem, że to stary post, ale znalazłem go, borykając się z dokładnie tym samym problemem. Rozwiązanie, które mi odpowiada, to raczej prymitywna metoda „low-tech” polegająca na umieszczeniu znacznika div, który obracam o 90 stopni,
Znając przybliżoną szerokość (która staje się wysokością po obróceniu) elementu div, mogę skompensować różnicę, dodając br's wokół tego elementu div, dzięki czemu zawartość powyżej i poniżej zostanie odpowiednio przesunięta.
źródło