Skip to content

Kapitel 10: Praxisprojekt - Blog-Theme erstellen

10.1 Anforderungsanalyse

Funktionale Anforderungen

  • ✅ Startseite mit Blog-Beiträgen
  • ✅ Einzelbeitragsseite
  • ✅ Statische Seiten (Über mich, Kontakt)
  • ✅ Sidebar mit Widgets
  • ✅ Responsive Design
  • ✅ Suchfunktion
  • ✅ Kommentare

Design-Anforderungen

  • ✅ Sauberes, modernes Design
  • ✅ Lesefreundliche Typografie
  • ✅ Kontrastreiche Farben
  • ✅ Mobile-optimiert

10.2 Schritt 1: Theme-Grundstruktur aufbauen

Ordnerstruktur

wp-content/themes/modern-blog/
├── style.css
├── index.php
├── header.php
├── footer.php
├── functions.php
├── single.php
├── page.php
├── archive.php
├── search.php
├── 404.php
├── sidebar.php
├── screenshot.png
├── css/
│   └── custom.css
├── js/
│   └── script.js
└── template-parts/
    ├── content.php
    ├── content-single.php
    └── content-page.php

10.3 Schritt 2: style.css mit Theme-Informationen

css
/*
Theme Name: Modern Blog
Theme URI: https://example.com/modern-blog/
Description: Ein modernes, responsives Blog-Theme
Author: Ihr Name
Author URI: https://example.com
Version: 1.0.0
Requires at least: WordPress 5.9
Tested up to: WordPress 6.4
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: modern-blog
Tags: blog, two-columns, right-sidebar, custom-colors, responsive-layout
*/

10.4 Schritt 3: functions.php erstellen

php
<?php
/**
 * Modern Blog - Funktionen
 */

function modern_blog_setup() {
    // Menüs registrieren
    register_nav_menus(array(
        'primary' => __('Hauptmenü', 'modern-blog'),
        'footer'  => __('Footer-Menü', 'modern-blog'),
    ));

    // Sidebar registrieren
    register_sidebar(array(
        'name'          => __('Sidebar', 'modern-blog'),
        'id'            => 'sidebar-1',
        'description'   => __('Hier Widgets hinzufügen.', 'modern-blog'),
        'before_widget' => '<section id="%1$s" class="widget %2$s">',
        'after_widget'  => '</section>',
        'before_title'  => '<h2 class="widget-title">',
        'after_title'   => '</h2>',
    ));

    // Beitragsbilder unterstützen
    add_theme_support('post-thumbnails');

    // Title-Tag unterstützen
    add_theme_support('title-tag');

    // HTML5-Markup
    add_theme_support('html5', array(
        'search-form',
        'comment-form',
        'comment-list',
        'gallery',
        'caption',
    ));
}
add_action('after_setup_theme', 'modern_blog_setup');

// Stylesheets und Skripte einbinden
function modern_blog_scripts() {
    // CSS
    wp_enqueue_style('modern-blog-style', get_stylesheet_uri(), array(), '1.0.0');
    wp_enqueue_style('modern-blog-custom', get_template_directory_uri() . '/css/custom.css', array(), '1.0.0');

    // JavaScript
    wp_enqueue_script('modern-blog-script', get_template_directory_uri() . '/js/script.js', array('jquery'), '1.0.0', true);

    // Kommentar-Reply-Skript
    if (is_singular() && comments_open() && get_option('thread_comments')) {
        wp_enqueue_script('comment-reply');
    }
}
add_action('wp_enqueue_scripts', 'modern_blog_scripts');
?>

10.5 Schritt 4: header.php erstellen

php
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
    <meta charset="<?php bloginfo('charset'); ?>">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?php wp_title('|', true, 'right'); ?></title>
    <link rel="profile" href="https://gmpg.org/xfn/11">
    <link rel="pingback" href="<?php bloginfo('pingback_url'); ?>">
    <?php wp_head(); ?>
</head>

<body <?php body_class(); ?>>
    <header id="masthead" class="site-header">
        <div class="container">
            <div class="site-branding">
                <?php if (has_custom_logo()) : ?>
                    <?php the_custom_logo(); ?>
                <?php else : ?>
                    <h1 class="site-title">
                        <a href="<?php echo esc_url(home_url('/')); ?>">
                            <?php bloginfo('name'); ?>
                        </a>
                    </h1>
                    <p class="site-description"><?php bloginfo('description'); ?></p>
                <?php endif; ?>
            </div>

            <nav id="site-navigation" class="main-navigation">
                <button class="menu-toggle" aria-controls="primary-menu" aria-expanded="false">
                    <span class="menu-icon"></span>
                    <span class="menu-text"><?php esc_html_e('Menü', 'modern-blog'); ?></span>
                </button>
                <?php
                wp_nav_menu(array(
                    'theme_location' => 'primary',
                    'menu_id'        => 'primary-menu',
                    'menu_class'     => 'nav-menu',
                    'container'      => false,
                ));
                ?>
            </nav>
        </div>
    </header>

    <div id="content" class="site-content">
        <div class="container">
php
            </div><!-- .container -->
        </div><!-- #content -->

        <footer id="colophon" class="site-footer">
            <div class="container">
                <div class="footer-widgets">
                    <?php if (is_active_sidebar('footer-1')) : ?>
                        <?php dynamic_sidebar('footer-1'); ?>
                    <?php endif; ?>
                </div>

                <div class="site-info">
                    © <?php echo date('Y'); ?> <?php bloginfo('name'); ?>.
                    Alle Rechte vorbehalten.
                </div>

                <?php if (has_nav_menu('footer')) : ?>
                    <nav class="footer-navigation">
                        <?php
                        wp_nav_menu(array(
                            'theme_location' => 'footer',
                            'menu_id'        => 'footer-menu',
                            'menu_class'     => 'footer-menu',
                            'depth'          => 1,
                        ));
                        ?>
                    </nav>
                <?php endif; ?>
            </div>
        </footer>
    </div>

    <?php wp_footer(); ?>
</body>
</html>

10.7 Schritt 6: index.php erstellen

php
<?php get_header(); ?>

    <div class="content-area">
        <main id="primary" class="site-main">
            <?php if (have_posts()) : ?>
                <header class="page-header">
                    <h1 class="page-title">
                        <?php
                        if (is_home() && !is_front_page()) {
                            single_post_title();
                        } else {
                            echo 'Blog';
                        }
                        ?>
                    </h1>
                </header>

                <div class="posts-grid">
                    <?php while (have_posts()) : the_post(); ?>
                        <?php get_template_part('template-parts/content', get_post_type()); ?>
                    <?php endwhile; ?>
                </div>

                <?php
                the_posts_pagination(array(
                    'mid_size'  => 2,
                    'prev_text' => '← ' . __('Zurück', 'modern-blog'),
                    'next_text' => __('Weiter', 'modern-blog') . ' →',
                ));
                ?>

            <?php else : ?>
                <p><?php _e('Keine Beiträge gefunden.', 'modern-blog'); ?></p>
            <?php endif; ?>
        </main>

        <?php get_sidebar(); ?>
    </div>

<?php get_footer(); ?>

10.8 Schritt 7: template-parts/content.php erstellen

php
<article id="post-<?php the_ID(); ?>" <?php post_class('post-card'); ?>>
    <?php if (has_post_thumbnail()) : ?>
        <div class="post-thumbnail">
            <a href="<?php the_permalink(); ?>">
                <?php the_post_thumbnail('medium'); ?>
            </a>
        </div>
    <?php endif; ?>

    <header class="entry-header">
        <h2 class="entry-title">
            <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
        </h2>

        <div class="entry-meta">
            <span class="posted-on">
                <time datetime="<?php echo get_the_date('c'); ?>">
                    <?php the_date(); ?>
                </time>
            </span>
            <span class="byline">
                von <?php the_author(); ?>
            </span>
        </div>
    </header>

    <div class="entry-excerpt">
        <?php the_excerpt(); ?>
    </div>

    <footer class="entry-footer">
        <a href="<?php the_permalink(); ?>" class="read-more">
            Weiterlesen
        </a>
    </footer>
</article>

10.9 Schritt 8: CSS für das Blog-Theme schreiben

Fügen Sie in css/custom.css hinzu:

css
/* === LAYOUT === */
.container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 20px;
}

.content-area {
    padding: 40px 0;
}

.site-content .container {
    display: flex;
    gap: 40px;
}

.site-main {
    flex: 1;
    min-width: 0;
}

.widget-area {
    width: 300px;
}

/* === HEADER === */
.site-header {
    background: white;
    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
    padding: 20px 0;
    position: sticky;
    top: 0;
    z-index: 1000;
}

.site-title {
    font-size: 2rem;
    margin: 0;
}

.site-title a {
    color: #1a73e8;
    text-decoration: none;
}

.site-description {
    color: #666;
    margin: 5px 0 0 0;
}

/* === NAVIGATION === */
.main-navigation {
    margin-top: 15px;
}

.menu-toggle {
    display: none;
    background: none;
    border: 1px solid #1a73e8;
    color: #1a73e8;
    padding: 8px 15px;
    cursor: pointer;
    border-radius: 4px;
}

.nav-menu {
    list-style: none;
    display: flex;
    gap: 20px;
    margin: 0;
    padding: 0;
}

.nav-menu a {
    color: #333;
    text-decoration: none;
    padding: 5px 0;
    display: block;
}

.nav-menu a:hover {
    color: #1a73e8;
}

/* === POSTS GRID === */
.posts-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 30px;
}

.post-card {
    background: white;
    border-radius: 8px;
    overflow: hidden;
    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
    transition: transform 0.3s ease;
}

.post-card:hover {
    transform: translateY(-5px);
}

.post-thumbnail img {
    width: 100%;
    height: 200px;
    object-fit: cover;
}

.entry-header {
    padding: 20px;
}

.entry-title {
    font-size: 1.3rem;
    margin: 0 0 10px 0;
}

.entry-title a {
    color: #333;
    text-decoration: none;
}

.entry-title a:hover {
    color: #1a73e8;
}

.entry-meta {
    color: #666;
    font-size: 0.9rem;
}

.entry-excerpt {
    padding: 0 20px 20px;
    color: #666;
}

.read-more {
    display: inline-block;
    margin: 0 20px 20px;
    color: #1a73e8;
    text-decoration: none;
    font-weight: bold;
}

/* === SIDEBAR === */
.widget {
    background: white;
    padding: 20px;
    margin-bottom: 20px;
    border-radius: 8px;
    box-shadow: 0 2px 5px rgba(0,0,0,0.05);
}

.widget-title {
    font-size: 1.2rem;
    margin-bottom: 15px;
    padding-bottom: 10px;
    border-bottom: 2px solid #1a73e8;
}

/* === FOOTER === */
.site-footer {
    background: #333;
    color: white;
    padding: 40px 0 20px;
    margin-top: 60px;
}

.footer-widgets {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 30px;
    margin-bottom: 30px;
}

.site-info {
    text-align: center;
    padding-top: 20px;
    border-top: 1px solid #555;
}

/* === RESPONSIVE === */
@media (max-width: 1024px) {
    .posts-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (max-width: 768px) {
    .site-content .container {
        flex-direction: column;
    }

    .widget-area {
        width: 100%;
    }

    .posts-grid {
        grid-template-columns: 1fr;
    }

    .menu-toggle {
        display: block;
    }

    .nav-menu {
        display: none;
        flex-direction: column;
    }

    .nav-menu.active {
        display: flex;
    }

    .footer-widgets {
        grid-template-columns: 1fr;
    }
}

10.10 Schritt 9: JavaScript für Mobile Navigation

Fügen Sie in js/script.js hinzu:

javascript
document.addEventListener('DOMContentLoaded', function() {
    const menuToggle = document.querySelector('.menu-toggle');
    const navMenu = document.querySelector('.nav-menu');

    if (menuToggle && navMenu) {
        menuToggle.addEventListener('click', function() {
            navMenu.classList.toggle('active');
            this.setAttribute('aria-expanded', navMenu.classList.contains('active'));
        });
    }
});

10.11 Schritt 10: Theme testen und debuggen

Test-Checkliste

  • [ ] Theme aktivieren (Design → Themes)
  • [ ] Startseite lädt korrekt
  • [ ] Beiträge werden angezeigt
  • [ ] Einzelbeitrag-Seite funktioniert
  • [ ] Seiten funktionieren
  • [ ] Navigation funktioniert
  • [ ] Sidebar zeigt Widgets an
  • [ ] Responsive Design auf Mobile
  • [ ] Suche funktioniert
  • [ ] Kommentare funktionieren

Häufige Fehler

Fehler: Styles werden nicht geladen Lösung: wp_head() in header.php prüfen

Fehler: Menü wird nicht angezeigt Lösung: Menü in functions.php registrieren und im Dashboard zuweisen


✅ Zusammenfassung

In diesem Kapitel haben Sie gelernt:

  • ✅ Ein vollständiges Blog-Theme zu planen
  • ✅ Alle Theme-Dateien zu erstellen
  • functions.php mit allen Funktionen zu schreiben
  • ✅ Ein responsives Design mit CSS zu erstellen
  • ✅ Das Theme zu testen

Nächstes Kapitel: Wir werden das Theme optimieren.

➡️ Zu Kapitel 11: Theme-Optimierung →

Frei für alle Anfänger