Content Folding

Avatar of Chris Coyier
Chris Coyier am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Vor weniger als einem Jahr veröffentlichte Trent Walton Content Choreography, in dem er sich über einige der Schwierigkeiten und Einschränkungen von responsiven Layouts beklagte.

Manchmal scheint es, als würde die gesamte Website-Architektur und -Planung über Bord geworfen, wenn sich der Inhalt neu anordnet.

Man muss zugeben, dass sehr viele responsive Designs am Ende so aussehen:

  1. Alles in eine Spalte quetschen
  2. Die Sidebar(s) nach unten verschieben

*hust* diese Seite macht das *hust*

Trent erwähnte, dass es vielleicht ein besserer Ansatz wäre, Inhalte zu „interdigitieren“.

Interdigitieren

Das heißt, Inhalte auf durchdachtere oder nützlichere Weise zu einer einzigen Spalte zusammenzufügen.

Ein praktisches Beispiel: Anzeigen-Faltung

Betrachten Sie ein Layout bei einem großen Browserfenster. Zwei Spalten. Artikel in einer breiten Spalte links, Anzeigen in einer schmalen Spalte rechts.

Bei schmaleren Browserfenstergrößen wechseln wir zu einer einzigen Spalte. Dieses Layout wird wahrscheinlich mit Floats realisiert, der bis heute gängigsten Layoutmethode. Leider bedeutet das wahrscheinlich, beide Spalten auf 100% Breite zu setzen und ihre Quellreihenfolge bestimmen zu lassen, welche oben liegt. Das heißt: alle Anzeigen nach unten verschieben. Wahrscheinlich nicht ideal. Wahrscheinlich wäre es besser, die Anzeigen in den Inhalt zu *falten*.

Aber wie?

Wahrscheinlich gibt es eine Reihe von Möglichkeiten, dies zu tun. Mit JavaScript könnten Sie die Fensterbreite messen und Elemente im DOM verschieben. Das erscheint mir aufwändig, aber die Browserunterstützung wäre gut. Ich würde mich lieber auf CSS verlassen, dafür ist CSS (wohl) da. Das Grid Layout mag einige Möglichkeiten bieten, aber für dieses Tutorial nehmen wir das brandneue CSS Regions, ein Beitrag von Adobe.

Hinweis: Diese Dinge sind brandneu und können sich ändern. Als ich dies im März 2012 schrieb, funktionierte diese Demo in Chrome. Jetzt im Januar 2013 tut sie es nicht mehr. Chrome 15-18 hatten teilweise Unterstützung und dann wurde sie in Version 19 entfernt, obwohl Chrome immer noch Unterstützung für die Eigenschaft anzeigt.

HTML

<section class="main-content">

  <article> ... </article>

  <div class="ad-region-1">
    <!-- empty, ads flow into here as needed -->
  </div>

  <article> ... </article>

  <div class="ad-region-2">
    <!-- empty, ads flow into here as needed -->
  </div>

  <article> ... </article>

  <div class="ad-region-3">
    <!-- empty, ads flow into here as needed -->
  </div>

</section>

<aside>
   <!-- Fallback content in this flow region, probably clone #ad-source -->
</aside>

<!-- Source of flowing content, essentially hidden as an element -->
<div id="ad-source">
  <a href="#"><img src="ads/1.jpg"></a>
  <a href="#"><img src="ads/2.jpg"></a>
  <a href="#"><img src="ads/3.jpg"></a>
  <a href="#"><img src="ads/4.png"></a>
</div>

Beachten Sie, dass der „Inhalt“ (unsere Anzeigen) in einem <div> am unteren Rand der Seite untergebracht ist. Sobald wir die CSS-Regionen eingerichtet haben, wird das Element im Wesentlichen versteckt und der Inhalt darin wird in die Regionen fließen, die wir ihm zuweisen.

CSS

Wir beginnen damit, dem div#ad-source, das den Inhalt hält, zu sagen, dass es seinen Inhalt in einen „benannten Fluss“ einfügen soll

#ad-source {
  -webkit-flow-into: ads;
  -ms-flow-into: ads;
}

Ich verwende hier nur zwei Vendor-Präfixes, da das im Moment die einzige Unterstützung ist. Ich würde empfehlen, die ungeprefixte Version *nicht* zu verwenden, da sich diese Dinge bei der endgültigen Implementierung ändern könnten.

‚ads‘ ist ein beliebiger Name, den wir uns ausgedacht haben. Es könnte alles sein, wie das Benennen einer CSS-Animation.

Nun richten wir Regionen ein, in die dieser Inhalt fließen soll. Zuerst in den Aside, dann in die interdigitierte Divs zwischen den Artikeln.

aside, [class^='ad-region'] {
  -webkit-flow-from: ads;
  -ms-flow-from: ads;
}

In unserem Fall sind bei breiten Browserfensterbreiten die Asides groß genug, um sie alle aufzunehmen. Bei schmaleren Breiten verstecken wir die Asides über Media Queries und zwingen den Inhalt, in die Divs zu fließen.

[class^='ad-region'] {
  display: none;
  height: 155px;
  width: 100%; /* Weird that this is required */
}

@media (max-width: 800px) {
  [class^='ad-region'] {
    display: block;
  }
  [class^='ad-region']:last-child {
    height: 300px; /* I wish height auto worked */
  }
  aside {
    display: none;
  }
}

Semantik

Alsooo ja, wir haben einige leere Elemente, mit denen wir herumspielen. Nicht sehr semantisch. Ich bin mir auch nicht sicher, was das für die Barrierefreiheit bedeutet. Ich weiß nur, dass sich der DOM nicht verändert. Der gesamte Inhalt, egal wo er „fließt“, ist immer noch innerhalb der „Quelle“ (des Elements mit der flow-into-Eigenschaft).

Die Sache ist jedoch: **Regionen sind layoutstil-unabhängig**. Wir verwenden in diesem Beispiel immer noch Floats für das Layout, aber der verwendete Layoutstil spielt eigentlich keine Rolle. Regionen, die mit CSS Grids kombiniert werden, könnten viel mächtiger und semantischer sein (ich weiß es einfach nicht).

Browser-Unterstützung

CSS Regions wird in **Chrome 16 bis 20** ausgeliefert, dann unter der Flagge „Enable CSS Regions“ in 21-22 und jetzt unter der Flagge „Enable experimental WebKit features“ in Chrome 23+. Es funktioniert in **Safari 5.2** (verfügbar als Dev oder WebKit Nightly). Angeblich funktioniert es auch in IE 10, aber ich konnte es nicht zum Laufen bringen.

Demo & Download

Zu Ihrer Freude

Demo ansehen   Dateien herunterladen

Bitte beachten Sie die oben genannte Browserunterstützung, sie ist sehr begrenzt.

Beachten Sie auch, dass bei einigen ziemlich breiten Browserfensterbreiten die Anzeigen im Aside abgeschnitten werden. Ich lasse es so, um zu veranschaulichen, wie Regionen nicht automatisch in der Höhe wachsen, Sie müssen sich selbst darum kümmern.

Update: Diese Demo funktionierte, war dann defekt und funktioniert jetzt wieder. Ich habe sie über Adobes CSS Regions Polyfill zum Laufen gebracht. Dies muss erneut überarbeitet werden, sobald sich die Spezifikation und die Browserunterstützung stabilisiert haben.

Browsererkennung

Dieses HTML und CSS wäre in einem Browser, der CSS-Regionen nicht unterstützt, ziemlich mies. Es gäbe diesen Block von Anzeigen zufällig am Ende der Seite. Stattdessen habe ich ein wenig JavaScript eingebaut (basierend auf diesem), um es zu testen und Klassen zum html-Element hinzuzufügen, die die Unterstützung widerspiegeln.

// Generic Testing Function
var supports = (function() {  
   var div     = document.createElement('div'),  
       vendors = 'Khtml Ms O Moz Webkit'.split(' '),  
       len     = vendors.length;  
  
   return function(prop) {  
      if (prop in div.style) return true;  
  
      prop = prop.replace(/^[a-z]/, function(val) {  
         return val.toUpperCase();  
      });  
  
      while (len--) {  
         if (vendors[len] + prop in div.style) {   
            return true;  
         }  
      }  
      return false;  
   };  
})();  
  
// Test
if ( supports('flowInto') ) { 
   $("html").addClass('cssregions');  
} else {
   $("html").addClass('no-cssregions'); 
}

Damit können wir Dinge tun, wie diese, um sicherzustellen, dass der Fallback in Ordnung ist.

#ad-source {
  display: none;
}
.cssregions #ad-source {
  display: block;
  -webkit-flow-into: ads;
  -ms-flow-into: ads;
}

Und auch den Inhalt des div#ad-source in den Aside kopieren, damit die Anzeigen dort zumindest bei den breitesten Browserfensterbreiten erscheinen.

Das sollte funktionieren, aber es meldet falsche Positive in Chrome, seit Chrome die Unterstützung in Chrome 23 entfernt hat. Sie können die Unterstützung jedoch aktivieren…
  1. Navigieren Sie über die Adressleiste zu chrome://flags
  2. Wenn Sie Chrome 21 oder 22 verwenden, suchen Sie nach der Flagge „Enable CSS Regions“ und aktivieren Sie sie.
  3. Wenn Sie Chrome 23 oder neuer verwenden, suchen Sie nach der Flagge „Enable experimental WebKit features“ und aktivieren Sie sie.
  4. Starten Sie Ihren Browser neu, indem Sie unten links auf die Schaltfläche „Jetzt neu starten“ klicken.

Wenn Sie diesen Test zu Modernizr hinzufügen möchten, würden Sie Folgendes tun:

Modernizr.addTest('regions', Modernizr.testAllProps('flow-into'));

Hoffentlich wird das in zukünftigen Versionen als Option hinzugefügt.

Dinge, die besser sein könnten

  • Ich wünschte, ich könnte Inhalte basierend darauf stylen, in welchen Container sie fließen. Das könnte problematisch sein, da ein anderer Stil in einem anderen Container zu einem Reflow führen könnte, der ihn aus diesem Container zurückdrängt und zu endlosen Schleifen führt, aber vielleicht gibt es dafür eine Lösung.
  • Ich wünschte, Block-Level-Elemente würden Block-Level-Elemente bleiben, auch mit der flow-from-Eigenschaft. Es ist seltsam, dass man ihnen width: 100% zuweisen muss.
  • Ich wünschte, height: auto; würde bei der Region mit dem letzten geflossenen Inhalt funktionieren. Ich verstehe, dass die meisten Flussregionen das nicht können, da sie sich sonst einfach ausdehnen würden, um den gesamten Inhalt aufzunehmen und den Fluss nicht fortsetzen, aber die letzte Region sollte wissen, was sie übrig hat und sich natürlich ausdehnen können.
  • Ich wünschte, man könnte flow-from und flow-into auf dasselbe Element anwenden. Auf diese Weise könnte ein semantisches Element die Quelle sein und nur wenn es schrumpft oder verschwindet, würden die anderen Regionen gefüllt.