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.
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;}
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:
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.float
'et element får den højde, indholdet
tilsiger (medmindre vi giver elementet en eksplicit højde). #page
-elementets bredde. Det er kun tekstens
venstre margin, der skydes til højre af det float
'ede
element.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:
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.
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>
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;}
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%.
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.
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;}
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.
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 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.
– 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.
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:
background-position
er ændret fra right top
til left top
.float:left
er ændret til float:right
,
og alle formregler float:right
er ændret til float:left
.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.
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.
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
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.
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.
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.