Wie versprochen gibt es diese Woche einen Ausflug in die Welt von Less im produktiven Einsatz so wie einem responsive Layout (inklusive ein paar Zeilen Javascript).

Ich wollte für dieses Projekt zwar unbedingt Less benutzen, konnte aber leider nicht „das“ rausholen was ich erhofft habe – Ich nutze bisher nur etwa fünf Variablen (für verschiedene Farben) und ein Mixin für die Schatten.
Generell ist das CSS relativ schlank – Doch das ist bei dem Layout auch kein großes Wunder 😉 Schließlich ging es mir um ein sauberes Layout ohne viele Grafiken oder Spielereien… Da ist so eine „knapp-200-Zeilen-CSS“-Datei nichts ungewöhnliches.

Starten wir doch direkt mit dem „globalen“ Styling – Als aller erstes binde ich einige modifizierte Reset-CSS Regeln ein (im Original vom 1140 Grid)…

html,body,div,span,object,iframe,h1,h2,h3,h4,h5,h6,hr,p,blockquote,pre,a,abbr,address,cite,code,del,dfn,em,img,ins,q,small,strong,sub,sup,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td {margin:0;padding:0;border:0;}
article,aside,figure,figure img,figcaption,hgroup,footer,header,nav,section,video,object {display:block}
table {border-collapse:collapse;border-spacing:0;}
ol,ul,li {list-style:none;}
h1,h2,h3,h4,h5,h6 {font-size:100%;font-weight:normal;}
q:before,q:after {content:'';}
a {text-decoration: none;}
a img{border:0;}

Gefolgt von einer Font-Face definition für die schöne „Titillium“ Schriftart.

@font-face {
    font-family: 'Titillium';
    src: url('../font/TitilliumText22L003-webfont.eot');
    src: url('../font/TitilliumText22L003-webfont.eot?#iefix') format('embedded-opentype'),
        url('../font/TitilliumText22L003-webfont.woff') format('woff'),
        url('../font/TitilliumText22L003-webfont.ttf') format('truetype'),
        url('../font/TitilliumText22L003-webfont.svg#TitilliumText22LThin') format('svg');
    font-weight: normal;
    font-style: normal;
    -webkit-font-smoothing: antialiased;
}

Und schließlich das Seitenlayout selbst:
Die Seite wird immer zentriert dargestellt, mit einer maximalen Breite von bis zu 900 Pixel. Die Zentrierung bleibt, bis die Browser-breite die 767 Pixel Marke unterschreitet – ab diesem Punkt wird die Seite Randlos dargestellt (Die Schlüssel-Maße 1023px und 767px kommen ebenfalls vom 1140 Grid):

.container {
    width: 900px;
    margin: 20px auto;
    padding: 20px 0;
    background: @box;
    
    .shadow_inset() /* Schatten mixin */
}

/* ... */

@media only screen and (max-width: 1023px) {
    .container {
        width: 700px;
        margin: 10px auto;
        padding: 10px 0;
    }
}

/* ... */

@media handheld, only screen and (max-width: 767px) {
    .container {
        width: 100%;
    }
}

(Der Code-Highlighter kommt leider mit Less nicht klar…)

In der Praxis schaut das ganze dann folgendermaßen aus:

Die Balken-Diagramme habe ich hier ausgeblendet, da diese nicht besonders spannend sind 😉 Die Galerie verfügt allerdings über ein kleines Feature: Während bei den Versionen von ∞ – 1024 Pixel die Galerie dreispaltig dargestellt wird, wird in der Größe von 1023 – 768 Pixel das Raster Zweispaltig. Unterhalb der 550 Pixel Grenze werden die Thumbs dann einspaltig präsentiert!

Dieses Verhalten ist leider nicht so einfach mit reinem CSS abbildbar, da die einzelnen Bild-Elemente mit einem margin ausgestattet sind. Das jeweils letzte Element pro Zeile bekommt außerdem eine „last“ CSS Klasse, um das rechte margin auf 0 zu setzen:

.container .threecol {
    width: 30.75%;
    margin-right: 3.8%;
    float: left;
}

.container .last {
    margin-right: 0;
}

Markieren wir das margin blau, sieht das ganze in etwa so aus:
Während wir also die breite der Galerie-Elemente einfach per Media-Query von 30.75% auf 48% setzen benötigen wir eine andere Lösung für das Umsetzen der „last“ Klasse.

Das HTML ist relativ schlank und arbeitet mit einzelnen DIV-Containern.

<section class="gallery">
    <h2>Projects</h2>
    <div class="threecol" style="background:url('tpl/projects/thumb_00.jpg');"></div>
    <div class="threecol" style="background:url('tpl/projects/thumb_00.jpg');"></div>
    <div class="threecol" style="background:url('tpl/projects/thumb_00.jpg');"></div>
    <div class="threecol" style="background:url('tpl/projects/thumb_00.jpg');"></div>
    <div class="threecol" style="background:url('tpl/projects/thumb_00.jpg');"></div>
    <div class="threecol" style="background:url('tpl/projects/thumb_00.jpg');"></div>
    <br class="cb" />
</section>

Die Lösung des Problems lautet, wie so oft: jQuery!
Ähnlich wie Adapt.js werden wir mit Hilfe eines „onResize“ Observer beobachten ab wann die „last“ Klasse umgesetzt werden muss. Daraus hat sich dieser Code ergeben:

// Definition einiger Variablen
var x, state, prev_state = 'x';

// Funktion zum setzen von "state" und rufen der "responsive"-Funktion.
window.browsersize = function () {
    x = $(window).width();

    if (x < 550) {
        state = 'd';
    } else if (x <= 767) {
        state = 'c';
    } else if (x <= 1023) {
        state = 'b';
    } else {
        state = 'a';
    }

    /* Wir wollen die "responsive"-Funktion nur rufen, wenn von einer
     * Responsive-Größe auf eine andere gewechselt wurde.
     */
    if (prev_state != state) {
        window.responsive();
        prev_state = state;
    }
};

// Responsive-Funktion zum setzen verschiedener Styles.
window.responsive = function () {
    // Zuerst setzen entfernen wir alle "last" CSS-Klassen und iterieren über die Elemente.
    $('section.gallery div.threecol').removeClass('last').each(function (i, el) {
        ++i;
        switch (state) {
            case 'c':
                // Jedes zweite Element bekommt die "last" CSS-Klasse.
                if (! (i%2)) {
                    $(el).addClass('last');
                }
                break;

            case 'b':
            case 'a':
                // Jedes dritte Element bekommt die "last" CSS-Klasse.
                if (! (i%3)) {
                    $(el).addClass('last');
                }
                break;
        }
    });
};

$(document).ready(function() {
    // Initialer Aufruf der "browsersize"-Funktion.
    window.browsersize();
    // Setzen des Observers.
    $(window).on('resize', window.browsersize);
});

Das schaut doch schon ganz gut aus und funktioniert einwandfrei! Durch die "responsive"-Funktion ist es uns außerdem möglich diverse Aktionen durchzuführen, sobald zwischen zwei Responsive-Schritten gewechselt wird.
Und das war auch schon der ganze Zauber um Less, CSS und das responsive Verhalten!

Damit möchte ich zum letzten Punkt für Heute kommen: Anlegen weiterer Seiten
Eine neue Seite anlegen ist wirklich sehr schnell getan und beansprucht nur wenige Minuten:

$app->get('/', function () use ($app) {
    // Startseite...
});

// Eine weitere Seite für das Impressum
$app->get('/imprint', function () use ($app) {
    $structure = Structure::factory($app->view())
        ->add('text', array(
            'headline' => 'Imprint',
            'paragraphs' => array(
                'This page represents the imprint' // ...
            )
        ));
});

// Ein Post Request für das Anfordern einer Projekt-Detailseite via Ajax.
$app->post('/project/:project', function ($project) use ($app) {
    // ":project" ist ein Platzhalter in der URL, dessen Wert als Parameter übergeben wird.
    $structure = Structure::factory($app->view())
        ->add('image', array(
            // ...
        ));
});

Wie ich diesen Post-Request genau anfordere und anschließend auswerte erfahren wir nächste Woche 😉

Bis dahin wünsche ich euch eine angenehme Woche und Happy Coding!

One comment on “Das eigene kleine Portfolio mit dem Slim Framework, RainTPL & Co. – Teil 4

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.