Div & Float

Uit De Vliegende Brigade
Ga naar: navigatie, zoeken

Met het div-element kun je gebieden binnen een website afbakenen en als een op zichzelf staand object bewerken, vergelijkbaar met frames of minipages in andere systemen. Div is wat dit betreft de opvolger van tabellen.

Voorbeeld

Resultaat: Een sectie met lichtgrijze achtergrond, aangepast lettertype, gecentreerd, op 75% van de paginabreedte

HTML-code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Kaders</title>
    <link href="Kaders-01.css" rel="stylesheet" type="text/css" />
</head>

<body>

<div id="page">

	Hello, world!

</div>

</body>
</html>

CSS-code:

div#page{
	width:75%;
	margin-left: auto;
	margin-right: auto;
	background-color: #f0f0f0;
	border-style: solid;
	border-width: 1px;
	border-color: ff0000;
	padding: 20px;
	font-size: 12px;	
}

clear

Een float zorgt ervoor dat een block-element naar een bepaalde kant wordt geduwd, waarbij het object buiten de 'flow' van de site belandt. De rest van de content stroomt daar omheen.

Maar soms wil je juist dat zo'n float niet compleet genegeerd wordt, bv. omdat je een kader wilt trekken om een float met de content die er omheen stroomt. Daarvoor heb je het css-commando clear: Nieuwe elementen worden pas na de betreffende float geplaatst.

En soms is een clear ongewenst zoals in dit voorbeeld: De tekst WordPressTest wil ik tussen de blokken (floats) hebben, maar staat eronder
En dit is de oorzaak: Die tekst is gevat binnen een h1-heading, en de bijbehorende css-code bevat het commando clear:both, zodat de tekst pas begint waar beide blokken ophouden

Vier kolommen

Vier kolommen naast elkaar. Gewoon alle vier float: left. Helemaal niet nodig om er eentje naar rechts te laten drijven
Oh nee! De tekst had boven en onder de floats moeten staan!
Probleem opgelost. Al is er één ding wat ik niet goed snap: Had er geen clear gegeven moeten worden voorafgaand aan de tekst onderaan de kolommen?

Hier komt de test: Kan ik vier kolommen naast elkaar zetten? Ik doe dit rechtstreeks in Drupal (page.tpl.php en style.css): Uiteindelijk wil ik het daar gebruiken, en ik vind het ook nog 's overzichtelijker.

Dit is simpel...

Anyhow, die kolommen zijn niet zo moeilijk nu ik snap dat je met float objecten naar een bepaalde kant duwt:

<div id="Kolom01">	Dit is Kolom01	</div>
<div id="Kolom02">	Dit is Kolom02	</div>
<div id="Kolom03">	Dit is Kolom03	</div>
<div id="Kolom04">	Dit is Kolom04	</div>
div#Kolom01{
	width:25%;
	float: left;
	background-color: #eee;
}

div#Kolom02{
	width:25%;
	float: left;
	background-color: #ddd;
}

div#Kolom03{
	width:25%;
	float: left;
	background-color: #ccc;
}

div#Kolom04{
	width:25%;
	float: left;
	background-color: #bbb;
}

...Toch?

Het wordt lastiger als je boven en onder de kolommen nietsvermoedend een fijn stukje tekst wilt plaatsen:

Bovenaan tekst

<div id="Kolom01">	Dit is Kolom01	</div>
<div id="Kolom02">	Dit is Kolom02	</div>
<div id="Kolom03">	Dit is Kolom03	</div>
<div id="Kolom04">	Dit is Kolom04	</div>

Onderaan tekst

Geen probleem

Maar ehh, nu floats geen geheimen meer voor ons heeft is dit allemaal begrijpelijk: Die kolommen drijven naar links, en de rest 'vloeit' er een beetje omheen. Net als tekst rondom een foto in een tijdschrift. De tekst kan zo'n beetje alle kanten opgaan.

Daarvoor heb je de eigenschap clear: Dan stopt-ie met dat gedrijf en plaatst-ie eerst waar-ie mee bezig was:

Bovenaan tekst

<div id="Schoonmaken"></div>

<div id="Kolom01">	Dit is Kolom01	</div>
<div id="Kolom02">	Dit is Kolom02	</div>
<div id="Kolom03">	Dit is Kolom03	</div>
<div id="Kolom04">	Dit is Kolom04	</div>

Onderaan tekst
<div#Schoonmaken{
	clear: both;
}

div#Kolom01{
	width:25%;
	float: left;
	background-color: #eee;
}

div#Kolom02{
	width:25%;
	float: left;
	background-color: #ddd;
}

div#Kolom03{
	width:25%;
	float: left;
	background-color: #ccc;
}

div#Kolom04{
	width:25%;
	float: left;
	background-color: #bbb;
}

Het Raadsel van de Krappe Container

Eih! De container omvat niet de inhoud. Het is een platte container, bovenop de kolommen. Klinkt als een kolfje naar de hand van Float-man!
No worries. Just go with the float

Dit schijnt een klassiek probleem te zijn. Dus die doen we effe tussendoor.

Iemand wil een lijntje trekken om die vier kolommen. Dat lijntje is dus de container. Dus dat persoon (niet ik!) denkt...

<div id="KrappeContainer">

	<div id="Kolom01">	Dit is Kolom01	</div>
	<div id="Kolom02">	Dit is Kolom02	</div>
	<div id="Kolom03">	Dit is Kolom03	</div>
	<div id="Kolom04">	Dit is Kolom04	</div>

</div>

met de volgende additionele css-code:

div#KrappeContainer{
	border: 1px solid #000;
}

Anyhow. Om het verhaal kort te maken: Bij mij werkte het prima door boven de kolommen weer dezelfde float te gebruiken, maar de literatuur zegt dat 't ingewikkelder kan zijn.

Tekst tussen objecten

Hoe doe je twee objecten die links en rechts staan, met daartussen tekst?

Objecten + tekst

So far, so good: Links een rechts een gefloat object met daartussen content die zich aanpast aan de beschikbare ruimte. Voor de tekst gebruik ik geen div

Dit is vermoedelijk een gerelateerd probleem, maar voor de verandering een probleem waar ik niet goed uitkom.

Opmaak (html meer interne style sheet):

<html>
<head>

<style type="text/css">

   div#linkerkolom{
      float: left
   }

   div#rechterkolom{
      float: right
   }
   
</style>
  
</head>
<body>

<div id="linkerkolom">
	<img src="afbeelding.gif">
</div>

<div id="rechterkolom">
	<img src="afbeelding.gif">
</div>

Lorem ipsum dolor sit amet ... nisl. 
	
</body>
</html>

Nu met gecentreerde tekst

Weer gelukt

Nu wordt het interessant: Hoe ga ik die tekst centreren? Lijkt me, met een div, toch?

De eerste stap: Een lege div toevoegen. Dat heeft gelukkig geen enkel effect. Daarom gelijk door naar de volgende stap: text-align: center:

<html>
<head>

<style type="text/css">

   div#linkerkolom{
      float: left
   }

   div#rechterkolom{
      float: right
   }

   div#midden{
      text-align: center;
   }
   
</style>
  
</head>
<body>

<div id="linkerkolom">
	<img src="afbeelding.gif">
</div>

<div id="rechterkolom">
	<img src="afbeelding.gif">
</div>

<div id="midden">
   Lorem ipsum ... nisl. 
</div>
	
</body>
</html>

Nu met WordPress

Dit gaat mis, omdat de content-div als tweede object wordt geplaatst. Daardoor blijft er geen ruimte meer over voor het rechterblok
De oplossing is nogal eenvoudig: Eerst de blokken plaatsen, daarna pas de div met het content: Dan kan de content zich aanpassen aan de blokken!

En dit is de betreffende WordPress header.php-tekst:

<?php
/**
 * The Header for our theme.
 *
 * Displays all of the <head> section and everything up till <div id="main">
 *
 * @package Shape
 * @since Shape 2.0
 */
?><!DOCTYPE html>

<!--[if IE 8]>
<html id="ie8" <?php language_attributes(); ?>>
<![endif]-->
<!--[if !(IE 8) ]><!-->
<html <?php language_attributes(); ?>>
<!--<![endif]-->

<head>
<meta charset="<?php bloginfo( 'charset' ); ?>" />
<meta name="viewport" content="width=device-width" />
<title><?php
/*
* Print the <title> tag based on what is being viewed.
*/
global $page, $paged;
 
wp_title( '|', true, 'right' );
 
// Add the blog name.
bloginfo( 'name' );
 
// Add the blog description for the home/front page.
$site_description = get_bloginfo( 'description', 'display' );
if ( $site_description && ( is_home() || is_front_page() ) )
echo " | $site_description";
 
// Add a page number if necessary:
if ( $paged >= 2 || $page >= 2 )
echo ' | ' . sprintf( __( 'Page %s', 'shape' ), max( $paged, $page ) );
 
?></title>
<link rel="profile" href="http://gmpg.org/xfn/11" />
<link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>" />
<!--[if lt IE 9]>
<script src="<?php echo get_template_directory_uri(); ?>/js/html5.js" type="text/javascript"></script>
<![endif]-->
<?php wp_head(); ?>
</head>
 
<body <?php body_class(); ?>>

<div id="page" class="hfeed site">

	<header id="masthead" class="site-header" role="banner">

		<div id="headersidebar1"> 
			<img src="<?php echo get_bloginfo('template_directory');?>/images/boaafbeeldingheaderlinks.jpg" alt="" >
		</div>
		<div id="headersidebar2">
		        <img src="<?php echo get_bloginfo('template_directory');?>/images/boaafbeeldingheaderrechts.gif" alt="" >
		</div>
		<div id="headercontent"> 
                   Lorem ipsum ... est laborum.
		</div> <!-- headercontent -->
	
		<nav role="navigation" class="site-navigation main-navigation">     
	
			<h1 class="assistive-text"><?php _e( 'Menu', 'shape' ); ?></h1>
			<div class="assistive-text skip-link">
                           <a href="#content" title="<?php esc_attr_e( 'Skip to content', '_s' ); ?>">
                           <?php _e( 'Skip to content', 'shape' ); ?></a>
                        </div>
		      
		</nav><!-- .site-navigation .main-navigation -->

	</header><!-- #masthead .site-header -->

<div id="main" class="site-main">

Casus: Header at_commerce

En nu een nog echter voorbeeld: De header van het at_commerce theme aanpassen.

Het probleem: Te grote header

Het probleem: Zo snel de slogan te veel naar rechts uitloopt, zakt alles daaronder naar beneden, en krijg je een onnodig hoge header. Lijkt me een typisch geval van onnodige clearing
Ingezoomed: De header bestaat uit twee div's en na die eerst div wordt waarschijnlijk iets met clear gedaan wat niet handig uitkomt

Nog enkele aspecten tav. het probleem:

  • Titel en Slogan worden met display: inline weergegeven
  • Het blok met Search, winkelwagen en menu'tje, is rechthoekig, terwijl het gedeelte linksboven van die rechthoek, helemaal niet gebruikt wordt
  • Het sjabloon page.tlp.php bevat inderdaad een clearfix-classe-ID voor div branding

Oplossing (1): Slogan onder titel plaatsen

Eerst de slogan onder de titel plaatsen, door display te vervangen in fresh.css. Daarnaast moet de padding van de slogan worden verwijderd, anders is-ie niet uigelijnd:

/* Slogan onder header ipv. ernaast
 * ====================================================
 *
*/
#site-name, #site-slogan {display: block;}
#site-slogan {padding-left: 0;}

Nu is het probleem eigenlijk al opgelost. Maar er is meer.

Oplossing (2): Clearfix verwijderen

In het sjabloon deze regel:

<div id="branding" class="branding-elements clearfix<?php print $branding_classes ? ' ' . $branding_classes : ''; ?>">

vervangen door:

<div id="branding" class="branding-elements <?php print $branding_classes ? ' ' . $branding_classes : ''; ?>">

Misschien niet meer nodig, of zelfs ongewenst: Gaan objecten nu niet overlappen op smalle displays? → Getest: Nee. Laat dan maar zo!

Oplossing (3): Negatieve verticale marge

Zoals hierboven opgemerkt: Het probleem is eigenlijk dat de rechthoek branding en de rechthoek Header (met Search, winkelwagen, etc.), snel overlappen, ook al is de linkerbovenhoek van Search leeg. Dat komt omdat het menu'tje verticaal is. Oplossing: Negatieve marges voor Header gebruiken! Het blijkt dat de linkermarge het probleem is. En dit is de oplossing:

/* Negatieve linkermarge Header
 * ====================================================
 *
*/
.hl-l .region-header {margin-left: -250px;}

Bronnen