Webside layout med float-egenskaben

Introduktion til layout med float.
Éns højde på to eller flere kolonner

Det mest populære princip for layout af webside ved hjælp af CSS er brugen af absolut position af et eller flere elementer på websiden.

Et absolut positioneret element udgør et lag over den egentlige side, det vil sige at det pågældende element så at sige fjernes fra websidens normale omløb. De øvrige elementer opfører sig som det absolut positionerede element overhovedet ikke findes på siden, medmindre vi på anden måde sørger for, at der ikke er noget andet indhold dér, hvor vi placerer det absolut positionerede element. Det er det, vi gør ved hjælp af margin egenskaben, som beskrevet i detaljer i artiklen Noter om websidelayout. Eller ved hjælp af border-egenskaben, som beskrevet den nævnte artikels eksempel 7.

Den praktiske konsekvens af dette er som regel, at vi har umådelig vanskeligt ved at styre højder på vore websider. Ethvert elements størrelse, uanset om det er positioneret eller ej, styres af dets indhold. Da vi ikke på forhånd ved hvor meget tekst, der for eksempel er på en webside, eller hvilken skrift og skriftstørrelse, den vises med i brugerens browser, kan vi nok fifle noget med bredder, men højden er en helt anden sag.

Vi kan naturligvis sætte både en bredde og højde på et vilkårligt element, men for så vidt angår brødtekst kan det medføre meget kedelige resultater. Hvis du gør det, skal du i hvert fald være bekendt med overflow-egenskaben – se artiklen Autocentrering.

Alternativet til position-egenskaben er float-egenskaben. Også denne egenskab fjerner det float'ede element fra sidens normale omløb, men det float'ede element lægger sig ikke over sidens øvrige HTML-elementer, men skubber elementernes indhold til højre elller venstre for det float'ede element.

float-egenskaben kan være en vanskelig en at danse med, fordi det float'ede element ofte opfører sig på en måde, der ikke stemmer overens med vores intution.

Ikke desto mindre er det muligt med denne egenskab at opnå nogle layouts, der ikke er mulige eller i hvert fald overordentligt vanskelige at realisere på anden måde.

Den almindelige brug af float-egenskaben

Nyhedsboks

Dette er et eksempel på et element, der er indsat i brødteksten ved hjælp af float-egenskaben.

I moderne webdesign er det float-egenskaben, vi anvender til at positionere billeder, tabeller og andet materiale inde i en brødtekst, jf. for eksempel min lille nyhedsboks her til højre.

Stylesheet'et for kassen ser ud som vist herunder:

.nybox {
  float:right;
  width:200px;
  border:1px solid maroon;
  font-family:arial,sans-serif;
  margin:0 0 0.5em 0.5em;}
.nybox h3 {
  color:white;
  background:maroon;
  padding:2px 5px;
  margin:0;}
.nybox p {
  margin:0;
  padding:2px 5px;}

Layout med float

Vi starter i det små med et standardlayout med to kolonner, et sidehoved og en sidefod: eksempel 1. Html-kildekoden til denne side er følgende:

<div id="page">
  <div id="banner">
  <h2>Sidehoved</h2>
  </div>
  <div id="leftcol">
  [ Menu ]
  </div>
  <div id="rightcol">
  [ Artikeltekst ]
  </div>
  <div id="footer">
  <h2>Sidefod</h2>
  </div>
</div>

– altså et ganske normalt sidelayout med 4 elementer (sidehoved, sidefod, en venstre menuspalte og en højre artikelspalte), indeholdt i et element #page. Dette sidstnævnte element er ét jeg næsten altid bruger for at kunne styre placeringen af alt indhold på siden.

Stylesheet'et for denne side ser således ud:

html, body {
  background:rgb(239,239,239);
  margin:0;padding:0;
  font-family:georgia,times,serif;}
div#page {
  width:90%;
  margin:1em auto;}
#leftcol {
  width: 25%;
  float: left;}
div#leftcol a {
  display:block;}
#footer {
  clear: left; } /* Nødvendig for at få
  sidehovedet til at lægge sig under det 
  eller de float'ede elementer.*/

Når du kigger på eksemplet, er det jo ganske tydeligt, at det ikke opfylder vore forventninger til et to-spaltet layout. Jeg bringer det imidlertid alligevel, fordi eksemplet kan lære os noget om float'ede elementers natur. Jeg oplister her de hovedpunkter, der illustreres af eksempel 1:

  1. Et float'et element skal altid have en bredde. Har elementet ikke en bredde, skal det blive så smalt som det bredeste element i indholdet, hvilket oftest vil være det bredeste ord. (Shrink Wrap). Det gør det så ikke altid alligevel, men det er browserens fejl.
  2. Et float'et element får den højde, indholdet tilsiger (medmindre vi giver elementet en eksplicit højde).
  3. Det er særlig tydeligt, hvis du bruger linket i venstre spalte til at give artiklen en lidt mørkere grå farve. Da vil du se, at artiklen i virkeligheden strækker sig over hele #page-elementets bredde. Det er kun tekstens venstre margin, der skydes til højre af det float'ede element.
  4. Det er også værd at bemærke, at overkanten af artiklen flyder op til overkanten af det float'ede element. Det ses igen tydeligst, hvis du bruger linket til at sætte en baggrundsfarve på artikelteksten.

Det umiddelbart største problem med de to spalter er naturligvis, at teksten i den brede spalte så at sige flyder ind over den smalle spalte, hvis den smalle spalte er lavere end den brede spalte.

Det problem kan vi tage vare på (eksempel 2) ved også at float'e den brede spalte. Det sker ved hjælp af følgende tilføjelse til stylesheet'et ovenfor:

#rightcol {
  width: 74%;
  float: left;}

Nu tegnes sidens indhold af to float'ede elementer. Det, der kommer først i kildekoden, er det flyder længst til venstre.

Til dette eksempel er følgende yderligere bemærkning at gøre:

  1. To (eller flere) float'ede elementer, hvis samlede bredde er mindre end bredden af det overordnede element, flyder op ved siden af hinanden.

Elementernes bredde

Bemærk, at jeg ovenfor har givet #rightcol-elementet en lidt smallere bredde end de 75 procent, der egentlig burde være plads til. Det er sket af hensyn til Internet Explorer, der har besvær med at lægge procenter sammen på samme måde som andre browsere.

Det vil ofte være uacceptabelt. Sidehoved og sidefod være de fulde 100 procent af bredden, og så vil det se forkert ud at summen af indholdets bredder ikke går helt ud til kanterne.

Det bli'r kun værre, hvis vi begynder at sætte padding eller borders på den ene eller begge spalter.

Den umiddelbare løsning er at float'e #rightcol elementet til den anden side:

#rightcol {
  width: 74%;
  float: left;}

Det er eksempel 2a, der bliver resultatet af denne øvelse. Det er jo heller ikke særligt tilfredsstillende, igen et eksempel jeg ta'r med af pædagogiske årsager. Vi ser her den samme effekt som vi så i eksempel 1, nemlig at det float'ede element kun skubber til teksten, og ikke til elementet.

Løsningen på problemet ku' godt minde lidt om den metode, jeg præsenterede i formbindelse med layout ved hjælp af position-egenskaben, nemlig at give det brede element en margin, der kan rumme den smalle spalte. (Eksempel 2b).

Stylesheet'et til denne løsning gengiver jeg her i sin helhed, for så vidt angår de væsentlige dele:

div#page {
  width:90%;
  margin:1em auto;
  background:transparent;}
#leftcol {
  width: 25%;
  float: left;
  margin-top:20px;}
#rightcol {
  margin-left:25%;}
#footer {
  clear: left; 
  border-top:1px solid #257;}

Sagen er, at et float'et element i har nogle af de samme egenskaber som som et absolut positioneret element: Det udgør et lag, der så at sige svæver over websiden. Men i modsætning til det positionerede element, der ikke skubber til websidens øvrige elementer, skubber det float'ede element til elementernes indhold. Og i relation til eksempel 2b ser vi, at et float'et element kan flyde op i den plads, der skabes af en margin.

Højrestillet menuspalte

Det er ret uproblematisk at at bytte om på de to spalter, således at den smalle spalte kommer til højre og den brede spalte til venstre. Kildekoden se nu således ud:

<div id="page">
  <div id="banner">
  <h1>Sidehoved</h1>
  </div>
  <div id="rightcol">
  [ Menu ]
  </div>
  <div id="leftcol">
  [ Artikel ]
  </div>
  <div id="footer">
  <h2>Sidefod</h2>
  </div>
</div>

Eksempel 3.

Stylesheet'et til eksempel 3:

div#page {
  width:90%;
  margin:1em auto;}
#rightcol {
  width: 25%;
  float: right;}
#leftcol {
  margin-right:27%;
  border-right:1px solid black;}
#footer {
  clear: right; 
  border-top:1px solid #257;}

Fikseret bredde på menukolonnen

Begge kolonner er i de 3 første eksempler fuldstændigt elastiske, de øges og mindskes med browservinduets bredde. Ofte vil vi imidlertid ønske at give menukolonnen en fikseret bredde.

Det har jeg gjort i eksempel 4 ved at ændre procentværdierne i ovenstående tilpixelværdier, margin-right 220 pixel i stedet for 27% og width 200 pixel istedet for 25%.

Negative marginer

Ryan Brill (se afsnittet længere nede i artiklen) har foreslået en meget elegant løsning, der giver os lidt bedre kort på hånden, når vi for alvor skal opnå noget med at bruge float-egenskaben til layout.

Den grundlæggende form er fortsat den samme:

<div id="page">
  <div id="banner">
  <h2>Sidehoved</h2>
  </div>
  <div id="leftcol">
  [ Artikelstof ]
  </div>
  <div id="rightcol">
  [ Menu]
  </div>
  <div id="footer">
  <address>
  [Sidefod]
  </address]
  </div>
</div>

– men nu har jeg ændret på stylesheet'et for så vidt angår de vigtigste elementer:

#leftcol {
  width: 100%;
  float: left;
  margin-right: -200px;  }
  
#rightcol {
  width: 200px;
  float: right;  }

Resultatet af dette ser du i eksempel 5. Det er jo ikke særligt opmuntrende, vi er snarere kommet fra asken i ilden, eftersom artikelteksten flyder ind under den smalle spalte.

Den misere kommer jeg ud af ved at omslutte indholdet af #leftcol-elementet med endnu en div, således at kildekoden – igen for hele siden – kommer til at se således ud:

<div id="page">
  <div id="banner">
  <h2>Sidehoved</h2>
  </div>
  <div id="leftcol">
    <div id="indhold">
    [ Artikelstof ]
    </div>
  </div>
  <div id="rightcol">
  [ Menu]
  </div>
  <div id="footer">
  <address>
  [Sidefod]
  </address]
  </div>
</div>

Dette sætter mig i stand til at give tekstindholdet en positiv højre margin, der skyder højre kant af indholdet til venstre:

div#indhold {
  margin-right:220px;  }

Se eksempel 6. Nu rykker vi, også mere end det umiddelbart ser ud til.

Kolonnernes højde

Som du ser, hvis du benytter linket, der viser en baggrundsfarve for tekstindholdet, har vi med disse manøvrer opnået, at artikelteksten ikke længere løber ind under menuspalten. Hvad der ikke er så tydeligt er, at sidefoden skubbes nedad, uanset hvilken en af spalterne, der har det meste indhold. Det kan du tydeliggøre ved at bruge linket, der viser/skjuler noget ekstra tekst i højre kolonne.

Hermed har vi nået det væsentligste ved at konstruere ved hjælp af float-egenskaben, nemlig at sidefoden altid rykker ned under indholdet.

Men der er mere: Hvis du kan forestille dig, at såvel venstre som højre spalte er indeholdt i et div-element, synes det klart at dette div-elements højde bestemmes af indholdet af den spalte, der har det meste indhold ("meste" i betydningen flest linier).

Hvis jeg nu indsætter et sådant element og forsyner det med en grafisk baggrund, der er lige så bred som min menuspalte, kan jeg få de to spalter til at se lige høje ud.

Eksempel 7 viser dette. Kildekoden, hvor jeg her kun gengiver de relevante dele, og har fremhævet det nye element med rødt, ser nu således ud:

#leftcol {
  width: 100%;
  float: left;
  margin-right: -200px;
  background-image:url(rightcolbg.png));
  background-repeat:repeat-y;
  background-position:right top;  }
div#indhold {
  margin-right:220px;  } 
#rightcol {
  width: 200px;
  float: right; }
div#rightcol a {
  display:block;
  margin-left:1em;  }
#footer {
  border-top:1px solid gray;
  clear: both;   }
div#container {
  background-image:url(rightcolbg.png);
  background-repeat:repeat-y;
  background-position:right top;  }
.clear {
  clear:both;height:0;}
.top {
  margin-top:0;padding-top:20px;}

Ryan Brills idé

Ideen med at bruge negative marginer er baseret på Ryan Brills artikel Creating Liquid Layouts with Negative Margins på webstedet A List Apart.

Bemærk, at den negative margin først får virkning, når det element, der ligger ved siden af, får en tilsvarende eller større positiv margin. Det er lidt ligesom hængende indrykning i brødtekst:

p.hindryk {
text-indent:-2em;
margin-left:2em;}

I dette eksempel rykker text-indent-egenskaben første linie i et afsnit 2 em til venstre, men det ses kun, hvis vi samtidig giver hele tekstafsnittet en venstre margin.

Container-elementet

Som bemærket ovenfor er illusionen om at begge kolonner er lige høje afhængig af, at såvel #leftcol som #rightcol er omsluttet af et element. Jeg kalder dette element for #container. #container-elementet er en div, hvis indhold består af #leftcol og #rightcol, og det synes klart at #container-elementet får den højde, som den højeste af de to kolonner eller spalter har.

Der er brug for et clear-element efter afslutningen af de to kolonner og før #container-elementet afsluttes. For at det ikke skal være synligt, har jeg givet dette element en eksplicit høje på 0 pixel.

Det grafiske element

Det grafiske elements opgave er at synliggøre den tilsyneladende ens højde. Derfor er det baggrund for #container-elementet.

Den grafik, der skaber spaltestregen, er:

Det er en 200 pixel bred og 10 pixel høj PNG-fil, der er transparent, bortset fra et 2 pixel bredt bånd i venstre side, der er mørkeblåt

Kigger du på HTML-kildekoden herover til dette eksempel vil du se, at også #leftcol-elementet er forsynet med denne baggrundsgrafik, på fuldstændig samme måde som #container-elementet. I den oprindelige artikel anbefaler Ryan Brill dette, angiveligt på grund af en "bug" i Internet Explorer. Derfor gør jeg det også her. Men det har ikke været muligt for mig at se, hvad der skulle være galt med visningen i hverken Internet Explorer 5 eller Internet Explorer 6, selvom #leftcol-elementet ikke får denne baggrundsgrafik.

Og mens vi er ved det, er eksemplet testet i Mozilla Firefox 0.9, Opera 7 og Netscape 7 foruden de to allerede nævnte browsere. Samt i Netscape 4.7.

Visningen i Internet Explorer 5

– er jeg ikke helt tilfreds med. Der er en margin imellem toppen og bunden af menukolonnen og de to rammekanter, der markerer hhv. bund og top af sidehoved og sidefod.

Denne margin skabes af de h2-tekster, der i eksemplet optræder som hhv. sidehovedtekst og sidefodstekst. Disse marginer fjernes let ved at sætte hhv. margin-bottom og margin-top til 0, og i stedet indsætte en passende mængde padding.

Venstrestillet menukolonne

Jeg bryder mig ikke om det, men nogle konstruktører foretrækker at have en venstrestillet menukolonne. Derfor gengiver jeg i eksempel 8 den samme webside, men med menukolonnen til venstre i stedet for til højre.

Det, jeg har gjort for at få resultatet i eksempel 8 er at ændre en smule på stylesheet'et til eksempel 5, på følgende punkter:

  1. Jeg har spejlvendt baggrundsgrafikken rightcolbg.png og gemt den som leftcolbg.png
  2. background-position er ændret fra right top til left top.
  3. Alle formregler float:left er ændret til float:right, og alle formregler float:right er ændret til float:left.
  4. margin-right er ændret til margin-left.

Det er alt hvad der skal til, der skal ingen ændringer til i kildekoden, bortset fra at jeg mest for min sjælefreds skyld har ændret elementet div#rightcol til div#leftcol. Men det er altså ikke nødvendigt i kildekoden at bytte om på rækkefølgen af de to hovedelementer.

3 kolonner, alle lige høje

Som nævnt herover under overskriften “Ryan Brills idé” bygger disse konstruktioner på Ryan's artikel på webstedet A List Apart. I denne artikel anviser Ryan også en 3-spaltet konstruktion. Den er imidlertid ikke uden problemer, så derfor har jeg jeg lavet en særskilt artikel over dette emne, 3 lige høje spalter.

Konklusion

Der er andre kilder til løsningen af problemet med at få to eller flere kolonner til at se ud, som om de er lige høje. I diskussionen af Ryan Brills artikel (se info-boksen i højre spalte) fandt jeg blandt andet en reference til www.webproducer.at/flexible-layout/, som nok er værd at studere.

Idéen med denne artikel har været at præsentere en skudsikker metode til at sikre, at to eller flere kolonner i et CSS-baseret layout altid syner lige høje, samt igennem brugen af float-egenskaben også at sikre, at en sidefod altid ligger under alle kolonner, uanset hvilken, der er højest.

Denne side er senest opdateret: February 25, 2006

Artikler om CSS-layout

Kvikfix lige høje spalter

Hvis dit mål er blot at få en anden baggrundsfarve i en eller to smalle kolonner, er der en kvikfix løsning, som jeg fortæller om i principlayout 7 og favoritlayout 4.

Ryan Brills idé

Den layoutmetode, der beskrives i denne artikel, er baseret på Ryan Brills idéer som de kommer til udtryk i artiklen Creating Liquid Layouts with Negative Margins på webstedet A List Apart.

Andre løsninger

Der er andre kilder til løsningen af problemet med at få to eller flere kolonner til at se ud, som om de er lige høje. I diskussionen af Ryan Brills artikel (se info-boksen herover) fandt jeg blandt andet en reference til www.webproducer.at/flexible-layout/, som nok er værd at studere.

Søg på siderne