Spaltenlayout mit Bootstrap

Aus Debacher-Wiki
Wechseln zu:Navigation, Suche

Grundlagen

Für die Nutzung in Typo3 soll ein Layout erstellt werden, mit zwei Spalten (eine Erweiterung auf drei Spalten ist dann jederzeit möglich). Dieses Layout soll responsive sein, sich also an das Ausgabegerät möglichst perfekt anpassen. Bis hierher ist das mit Bootstrap als Grundlage kein Problem. Schwieriger wird es, wenn die Spalten, unabhängig vom jeweiligen Inhalt, gleich hoch werden sollen.

Für die folgenden Beispiele benutze ich das Angebot von http://www.bootply.com, hier kann dann jeder Leser auch mit dem html, dem css und ggf. dem Javascript experimentieren ohne irgendwelchen Schaden anzurichten.

Bootply0.png

Das Grundlayout

Unter http://www.bootply.com/LdQclKSgr5 findet sich das erste Beispiel mit den Grundlagen.

Hier der HTML-Code

<div id="zweispaltig">
 <div class="container">
  
   <div class="row" id="header">
     <div class="col-md-12">
        <div id="headerimage" style="background-image:url('http://placehold.it/850x140/00ff00/000000&text=Besispiel+x');"></div>
     </div>
   </div>
  
   <div class="row equalheight">
     <div class="col-md-3 equal" id="spalte-links">
        Spalte 1<br>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut lab
     </div> 

     <div class="col-md-9 equal" id="hauptinhalt">
        Spalte 2<br>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut lab
     </div>
     
   </div>

   <div class="row" id="footer">
          <div class="col-md-12">Beschreibung: <a href="http://debacher.de/wiki/Spaltenlayout_mit_Bootstrap">debacher.de/wiki/Spaltenlayout_mit_Bootstrap</a></div>
   </div>
 </div> 
</div>

Das zugehörige CSS

/* CSS used here will be applied after bootstrap.css */
 
 #headerimage {
  height: 140px;
  margin-left: -15px;
  margin-right: -15px;
 }
 
 #hauptinhalt {
  background-color: yellow; 
 }
 
 #spalte-links {
  background-color: cyan; 
 }

 a {
  color: white; 
 }

 #footer {
  background-color: blue; 
  text-align: center; 
  color:white; 
  height:50px;
  padding-top: 10px;
  border: 0; 
  border-top:1px solid #DDDDDD;
 }

Das Ergebnis

In einem normalen Browser ergibt sich folgendes Bild

Bootply1.png

Man sieht deutlich, dass die beiden Spalten nicht die gleiche Höhe besitzen. Auf einem Smartphone sieht das deutlich besser aus.

Bootply2.png

Die folgenden Tricks sind also immer nur für die großen Geräte notwendig.

Der erste Trick

Mit einer kleinen Veränderung im CSS scheinen die beiden Spalten gleich lang.

http://www.bootply.com/wvF8rJFUgu#

Wir ergänzen das CSS um:

.equal {
 margin-bottom: -99999px;
 padding-bottom: 99999px;
}

.equalheight {
 overflow: hidden; 
}

Damit wird der innere Rand (Padding) beider Inhalts-Spalten jeweils um 99999 Pixel nach unten verschoben und der äußere Rand (Margin) um 99999 Pixel zurück geschoben. Mit overflow: hidden werden dann die überstehenden Bereiche, die 99999 Pixel lang sind, verborgen. Der Effekt ist folgendermaßen.

Bootply3.png

Problem: Das Konstrukt funktioniert ganz gut. Es hat aber leider einen kleinen Haken. Falls man einen Anker in einer Seite aufruft, also eine URL mit z.B. #c401 am Ende, dann wird der Inhalt teilweise aus dem sichtbaren Bereich herausgeschoben. Anker lassen sich also im Zusammenhang mit diesem System nicht nutzen.

CSS Tabellen

Eine der klassischen Lösungen arbeitet mit CSS-Tabellen, eine Beschreibung dazu ist unter http://www.minimit.com/articles/solutions-tutorials/bootstrap-3-responsive-columns-of-same-height bzw. http://www.hongkiat.com/blog/css-equal-height/ zu finden.

http://www.bootply.com/KDGtM3xdhO (oder eventuell besser: http://www.bootply.com/9BFdkGDkPh )

Hierzu muss wieder nur das CSS angepasst werden.

.equalheight {
  display: table;
  height: 100%;
  /* fix overflow */
  table-layout: fixed;
 }
 .equal {
  display: table-cell;
  float: none ;
  height: 100%;
 }

Bootply7.png

Damit die Spalten auf kleinen Geräten untereinander laufen muss man dass Floaten wieder erlauben.

Bootply8.png

@media (max-width: 767px) {
 .equal, .equalheight {
    display: block;
  }
 }

JQuery kann viel

Auch mit ein paar Zeilen Javascript-Code kann man gleichlange Spalten erzeugen, zumindest wenn JQuery vorhanden ist.

http://www.bootply.com/ywCK0VRpQR

Beschreibung hierzu: https://www.stetic.com/developer/hoehe-von-html-elementen-automatisch-anpassen-jquery-und-javascript.html

 var max_height = 0;
 $('.equal').each(function(e) {
   h = $(this).height();
   if(typeof(h) != "undefined") {
    if(h > max_height) {
      max_height = h;
    }
   }
 });
 if(max_height > 0) {
   $('.equal').height(max_height);
 }
 

Hier wird einfach von allen Elementen mit der Klasse .equal die aktuelle Höhe ermittelt und die größte Höhe notiert, dann wird diese Höhe bei allen derartigen Elementen gesetzt.

Bootply9.png

Das funktioniert in allen Größen wie gewünscht.

Problem: Das Konstrukt lässt sich nicht einfach schachteln, also z.B. bei Dreispalten-FCE im Dreispalten-Layout. Es muss dann immer der Bezeichner (hier .equal) gewechselt werden und jeweils ein passendes Javascript eingefügt werden.

Die Methode der Zukunft

Wenn endlich alle Internet-Explorer-Versionen vom Erdball verschwunden sind, dann wird generell eine sehr moderne Methode alle Tricksereien mit CSS überflüssig machen. Wer auf Nutzer im IE<10 verzichten kann, der kann diese Methode sofort einsetzen.

http://www.bootply.com/6BwFtVndmc#

Weitere Erläuterungen unter http://www.mediaevent.de/tutorial/flexbox.html

Wir ergänzen folgendes CSS:

.equalheight {
  display: inherit;
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  }
  
 .equal {
  flex: 0 0 1;
 }

Das display: flex ist eine Regel, die genau für die Spalten eingeführt wurde. Ich habe hier auch alle Versionen mit Präfix aufgeführt, damit die Lösung in möglichst vielen Browsern funktioniert. Mit der Eigenschaft flex: 0 1 1 kann man Einstellen, wie die Spalten jeweils auf Größenänderungen reagieren. Sie können ihre Größe damit unterschiedlich verändern.

Im großen Browserfenster sieht das wie gwünscht aus.

Bootply4.png

Auf dem Smartphone sieht das jetzt nicht wie erwünscht aus, da sich die Spalten beliebig verkleinern lassen.

Bootply5.png

Daher muss man noch eine Einstellung ergänzen.

@media (max-width: 767px) {
 .equalheight {
    display: block;
 }
 }

Damit wird für kleine Ausgabegeräte (bis 767 Pixel) die Spalteneinteilung abgeschaltet und die Spalten landen wieder untereinander.

Bootply6.png

Das funktioniert einwandfrei, zumindest in aktuellen Browsern.

Problem: Browser, die flex nicht kennen ignorieren diese Einstellung, hier werden also die kurzen Spalten zu kurz. Man könnte hier die Hintergrundfarbe einer der Seitenspalten für das umfassende Element angeben, das wirkt dann aber nur für eine Spalte, wenn die zu kurz wird.

Ein altes Verfahren

Bei unseren Webseiten haben wir vor Bootstrap meistens ein anderes Verfahren benutzt.

http://www.bootply.com/ayu3QPpbLj

Hier wird für jede der Spalten außen ein Container-Element darum gesetzt.

   <div class="row">
     <div id="container-hauptinhalt">
      <div id="container-spalte-links">
        <div id="spalte-links">Spalte 1<br>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut lab</div>
        <div id="hauptinhalt">Spalte 2<br>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut lab</div>
      </div>
     </div>
   </div> 
 

Jedes der Container-Elemente ist dann so hoch wie die höchste Spalte, da die ja innerhalb liegt. Diese Container tragen die Hintergrundfarbe und liegen alle übereinander. Sie müssen nun jeweils so verschoben werden, dass an der richtigen Stelle die richtige Farbe erscheint. Dann müssen die Inhalte noch in die richtige Position geschoben werden.

 /* CSS used here will be applied after bootstrap.css */
 
 #headerimage {
   height: 140px;
   margin-left: -15px;
   margin-right: -15px;
 }
 
 #footer {
   background-color: blue; 
   text-align: center; 
   color:white; 
   height:50px;
   padding-top: 10px;
   border: 0; 
   border-top:1px solid #DDDDDD;
 }
 
 a {
   color: white; 
 }
 
 /* Start Spalten mit CSS */
 #container-hauptinhalt {
   float:left;
   width:100%;
   overflow:hidden;
   background-color: yellow; 
 }
 #container-spalte-links {
  float:left;
  width:100%;
  position:relative;
  right:70%;
  background-color: cyan; 
 }
 #spalte-links { 
  float:left;
  width:30%;
  position:relative;
  left:70%;
  overflow:hidden;
 }
 #hauptinhalt {
  float:left;
  width:70%;
  position:relative;
  left:70%;
  overflow:hidden;
 }

Bootply10.png

Hier wird sehr viel mit float gearbeitet, damit sich die Elemente passend umfließen können. Eine schöne Beschreibung ist unter http://matthewjamestaylor.com/blog/equal-height-columns-cross-browser-css-no-hacks zu finden.

Auch die Ausgabe für schmalere Geräte lässt sich realisieren, indem man folgende CSS-Zeilen ergänzt:

@media (max-width: 767px) {
 
  #spalte-links {
   left:0;
   width: 100%;
  }
  #hauptinhalt {
   left:0;
   width: 100%;
   background-color: yellow;
  }
  #container-hauptinhalt {
  }
  #container-spalte-links {
   right:0;
  }  
 }
 

Bootply11.png

Bei beiden Darstellungen fehlen noch die Ränder der jeweiligen Textbereiche. Dazu muss man nur die Breiten und die Verschiebungen der Inhaltsbereiche entsprechend anpassen. Ich habe das unterlassen, da dann das Grundprinzip deutlicher sichtbar wird.

Faux Columns

Eine weitere ältere Technik ist unter http://codethatworks.blogspot.de/2012/05/responsive-full-height-columns-using.html beschrieben.

Hier legt man um die Inhaltsspalten ein zusätzliches DIV herum und dieses DIV bekommt dann eine Grafik als Hintergrund zugeordnet, nicht die eigentlichen Spalten. Das Hintergrundbild muss also einen Farbwechsel beinhalten.

Ein Nachteil bei diesem System ist, dass die linke Spalte fest sein muss, damit das Layout funktioniert.

Links