Kompakte matriser med roterte kolonneoverskrifter

Daniel Eriksson
Systek
Published in
6 min readFeb 28, 2024
Photo by Rob Wicks on Unsplash

Innimellom kommer vi over tabeller (matriser) som har et veldig kortfattet innhold i hver enkeltcelle, samtidig som at rad- og kolonneoverskriftene vil være av noe lenger art.

Matrise med kolonneoverskrifter som er større enn innholdet i cellene

I slike tilfeller hadde det vært fint om kolonneoverskriftene kunne tatt minst mulig plass, slik at cellene ikke blir unødvendig brede. Hva med å rotere dem?

Å rotere noe er enkelt nok med transform: rotate(). Her har jeg valgt å rotere kolonneoverskriftene med 45°. Særlig vakkert blir det dog ikke på første forsøk.

th {
transform: rotate(-45deg);
}
Roterte overskrifter som bare tar marginalt mindre plass i bredden

Første problem vi støter på er at skråstillingen fortsatt krever for mye bredde. Dette kan vi fikse med posisjonering. Vi innfører en indre div og flytter rotasjonen til den.

<th><div class="roter">Ild</div></th>
<th><div class="roter">Vann</div></th>
<th><div class="roter">Gress</div></th>
th {
position: relative;
border: none;
}

.roter {
position: absolute;
bottom: 0;
transform: rotate(-45deg);
border: 1px solid white;
}
Kolonneoverskrifter som flyter oppå tabellen

Fortsatt ser det rart ut. Dette skyldes blant annet at vi har rotert div-ene rundt sitt eget sentrum. Vi ønsker istedet å rotere rundt et av de nedre hjørnene. Dette fikser vi greit med transform-origin.

.roter {
/* Gammelt */
position: absolute;
bottom: 0;
transform: rotate(-45deg);
border: 1px solid white;

/* Nytt */
transform-origin: bottom left;
}
Kolonneoverskrifter som havner for langt til venstre

Da ser vi at hjørnet på div-ene havner for langt til venstre, så vi må flytte dem like mye til høyre som kolonnene er brede (40 piksler).

.roter {
/* Gammelt */
position: absolute;
bottom: 0;
transform: rotate(-45deg);
border: 1px solid white;
transform-origin: bottom left;

/* Nytt */
left: 40px;
}
Kolonneoverskrifter som er for lave

Neste irritasjon er at div-ene er for lave. På øyemål ser vi at de må være lavere enn den opprinnelige cellebredden, men hvor mye?

Du spurte kanskje læreren din om hva pokker vi skal med Pytagoras, og vedkommende svarte sikkert at det skal hjelpe deg med å rotere, posisjonere og velge størrelse på roterte kolonneoverskrifter i kompakte matriser. Det hadde i hvert fall jeg svart, for han skal vi bruke nå!

Kolonnebredden er på 40px.

Pytagoras på sin pureste form er som vi alle husker slik: hosliggende katet² + motstående katet² = hypotenus².

På litt kortere form: a² + b² = c².

Siden katetene er like lange, får vi a² + a² = c² => 2a² = c².

Også kan vi fylle inn for c (kolonnebredden):

Så da ender vi til slutt opp med:

2a² = 1600
=> a² = 800
=> a = √800
=> a ≈ 28,28

Alternativ (og bedre?) trigonometrisk løsning:

sin(α) = motstående katet ÷ hypotenus // α angitt i radianer, og 45° = π/4 radianer
=> sin(π ÷ 4) = motstående katet ÷ hypotenus
=> sin(π ÷ 4) = motstående katet ÷ 40
=> motstående katet = sin(π ÷ 4) × 40
=> motstående katet ≈ 28,28
.roter {
/* Gammelt */
position: absolute;
bottom: 0;
transform: rotate(-45deg);
border: 1px solid white;
transform-origin: bottom left;
left: 40px;

/* Nytt */
height: 28.28
}
Kolonneoverskrifter som er høye nok!

Men hva om vi har rotert med noe annet enn 45°, sier du? La oss si at vi istedet ønsker å rotere med 33°. Vi gjenbruker den alternative trigonometriske løsningen.

33° = 2π × (33 ÷ 360) radianer

sin(2π × 33 ÷ 360) = høyde ÷ 40
=> sin(2π × 33 ÷ 360) × 40 = høyde
=> høyde ≈ 21,79
.roter {
/* Gammelt */
position: absolute;
bottom: 0;
border: 1px solid white;
transform-origin: bottom left;
left: 40px;

/* Nytt */
transform: rotate(-33deg);
height: 21.79
}
33° roterte kolonneoverskrifter med riktig høyde!

Men tilbake til 45°-løsningen.

Så hadde det jo vært fryktelig fint om det ikke var et “åpent hakk” mellom linjene til tbody-en og linjene til overskriftene. Vi trenger å strekke dem ut på et eller annet vis. Hva med transform: skew()?

Vi innfører en ny div, hvis oppgave er å tegne et parallellogram rundt de roterte overskriftene.

Dette medfører dessverre at vi mister muligheten til å ha dynamisk størrelse på overskriftene, så vi hardkorder dette til 60 piksler (inntil videre).

.roter {
/* Gammelt */
position: absolute;
bottom: 0;
transform: rotate(-45deg);
transform-origin: bottom left;
left: 40px;

/* Fjernet */
/* height: 28.29px; */
/* border: 1px solid white; */

/* Nytt */
border: none;
}
.skew {
transform-origin: bottom left;
transform: skew(-45deg);
border: 1px solid white;
width: 40px;
bottom: 0;
height: 60px;
}
Pene skråstilte rammer på kolonneoverskriftene, men med forvrengt innhold

Vi ser nå at tekstene er både forvrengt og overrotert. Dette skyldes at vi også har skew-et innholdet i roter-div-en, noe som ikke er ønskelig. Vi legger derfor inn en "anti"-skew i den indre roterte div-en.

.roter {
/* Gammelt */
position: absolute;
bottom: 0;
transform-origin: bottom left;
left: 40px;
border: none;

/* Nytt */
transform: skew(45deg) rotate(-45deg);
}
Pene og roterte kolonneoverskrifter!

Så har vi som nevnt juksa litt ved å sette en fast høyde på div-en medskew. Hva skjer om vi fjerner dette igjen?

.skew {
/* Gammelt */
transform-origin: bottom left;
transform: skew(-45deg);
border: 1px solid white;
width: 40px;

/* Nytt */
height: auto;
border: 1px solid red;
}
Kolonneoverskrifter som blir flytende oppå en rød strek

Da blir skew-høyden 0, og her er det slutt på de gode løsningene. Hvis man ikke har ønske om eller mulighet til å benytte fast høyde, kan dette løses med JavaScript.

const roterteDiver = document.querySelectorAll('.roter');
const bredder = [...roterteDiver].map(({ offsetWidth }) => offsetWidth);
const høyde = Math.max(...bredder);

document.querySelectorAll('.skew').forEach(({ style }) => {
style.height = høyde + 'px';
});
Pene og roterte kolonneoverskrifter med dynamisk høyde

Og hvis du synes dette ble for ille og har gitt opp alt håpet for 45° roterte overskrifter, så kan jeg forsøke å trøste deg med at det finnes en noe enklere °.-løsning.

thead th {
writing-mode: vertical-lr;
/* writing-mode: sideways-lr; */ /* Finest, men foreløpig kun støttet i Firefox */
}
90° roterte kolonneoverskrifter som går fra topp til bunn
writing-mode: vertical-lr
90° roterte kolonneoverskrifter som går fra bunn til topp
writing-mode: sideways-lr

Håper dette var nyttig lesing og læring!

Er du nysgjerrig på hvilke muligheter vi har for deg i Systek, sjekk gjerne ut våre tjenester og ledige stillinger på https://systek.no/.

--

--