Webdesign 101

Jørgen Farum Jensens webdesign notesblok

  1. Webdesign 101 forside
  2.  » CSS-layout
  3.  » CSS-table layout

CSS-table layout modeller

Efter frigivelsen af Internet Explorer version 8 i foråret 2009 er det attraktivt at overveje at bruge CSS-table egenskaberne til layout.

I denne artikel gennemgår jeg disse egenskaber og demonstrerer, hvorledes de kan bruges til layout af websider.

Et passende sted at begynde er at skabe en smule overblik over de egenskaber, det i grunden handler om:

Oversigt over CSS display-værdier vedr. tabeller
NavnBeskrivelseEksempel
noneTabellen vises ikke 
table Får elementet til at opføre sig som et table-element (table).element {
display:table;}
table-row-groupFår elementet til at opføre sig som et tbody-element.element {display:
table-row-group}
table-row Får elementet til at opføre sig som en tabelrække (tr). element {display:
table-row;}
table-header-group Får elementet til at opføre sig som et thead-element. element {display:
table-header-group;}
table-footer-group Får elementet til at opføre sig som et tfoot-element. element {display:
table-footer-group;}
table-column-groupFår elementet til at opføre sig som et colgroup-element. element {display:
table-column-group;}
table-column Får elementet til at opføre sig som et col-element. element {display:
table-column;}
table-cell Får elementet tilat opføre sig som en tabelcelle (td). element {display:
table-cell}
table-caption Får elementet til at opføre sig som et caption-element. element {display:
table-caption;}

Bemærk at disse egenskaber er CSS2.1 egenskaber, og har været tilgængelige i adskillige år. Samt at browserunderstøttelsen er god – lige med undtagelse af Internet Explorer < version 8. Hvilket naturligvis er forklaringen på, at egenskaberne ikke har været brugt synderlig meget.

Denne artikel omfatter en håndfuld inline eksempler. Hvis du bruger Internet Explorer 7 eller tidligere vil flere af disse inline eksempler ikke blive vist korrekt. En del af formålet med denne artikel og artiklens øvrige eksempler er at få gjort noget ved dette.

Et passende sted at fortsætte denne artikel er med et par eksempler:

Vis/skjul inline eksempel 1.

Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.

Eksemplet herover er skabt af følgende HTML-kode:

<div class="tblex" id="ex1">
  <div id="menuex">
  [ Tekst ]
  </div>
  <div id="indholdex">
  [ Tekst ]
  </div>
</div>

Og stylesheet'et:

.tblex {
  font-family:arial, helvetica, sans-serif;
  font-size:12px;
  display:table;
  width:300px;
  margin:0.4em .1em;}
#ex1 .menuex {
  display:table-cell;
  width:90px;
  padding-right:10px;
  background:#ccc;
  border-right:1px solid black;}
#ex1 .indholdex {
  display:table-cell;
  background:#ccc;
  padding-left:10px;}

Her fristes jeg til at sige som Storm P. sagde om at lære tysk: “Hest hedder Pferd og sådan er det hele vejen igennem”.

Jeg vil nu klappe hesten og forklare en smule mere: Mit minilayout skabes af en div, der har fået egenskaben CSS-egenskaben table. Denne div indeholder to div'er, der hver har fået egenskaben table-cell. Den første af disse har tillige fået en bredde.

Det er nok. Det er alt hvad der skal til. Glem alt om float og clear og højder og bredder. Jeg gentager lige eksemplet med et par formregler mere:

Vis/skjul inline eksempel 2.

Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.

I en håndevending har jeg nu produceret det umulige layout: To lige høje spalter med en border fra top til bund omkring begge spalter. Det er bedøvende ligegyldigt om den ene spalte har mere eller mindre indhold end den anden, begge spalter vil altid være lige høje.

HTML-tabeller vs. CSS-tabeller

Nu hører jeg dig udbryde: “Det er da ingen sag. Det kan jeg sagtens lave mage til med en HTML-tabel med to kolonner.” Og NEJ, det er ikke det samme. Det er ikke mage til.

Bemærk nøje, at i det øjeblik du opretter en tabel på din webside, har du tilføjet din side noget præsentationsformatering. Det er fint nok til tabelopstillinger af sportsresultater, regnskabstal eller oversigter, som min tabel i indledningen til denne artikel. Det er ikke OK at bruge tabelmarkøren til at positionere websidens elementer i forhold til hinanden. Dertil har vi årevis brugt div-markøren.

Klik her for et endnu mere overbevisende argument. Klik igen for at skjule boksen.

Hvis du bruger HTML-tabeller til layout af websiden blander du form og indhold. CSS er netop lavet for at adskille HTML strukturopmærkning fra præsentationsformatering af HTML-elementerne.

Selv om du i praksis er ligeglad med det, vil det betyde at du afskærer fra den store gevinst der er ved at have én CSS-fil til mange sider. Bruger du HTML-tabeller til layout, skal du kopiere dine tabeller ind på alle sider, hvis ellers siderne skal se ens ud.

Det er også ulige mere besværligt at lave et særligt stylesheet til udskrift, og i disse tider måske nok så vigtigt, et særligt stylesheet til mobiltelefoner og PDA'er.

Div-markøren

div-markøren er en semantisk indholdsløs HTML-markør – det vil sige, den har ikke nogen iboende betydning på samme måde som h1-h6, p, li, dt, address osv.

En <div>...</div> er et blokelement, der opretter en rektangulær boks på websiden. Boksens bredde er den samme som det overordnede elements bredde, medmindre du giver elementet en eksplicit bredde. Boksens højde afhænger af indholdets mængde. Boksens indhold kan være et vilkårligt udvalg af de HTML-elementer, du har brug for for at strukturformatere dette indhold.

Er der mere indhold i boksen end der er plads til i forhold til boksens bredde og højde, vil dette indhold som standard flyde nedenud af boksen. Ønsker du at kontrollere dette forhold er det overflow-egenskaben, der skal i spil.

Et div-element indtager den position på websidens, der følger af elementernes almindelige omløb. Dette omløb kan manipuleres ved hjæp af float- og position-egenskaberne

I artiklen Layout med float-egenskaben og eksemplerne til denne finder du en del praktiske anvisninger, der relaterer sig til dette emne.

Anonyme tabelelementer

Et div-element kan imidlertid også påtrykkes en af de egenskaber, der er beskrevet i den indledende oversigt. I de minilayouts, jeg viste ovenfor, var kun benyttet to af disse egenskaber, nemlig display:table for den div, der skal indeholde spalterne, og display:table-cell for de div'er, der udgør spalterne.

For den, der har arbejdet med HTML-tabeller, forekommer dette aldeles utilstrækkeligt. Hvor er <tr>...</tr> blevet af? for blot at nævne én af tabel-markørens indholdsmarkører.

Jeg kan trygt udelade alle de markører jeg ikke har brug for. Ifølge W3C's specifikation skal en browser når den støder på et et element, der har egenskaben table-cell, indsætte såkaldte anonyme tabelelementer, og det vil sige dem, der ret beset mangler for at browseren kan tegne en tabel.

Eksemplet herunder demonstrerer til fulde dette.

Vis/skjul inline eksempel 3.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat

Ut wesi minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.

Ut wesi minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut.

Eksemplets HTML-kode er:

  <div class="col">
 [ Tekst ]
  </div> 
  <div class="col">
  [ Tekst ]
  </div> 
  <div class="col">
  [ Tekst ]
  </div> 
  <div class="col">
  [ Tekst ]
  </div> 

Den operative CSS-kode er den simple:

#ex3 .col {
display:table-cell;
width:21%;
padding:1%;
border:1px solid black;
font-family:arial, helvetica, sans-serif;
font-size:12px;}

Der er ikke nogen simplere metode til at lave to eller flere spalter, der skal se lige høje ud.

Lige høje spalter

Derimod er der en særdeles simpel metode til at få to eller flere spalter til at være lige høje. Det kræver blot at browseren understøtter egenskaberne column-width og column-count.

Vis/skjul inline eksempel 4.

Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.

Ut wesi minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud.

Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.

Det der sker her er, at en browser, der understøtter de to nævnte CSS3-egenskaber, gør sit bedste for at fordele den givne mængde indhold ligeligt på så mange spalter, der er plads til, ud fra værdierne:

  -moz-column-width:100px;
  -moz-column-gap:10px;
  -webkit-column-width:100px;
  -webkit-column-gap:10px;
  column-width:100px;
  column-gap:10px;

Det er jo lækkert og interessant, men også lidt uanvendeligt i en verden hvor Internet Explorer selv i den nyeste version halter bag efter andre browsere.

Det der er interessant i 2009 er at Internet Explorer 8, der udrulles via Windows Update netop mens jeg skriver dette, understøtter CSS table-egenskaberne. Det er derfor nu muligt at layout'e websider efter de samme principper som jeg illustrerede i de første tre inline eksempler. Let's do it!

CSS table-layout

CSS tabellayout eksempel 1 er min foretrukne tospaltede layoutmodel. Det stylesheet, er formaterer siden, har følgende udseende:

#side{
  position: relative;
  width: 760px;
  margin-right: auto;
  margin-left: auto;}
#indhold {
  display: table;
  border-collapse: collapse;}
#nav {
  display: table-cell;
  width: 180px;
  background-color: #939d92;
  vertical-align:top;}
#artikel {
  display: table-cell;
  width: 580px;
  padding-right: 10px;  }

For ikke at komplicere forklaringerne unødigt har jeg

  1. lagt al formatering, der ikke vedrører layout'et, ud i en separat stylesheet fil: common10.css, og
  2. brugt fikserede bredder på elementerne. Det er ret nemt at lægge 180 pixel og 580 pixel sammen og nå frem til at #container-elementet, der omslutter alt indhold på siden, skal være 760 pixel bredt.

Den afgørende forskel på dette layout og et layout med float-mekanismen er, at de to spalter ser ud til at være lige høje. Det skyldes, at jeg har lagt en baggrundsfarve ind under den smalle navigationsspalte. Og da en moderne browser tegner denne spalte som om det er en tabelcelle, vil baggrundsfarven vises under hele højden af denne, indtil #indhold-elementet afsluttes.

Hvad så med Internet Explorer?

Hvis du bruger Internet Explorer 7 eller ældre vil du se, at sidehovedet i CSS tabellayout eksempel 1 tilnærmelsesvis er dækket af en grim gul advarselsboks. Denne browser ene af alle moderne browsere understøtter ikke CSS tabelegenskaberne, hvilket nok er forklaringen på at de ikke har været brugt særlig meget.

Klik her for at vise/skjule en miniudgave af advarselsboksen.

Denne webside ses bedst i en moderne browser, der overholder webstandarderne.

I en Internet Explorer 7 og ældre er alt indhold på websiden synligt og læsbart, men ikke særlig præsentabelt.

Hvis du bruger en sådan browser opfordres du til at installere en nyere version eller en alternativ browser, som for eksempel Firefox.

Denne advarselsboks er sat ind på siden (i slutningen af #side-elementet):

<!--[if lt IE 8]>
    <div id="advarsel">
    [ Advarselsboks tekst ]
    </div>
<![endif]--> 

Som du ser indlæses boksen kun af Internet Explorer med versionsummer mindre end 8. Jeg bruger her Microsofts betingede kommentarer til at sørge for dette. Dem kan du læse mere om i artiklen Microsoft betingede kommentarer.

Det samme gælder det stylesheet, der formaterer den gule boks:

<!--[if lt IE 8]>
  <style type="text/css">
  div#advarsel {
    position:absolute;
    top:10px;
    left:70px;
    display:block;
    width:600px;
    padding: 10px ;
    background-color: #ffcc00;
    border:2px solid black;
    z-index:2;}
  </style>
<![endif]--> 

Med display-værdien none skjules denne boks i alle browsere. Den vises imidlertid i Internet Explorer 7 og tidligere med følgende lille finurlighed:

<!--[if lt IE 8]>
 <style type="text/css">
div#advarsel {display:block;}
 </style>
<![endif]-->

Det vi har her er en Microsoft betinget kommentar, der sørger for, at det lille stylesheet kun læses af Internet Explorer med et versionsnummer mindre end 8. Version 8 af denne browser understøtter nemlig CSS-tabelegenskaberne. Du kan læse mere om de betingede kommentarer i artiklen: Microsoft betingede kommentarer.

Situationen er nu den, at alle browsere viser dette layout korrekt, undtagen version 7 og tidligere af Internet Explorer. Selv i denne browser er alt indhold på siden imidlertid tilgængeligt og læsbart.

Et særligt stylesheet til Internet Explorer 7

Her kunne jeg godt lade tingene hvile og sige, at publikum med ældre IE-browsere bare kunne følge rådet i den gule boks og opgradere eller installere en nyere browser.

Imidlertid kan vi bruge den betingede kommentar til et lidt bedre formål end at vise en advarselsboks. Vi kan for eksempel indsætte et stylesheet, der bruger en gammeldags metode til at layout'e siden, og sørge for at de gamle IE-browsere får dette serveret.

CSS tabellayout eksempel 2 er ganske mage til CSS tabellayout eksempel 1, og hvis du bruger enhver anden browser end Internet Explorer 7 eller tidligere kan du ikke se nogen som helst forskel.

Det kan du derimod netop hvis du bruger IE7 eller IE6. I et sådant tilfælde vil du bemærke at de to kolonnner ser ud til at være lige høje i eksempel 2, hvad de ikke er og ikke ser ud til i eksempel 1.

“Hemmeligheden” bag dette er den betingede kommentar i eksempel 2, der har følgende udseende:

<!--[if lt IE 8]<
<style type="text/css">
#indhold {
  position: relative;
  overflow:hidden; 
  width:100%; /* Aht. IE6 */ }
#nav {float:right;}
#nav ul.menu li {display:inline;}
#artikel { float:left;width:540px;}
#sidefod {clear:both;}
#nav, #artikel {
padding-bottom:1000em;
margin-bottom:-1000em;
}
</style>
<![endif]--< 

Forklaringen til dette er, at vi anvender et konventionelt float-layout i forhold til IE 7 og tidligere:

  1. Alle IE-browsere med et versionsnummer mindre end version 8 indlæser det stylesheet, der er indsat i den betingede kommentar.
  2. Dette stylesheet indlæses efter det normale stylesheet, som jeg gengav ovenfor (stylesheet 1).
  3. Alle værdier, der er deklareret i det første stylesheet, gælder fortsat for alle elementerne.
  4. Det er derfor kun nødvendigt at det stylesheet, der kun læses af IE < 8, omfatter de formregler, der skal gælde for et float-layout. For eksempel har jeg jo én gang sat bredden på #nav-elementet, så det er ikke nødvendigt at gøre det en gang til.
  5. Det er derimod nødvendigt at float'e de to spalter, clear'e sidefoden og bruge padding/margin-tricket for at få de to spalter til at se lige høje ud.

Layout ved hjælp af float-mekanismen har jeg beskrevet i artiklen Layout med float-egenskaben (2007) og senest i artiklen Float-layout med negative marginer (2009).

3-spaltede layouts

Før jeg demonstrerer dette nemme layoutprincip på trespaltede layouts vil jeg lige i eksempel 3 vise, hvor let det er at spejlvende layoutet, så menuspalten kommer til at stå i venstre side.

Eksempel 4 viser det konventionelle trespaltede layout med en smal navigationsspalte til venstre, en bredere midterspalte og en smal spalte til højre til annoncer, resuméer, teasers osv.

Når først du har fat i ideen om brug af CSS-tabelegenskaberne til layout er det så let som at klø sig i nakken at lave det 2-spaltede layout om til et 3-spaltet. Kernen i HTML-koden er den simple:

<div id="nav">
...
</div>
<div id="artikel">
...
</div>
<div id="sidebar">
...
</div>

Og stylesheet'et er i det store og hele som før, blot med en tilføjelse, der formaterer den nye smalle spalte:

div#side {
  position: relative;
  width:95%;
  max-width: 1000px;
  min-width: 760px;
  margin: 0 auto;  }
#indhold {
  display: table;
  border-collapse: collapse; }
#nav {
  display: table-cell;
  width: 200px;
  background-color: #939d92;
  vertical-align:top;}
#sidebar {
  display: table-cell;
  vertical-align:top;
  width:200px;
  background-color: #939d92;
  padding-top:5px;}
#artikel{
  display: table-cell;
  padding-right: 20px;
  padding-left: 20px;
  vertical-align:top;}

Jeg har fremhævet den nye formdeklaration, som er #sidebar.

Bemærk, at jeg har ændret sidebredden fra det fikserede mål, jeg har brugt i de tidligere eksempler. Med tre spalter bliver artikelspalten lidt for smal efter min smag.

Det 3-spaltede layout i IE<8

At formatere det 3-spaltede layout i eksempel 4 så det også tegnes på samme måde i IE6/7 som i IE8 og andre moderne browsere er ikke helt så ligetil som i de to foregående eksempler. De metoder, jeg beskriver i mine tidligere artikler om float-layouts (se boksen i højre spalte) duer ikke rigtigt her. De kræver nemlig at de to smalle spalter skal komme før den brede spalte. Det kan i sagens natur ikke lade sig gøre her.

Den løsning jeg er landet på er at venstre-float'e de to elementer, der kommer først i kildekoden, og højre-float'e den spalte, der kommer til sidst i kildekoden:

<!--[if lt IE 8]>
<style type="text/css">
div#side {width:760px;}
#indhold {
  position: relative;
  overflow:hidden; 
  width:100%; /* Aht. IE6 */ }
#nav {float:left;}
#nav ul.menu li {display:inline;}
#artikel {
  width:340px;
  float:left;
  padding-left:10px;
  padding-right:10px; }
#sidebar {float:right;}
#sidefod {clear:both;}
#nav, #artikel, #sidebar {
padding-bottom:1000em;
margin-bottom:-1000em;
</style>
<![endif]--> 

I stylesheet'et herover, der formaterer sidens elementer til IE6/7, har jeg fremhævet de springende punkter som er:

  1. Når jeg vil left-float'e #artikel-elementet er jeg nødt til at give det en bredde.
  2. For at bredden af #indhold-elementet og de to øvrige hovedelementer, sidehoved og sidefod, kan komme til at stemme overens er jeg også nødt til at vælge en overordnet sidebredde for #side-elementet.

Hvis du kan leve med vandrette rulleskakter hos de få folk, der bruger en 800*600 pixel skærm, vil en overordnet bredde på for eksempel 980 pixel og en bredde af #artikel-elementet på 460 pixel givet et mere harmonisk skærmbillede.

Grundlæggende bryder jeg mig ikke om smal-bred-smal konstruktionen. Jeg foretrækker en 2-spaltet layout med artikel for sig og navigationsspalte for sig.

For nylig er jeg imidlertid blevet inspireret til at “tænke ud af boksen” sommansir. Inspirationskilden har været Kevin Yanks og Rachel Andrews' lille bog, “Everything You Know About CSS Is Wrong” (Sitepoint, nov. 2008).

Bogens titel ufortalt – det passer simpelt hen ikke, uanset hvor meget eller hvor lidt man ved om CSS – har den været inspirationen til dels denne artikel og dels den måde at layout'e på som er anvendt på denne side, og som i øvrigt er denne artikels emne.

3-spaltet smal-smal-bred

Eksempel 5 demonstrerer en udførelse, hvor de to smalle spalter er anbragt til venstre. Tænker du i tabelbaner er det indlysende, at dette kun drejer sig om den orden, hvori spalteelementerne optræder i kildekoden:

<div id="nav">
...
</div>
<div id="sidebar">
...
</div>
<div id="artikel">
...
</div>

I dette eksempel er det IE6/7-specifikke stylesheet lidt nemmere at have med at gøre. Vi kan gribe tilbage til vore erfaringer fra de “almindelige” float-layouts. Disse tilsiger os, at dersom vi left-float'er de to smalle spalter vil de 1) flyde op ved siden af hinanden og 2) #artikel-elementet vil flyde op på højre side af disse, dersom vi afsætter den fornødne plads til venstre for #artikel-elementet:

<!--[if lt IE 8]>
<style type="text/css">
#indhold {
  position: relative;
  overflow:hidden; 
  width:100%; /* Aht. IE6 */ }
#nav {float:left;}
#nav ul.menu li {display:inline;}
#artikel {margin-left:420px;}
#sidebar {float:left;}
#sidefod {clear:both;}
#nav, #artikel, #sidebar {
padding-bottom:1000em;
margin-bottom:-1000em;}
</style>
<![endif]--> 

3-spaltet bred-smal-smal

Som rosinen i pølseenden har jeg eksempel 6, der er en skitse til, hvad jeg har tænkt mig skal være mit fremtidige standardlayout på dette websted. Det er en spejlvending af det foregående eksempel. De få og små ændringer, der skal til i kildekoden, er forklaret i eksemplets artikeldel.

Eksempel 6a er det samme, men med en mindre ændring, således at brødteksten i artikeldelen og teksten i nyhedspalten kommer til at holde poverkant.

Konklusion

Formålet med denne artikel har været at introducere en potentielt revolutionende metode til moderne websidelayout samt at give eksempler på metodens anvendelse.

I betragtning af at der blandt publikum fortsat er en del der anvender Internet Explorer 6 og ikke mindst Internet Explorer 7, anviser jeg også metoder til at præsentere det moderne layout på en sådan måde, at også disse browsere viser et præsentabelt resultat.

Endelig anviser jeg også en metode hvorpå du kan gøre din målgruppe opmærksom på, at dersom de anvender en ukurant version af Internet Explorer bør de måske opdatere deres browser.

Har du kommentarer til denne artikel, modtager jeg dem gerne på den mailadresse, du ser i sidefoden, eller – og bedre – i Usenet webdesign nyhedsgruppen. Er du i tvivl om hvad dette er, kan du læse en artikel om det her: Nyhedsgrupper.

Oprettet: Maj 2009