Ein Glossar mit PHP, HTML und CSS erstellen

CSS HTML

Ein Glossar ist ein Wörterverzeichnis zu einem bestimmten Themenbereich. Dabei werden Fachbegriffe alphabetisch aufgelistet und kurz erklärt. Ein Glossar kann unterschiedlich umgesetzt werden. Es besteht typischerweise jedoch aus einer Liste mit den Buchstaben A-Z und einer Definitionsliste mit den einzelnen Einträgen die zu den Buchstaben zugeordnet sind. In diesem Tutorial wird die Entwicklung eines Glossars mit PHP, HTML und CSS Schritt für Schritt beschrieben.

Demo

1) Das Datenmodell definieren

Zuerst überlegen wir uns was wir in dem Glossar darstellen wollen. Ein Glossar kann aus Begriffen bestimmte Fachbereiche bestehen. Zum Beispiel ein Glossar über Politik oder die Finanzfachwelt. Oder auch über Maschinenbau, Fahrzeugbegriffe oder eine Sammlung von Kochbegriffen. In unserem Glossar werden Fachbegriffe aus der Welt der Webentwicklung definiert. Dafür brauchen wir ein Datenmodell. Wir erstellen ein PHP-Array mit den einzelnen Einträgen. Dieses können wir später bei Bedarf einfach erweitern.
Die Daten des Glossars könnten genauso gut über eine Datenbank aus einem CMS oder eine API abgerufen werden. Der Einfachheit halber benutzen wir im Beispiel ein PHP-Array.



// file /data/glossary.php
return [
    [
        'name' => 'DOM',
        'text' => 'Abk. Document Object Model. Der Dokumentenbaum einer HTML-Struktur. Das DOM kann zur Laufzeit einer Website durch CSS und JavaScript verändert werden.'
    ],
    [
        'name' => 'Frontend',
        'text' => 'Einfach gesagt, der sichtbare Bereich einer Website der für den Endnutzer sichtbar, bzw. nutzbar ist. Auch der sichtbare Bereich eines CMS wird als Frontend bezeichnet.'
    ],
    [
        'name' => 'HTML',
        'text' => 'Abk. für "Hyper Text Markup Languange". Die XML-Sprache für Websites. Der semantische Grundaufbau von Websiten ist immer in HTML geschrieben.'
    ],
    [
        'name' => 'JavaScript',
        'text' => 'JavaScript hat nichts mit der Programmiersprache Java zu tun. Beide Sprachen basieren auf völlig unterschieldichen Technologie-Stacks'
    ],
    [
        'name' => 'PHP',
        'text' => 'beliebte CMS-Systeme wie WordPress, Drupal sind in PHP geschrieben. Auch Wikipedia oder MediaWiki nutzen PHP.'
    ],
];

2) PHP-Klasse Glossary.php erstellen

Im zweiten Schritt müssen wir die Daten irgendwie laden und auf der Website darstellen. Dazu erstellen wir uns die PHP-Klasse "Glossary".



// file Glossary.php
class Glossary2 {

    /**
     * @var array
     */
    protected $data = [];

    protected $glossaryList = [
        'a',
        'b',
        'c',
        'd',
        'e',
        'f',
        'g',
        'h',
        'i',
        'j',
        'k',
        'l',
        'm',
        'n',
        'o',
        'p',
        'q',
        'r',
        's',
        't',
        'u',
        'v',
        'w',
        'x',
        'y',
        'z'
    ];

    public function __construct()
    {
        $this->loadData();
    }

    public function loadData()
    {
        $this->data = include(APP_DIR . 'data/glossary.php');
    }

    public function getData(): array
    {
        $data = [];
        for ($i=0; $i<count($this->data); $i++) {
            $data[] = (object)$this->data[$i];
        }
        return $data;
    }

    public function getAlphabetList($exclude = []): array
    {
        return array_diff($this->glossaryList, $exclude);
    }

    public function isMatching(string $letter, $entry): bool {
        return strtolower($letter) === strtolower($entry->name[0]);
    }

    public function hasEntries($letter): bool {
        $entryExists = false;
        foreach ($this->getData() as $entry) {
            if (strtolower($entry->name[0]) === strtolower($letter)) {
                $entryExists = true;
                break;
            }
        }
        return $entryExists;
    }
}

3) Das Glossar mit HTML und CSS erstellen

Nachdem wir die Glossar-Daten definiert haben und unsere PHP-Klasse mit der dazugehörigen Logik implementiert haben müssen wir das Glossar im Frontend darstellen. Das machen wir mit HTML und CSS. Wir erstellen als erstes die Navigation des Glossars. Dann die Glossarliste und darin die einzelnen Einträge, jeweils alphabetisch angeordnet.

3.1) Die Glossar-Navigation

Für unsere Glossar-Navigation nutzen wir das HTML-Element <nav>. Mit $glossary->getAlphabetList() holen wir uns die einzelnen Buchstaben als Array. Dieses können wir durchiterieren und die einzelnen Buchstaben als Links <a> darstellen. Das Linkziel verweist auf den Eintrag des Buchstabens innerhalb der Glossarliste.


<nav class="glossary-nav">
    <?php foreach ($glossary->getAlphabetList() as $letter): ?>
        <a class="glossary-nav-item" href="#glossary-<?= $letter ?>"><?= $letter ?></a>
    <?php endforeach ?>
</nav>

Die Glossar-Navigation (.glossary-nav) stellen wir mit CSS Grid dar display: grid;. Durch die Eigenschaft grid-template-columns: repeat(auto-fit, minmax(32px, 1fr)); definieren wir das Grid Die Eigenschaft "auto-fit" legt fest, dass die Elemente des Grids immer die volle zur Verfügung stehende Breite nutzen sollen. Das ist wichtig für das responsive Verhalten der Seite. Die Columns bekommen eine Minimalbreite von 32px sodass sie nicht zu klein gedrückt werden. Bei kleineren Bildschirmgrößen rücken die Elemente automatisch in die nächste Zeile.

.glossary-nav {
    width: 100%;
    margin: 20px auto;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(32px, 1fr));
}
.glossary-nav-item {
    margin: 0 1px 2px 1px;
    padding: 6px;
    display: block;
    white-space: nowrap;
    color: white;
    text-align: center;
    background-color: #00a175;
    border-radius: 4px;
    text-decoration: none;
    text-transform: uppercase;
}
.glossary-nav-item:hover {
    color: white;
    background-color: #00513b;
    text-decoration: none;
}

Das Ergebnis sieht dann so aus:

Bei kleineren Bildschirmen brechen die Elemente der Navigation automatisch um und rücken in die nächste Zeile. Die einzelnen Elemente behalten aber die Mindestbreite von 32px bei:

3.2) Die Glossar-Liste

Als nächstes erstellen wir die Glossarliste mit den Einträgen. Diese wird alphabetisch von oben nach unten dargestellt. Wir definieren den Container .glossary-list mit der Headline <h3> die den darzustellenden Buchstaben enthält. Die Headline bekommt als id den gleichen Wert wie das href-Attribut im. Dadurch können die Headline angesteuert werden, wenn man oben in der Glossar-Navigation auf einen Eintrag klickt. Der Container .glossary-entries bekommt die einzelnen Eintrger des Glossars, die zu diesem Buchstaben passen. Zum Beispiel für den Buchstaben "C" würden die Einträge "CSS", "Client" oder "CORS" passen. Diese erstellen wir im nächsten Schritt.


<?php foreach ($glossary->getAlphabetList() as $letter): ?>
    <div class="glossary-list">
        <h3 class="glossary-headline" id="glossary-<?= $letter ?>">
            <?= $letter ?>
        </h3>
        <div class="glossary-entries">
            <!-- single glossary entry here -->
        </div>
    </div>
<?php endforeach ?>

3.3) Einen Glossar-Eintrag erstellen

Für die eiznelnen Einträge gibt es verschiene Möglichkeioten, Wir könnten einen <div> benutzen oder einen <span> oder ein normales Absatz-Element (Paragraph) <p> Wir können auber auch eine DefinitionList (<dl>) nutzen. Eine Definitionsliste besteht aus einem DefinitionTitle (<dt>) und einer DefinitionDescription (<dd>). Auf diese Weise können wir die einzelnen Einträge semantisch korrekt im Markup auszeichen statt sie einfach nur mit einem inhaltlich unaussagekräftigen div doer span zu markieren. Suchmaschinen können diese Struktur erkennen. Die Website wird dadurch praktisch inhaltlich und semantisch angereichert. Das ist der Sinn von HTML.

Beispiel des Glossar-Eintrags "CSS":


<dl class="definition" id="css">
    <dt class="definition-title"><strong>CSS</strong></dt>
    <dd class="definition-description">Is Somewhat great stuff.</dd>
</dl>

Zusammengesetzt mit PHP sieht die Glossarliste so aus:


<?php foreach ($glossary->getAlphabetList() as $letter): ?>
    <div class="glossary-list">
        <h3 class="glossary-headline" id="glossary-<?= $letter ?>">
            <?= $letter ?>
        </h3>
        <div class="glossary-entries">
            <?php foreach($glossary->getData() as $entry): ?>
                <?php if ($glossary->isMatching($letter, $entry)): ?>
                    <dl class="definition" id="<?= $entry->name ?>">
                        <dt class="definition-title"><strong><?= $entry->name ?></strong></dt>
                        <dd class="definition-description"><?= $entry->text ?></dd>
                    </dl>
                <?php endif ?>
            <?php endforeach;?>
        </div>
    </div>
<?php endforeach ?>

4) Handling about edge cases?

4.1) Glossar-Bereiche ohne Einträge herausfiltern

Manchmal kann es vorkommen, dass ein Glossar A-Z bei bestimmten Buchstaben keine Einträge hat. Begriffe die mit "Y" oder "Q" beginnen, gibt es eher selten. Deshalb wollen wir die Glossar-Navigation so erweitern, dass nur Buchstaben die auch Einträge haben hervorgehoben sind. Die anderen sollen ausgegraut werden.


<nav class="glossary-nav">
    <?php foreach ($glossary->getAlphabetList() as $letter): ?>
        <a class="glossary-nav-item <?= (!$glossary->hasEntries($letter)) ? 'inactive' : '' ?>" href="#glossary-<?= $letter ?>"><?= $letter ?></a>
    <?php endforeach ?>
</nav>

In Glossary.php wird die Methode hasEntries() implementiert, die prüft ob es für einen bestimmten Buchstaben Einträge gibt oder nicht. Falls es keine Einträge gibt, setzen wir für das .glossary-nav-item eine CSS-Klasse "inactive". Diese bekommt eine graue Hintergrundfarbe - fertig. Wir könnten die Einträge auch auf display: none; setzen oder sie direkt per PHP herausfiltern, sodass sie gar nicht erst im Frontend im Markup auftauchen. Damit könnten wir Code reduzieren und unnötige Leerstellen vermeiden und das wäre auch völlig in Ordnung. Wir würden aber damit auch den Eindruck vermitteln, dass das Glossar vollständig ist und alle Fachbegriffe in diesem Themenbereich abgedeckt sind. Für ein Glossar ist das aus meiner Sicht jedoch nie der Fall. Ein Glossar ist vermutlich nie komplett vollständig sondern es entwickelt sich. Daher sind Leereinträge auch völlig in Ordnung.

.glossary-nav-item.inactive {
    background-color: #e0e0e0;
}

4.2) Ziffern und Umlaute abbilden

Jetzt stellen wir uns die Frage was passiert eigentlich wenn die Glossar-Navigation nicht nur aus den Buchstaben A-Z bestehen sondern zum Beispiel auch Zahlen 0-9 enthalten sind. Was passiert wenn wir Einträge haben die mit "Ä" oder "Ö" beginnen? Im Prinzip relativ einfach. Wir müssen unser Array $glossaryList in der Glossary.php mit den entsprechenden Umlauten erweitern.

$glossaryList = [
    "0-1",
    "a",
    "ä",
    "b",
    "c",
    "d",
    // ...
]

Aber hoppla: Wenn wir das tun funktioniert unsere Methode isMatching() nicht mehr, da wir hier nur die Anfangsbuchstaben vergleichen aber keine Ziffern-Ranges. Wir müssen dafür die Methode ändern. Ein Möglichkeit wäre die Prüfung durch einen Regulären Ausdruck "RegEx" zu ersetzen. Mit Hilfe von preg_match() können wir ein pattern zu einem String validieren.
Im Beispiel unten würde der Wert preg_match("/^[0-9]$/", '2-Faktor-Authentifizierung'); korrekt validieren. Das Pattern sagt: Prüfe in der Zeichenkette "2-Faktor-Authentifizierung" ob das erste Zeichen einen Wert zwischen 0-9 hat. Die "2" fällt genau darunter.

public function isMatching(string $letter, $entry): bool {
    return preg_match("/^[". $letter ."]$/", strtolower($entry->name[0]));
}

Das "p" in "preg_match" steht vermutlich für das Wort "pattern". Aber ganz genau weiß man das bei den Funktionsbezeichnung in PHP leider nie :) In der Code-Dukumentation von PHP steht "Perform a regular expression match". Demnach könnte "p" also auch für "perform" stehen.

5) Mehr zum Thema



Artikel teilen