WordPress’te Sayfa Türüne Göre Body Class Ekleme

WordPress ile çalışırken, tema geliştirme sürecinin en can sıkıcı yanlarından biri farklı sayfa türleri için ayrı ayrı CSS yazmaya çalışmaktır. “Şu sayfada bu div gizlensin, bu sayfada şu renk değişsin” derken kendinizi body’e inline style eklerken ya da JavaScript ile class toggle yaparken bulursunuz. Oysa WordPress’in body_class filtresi tam da bu iş için tasarlanmış, son derece temiz bir çözüm sunuyor.

Bu yazıda, functions.php dosyasına ekleyeceğiniz birkaç fonksiyon ile sayfa türüne göre etiketine otomatik class eklemeyi, bunu gerçek dünya senaryolarıyla nasıl kullanacağınızı ve WooCommerce entegrasyonunu detaylıca ele alacağız.

Body Class Neden Önemli?

WordPress zaten varsayılan olarak body etiketine bazı class’lar ekler. Bir sayfayı browser’da inspect ettiğinizde şöyle bir şey görürsünüz:

<body class="page-template-default page page-id-42 logged-in admin-bar">

Bu class’lar şunları içerir: sayfa şablonu adı, post türü, sayfa ID’si, giriş durumu gibi bilgiler. Ancak bunlar her zaman yeterli olmaz. Özel iş mantığınıza göre ek class’lara ihtiyaç duyarsınız.

Örneğin:

  • Üyelik sisteminiz varsa, premium üyeler için ayrı bir görünüm
  • Belirli kategorideki yazılarda farklı bir sidebar
  • WooCommerce sepetinde ürün varsa özel bir banner gösterme
  • Kullanıcının dil tercihine göre RTL/LTR düzeni
  • A/B test senaryolarında farklı body class’ları

Tüm bunları body_class filtresiyle çok temiz bir şekilde halledebilirsiniz.

Temel Kullanım

functions.php dosyasına ekleyeceğiniz en basit body class fonksiyonu şöyle görünür:

add_filter( 'body_class', 'custom_body_classes' );

function custom_body_classes( $classes ) {
    // Tekil sayfalarda 'is-single' class'ı ekle
    if ( is_single() ) {
        $classes[] = 'is-single';
    }

    // Ön sayfada 'is-home-page' ekle
    if ( is_front_page() ) {
        $classes[] = 'is-home-page';
    }

    // Arşiv sayfalarında 'is-archive-page' ekle
    if ( is_archive() ) {
        $classes[] = 'is-archive-page';
    }

    return $classes;
}

Burada dikkat edilmesi gereken en kritik nokta: fonksiyonun mutlaka $classes array’ini return etmesi gerekiyor. Return etmeyi unutursanız body’nizde hiç class kalmaz ve tasarımınız dağılır. Bu hatayı en az bir kez yapmamış WordPress geliştiricisi yoktur.

Sayfa Türlerine Göre Detaylı Class Ekleme

Şimdi daha kapsamlı bir örnek yazalım. Gerçek bir projede kullanabileceğiniz, sayfa türlerini eksiksiz ele alan bir fonksiyon:

add_filter( 'body_class', 'sysadmin_extended_body_classes' );

function sysadmin_extended_body_classes( $classes ) {

    // Ana sayfa kontrolü
    if ( is_front_page() && is_home() ) {
        $classes[] = 'blog-front-page';
    } elseif ( is_front_page() ) {
        $classes[] = 'static-front-page';
    } elseif ( is_home() ) {
        $classes[] = 'blog-index-page';
    }

    // Sayfa hiyerarşisi kontrolü
    if ( is_page() ) {
        $page_id = get_the_ID();
        $parent_id = wp_get_post_parent_id( $page_id );

        if ( $parent_id ) {
            $classes[] = 'has-parent-page';
            $classes[] = 'parent-page-' . $parent_id;
        }

        // Alt sayfası olan sayfalar
        $children = get_pages( array( 'parent' => $page_id ) );
        if ( ! empty( $children ) ) {
            $classes[] = 'has-child-pages';
        }
    }

    // Kategori arşivi
    if ( is_category() ) {
        $category = get_queried_object();
        $classes[] = 'category-archive';
        $classes[] = 'category-' . $category->slug;
    }

    // Etiket arşivi
    if ( is_tag() ) {
        $tag = get_queried_object();
        $classes[] = 'tag-archive';
        $classes[] = 'tag-' . $tag->slug;
    }

    // Yazar arşivi
    if ( is_author() ) {
        $author = get_queried_object();
        $classes[] = 'author-archive';
        if ( user_can( $author->ID, 'administrator' ) ) {
            $classes[] = 'author-is-admin';
        }
    }

    // Arama sonuçları
    if ( is_search() ) {
        $classes[] = 'search-results-page';
        if ( have_posts() ) {
            $classes[] = 'search-has-results';
        } else {
            $classes[] = 'search-no-results';
        }
    }

    // 404 sayfası
    if ( is_404() ) {
        $classes[] = 'error-404';
        $classes[] = 'not-found-page';
    }

    return $classes;
}

Bu fonksiyonla artık CSS’inizde şöyle şeyler yazabilirsiniz:

/* Sadece blog anasayfasında görünsün */
.blog-front-page .hero-section {
    display: block;
}

/* Arama sonucu yoksa özel mesaj */
.search-no-results .custom-search-message {
    display: block;
}

/* Admin olan yazarların sayfasında özel badge */
.author-is-admin .author-badge {
    visibility: visible;
}

Özel Post Type’lara Göre Class Ekleme

Eğer custom post type’larla çalışıyorsanız, her post type için ayrı body class mantığı kurmanız gerekir:

add_filter( 'body_class', 'custom_post_type_body_classes' );

function custom_post_type_body_classes( $classes ) {
    // Custom post type kontrolü
    $post_type = get_post_type();

    if ( $post_type && ! is_archive() ) {
        // Her custom post type için prefix ekle
        $classes[] = 'cpt-' . $post_type;
    }

    // Özel post type: 'portfolio'
    if ( is_singular( 'portfolio' ) ) {
        $portfolio_type = get_post_meta( get_the_ID(), 'portfolio_type', true );
        if ( $portfolio_type ) {
            $classes[] = 'portfolio-type-' . sanitize_html_class( $portfolio_type );
        }
    }

    // Özel post type: 'hizmet' (services)
    if ( is_singular( 'hizmet' ) ) {
        $classes[] = 'hizmet-detay';

        // Bu hizmetin fiyat aralığı
        $price_range = get_post_meta( get_the_ID(), 'price_range', true );
        if ( in_array( $price_range, array( 'low', 'medium', 'high', 'enterprise' ) ) ) {
            $classes[] = 'price-range-' . $price_range;
        }
    }

    // Custom taxonomy arşivleri
    if ( is_tax( 'proje_kategorisi' ) ) {
        $term = get_queried_object();
        $classes[] = 'proje-kategorisi-arsiv';
        $classes[] = 'proje-kat-' . $term->slug;
    }

    return $classes;
}

Kullanıcı Durumuna Göre Class Ekleme

Üyelik sitelerinde veya abonelik sistemlerinde kullanıcının durumunu body class olarak yansıtmak son derece pratiktir. Özellikle “premium içerik” veya “reklamsız deneyim” gibi senaryolarda çok işe yarar:

add_filter( 'body_class', 'user_status_body_classes' );

function user_status_body_classes( $classes ) {

    if ( is_user_logged_in() ) {
        $user = wp_get_current_user();

        // Kullanıcı rolü class'ı
        foreach ( $user->roles as $role ) {
            $classes[] = 'user-role-' . sanitize_html_class( $role );
        }

        // Premium üye kontrolü (örnek: user meta ile)
        $is_premium = get_user_meta( $user->ID, 'is_premium_member', true );
        if ( $is_premium ) {
            $classes[] = 'premium-user';
            $classes[] = 'no-ads';
        } else {
            $classes[] = 'free-user';
            $classes[] = 'show-ads';
        }

        // Kullanıcının profil tamamlanma durumu
        $profile_complete = get_user_meta( $user->ID, 'profile_completed', true );
        if ( ! $profile_complete ) {
            $classes[] = 'profile-incomplete';
        }

        // İlk giriş mi? (signup sonrası ilk 24 saat)
        $user_registered = strtotime( $user->user_registered );
        if ( ( time() - $user_registered ) < 86400 ) {
            $classes[] = 'new-user';
        }

    } else {
        $classes[] = 'not-logged-in';
        $classes[] = 'guest-user';
    }

    return $classes;
}

Artık CSS’inizde şunu yazabilirsiniz:

/* Misafir kullanıcılara reklam göster */
.guest-user .ad-banner { display: block; }

/* Premium kullanıcılara reklam gösterme */
.premium-user .ad-banner { display: none !important; }

/* Yeni kullanıcılara hoşgeldin mesajı */
.new-user .welcome-message { display: flex; }

/* Profili tamamlanmamış kullanıcılara uyarı */
.profile-incomplete .header-warning { display: block; }

WooCommerce ile Entegrasyon

WooCommerce zaten kendi body class’larını ekler, ancak daha ince ayarlı kontrol için custom class’lara ihtiyaç duyarsınız. Özellikle sepet ve ödeme akışında:

add_filter( 'body_class', 'woocommerce_custom_body_classes' );

function woocommerce_custom_body_classes( $classes ) {

    // WooCommerce aktif mi kontrol et
    if ( ! class_exists( 'WooCommerce' ) ) {
        return $classes;
    }

    // Sepette ürün var mı?
    if ( WC()->cart && ! WC()->cart->is_empty() ) {
        $classes[] = 'cart-has-items';
        $item_count = WC()->cart->get_cart_contents_count();

        // Sepet boyutuna göre class
        if ( $item_count >= 10 ) {
            $classes[] = 'cart-large';
        } elseif ( $item_count >= 5 ) {
            $classes[] = 'cart-medium';
        } else {
            $classes[] = 'cart-small';
        }
    } else {
        $classes[] = 'cart-empty';
    }

    // Ödeme sayfasında ekstra class'lar
    if ( is_checkout() ) {
        // Kupon uygulanmış mı?
        $applied_coupons = WC()->cart->get_applied_coupons();
        if ( ! empty( $applied_coupons ) ) {
            $classes[] = 'checkout-has-coupon';
        }

        // Ücretsiz kargo eşiği aşıldı mı?
        $subtotal = WC()->cart->get_subtotal();
        $free_shipping_threshold = 500; // TL cinsinden
        if ( $subtotal >= $free_shipping_threshold ) {
            $classes[] = 'checkout-free-shipping';
        }
    }

    // Ürün sayfasında stok durumu
    if ( is_product() ) {
        global $product;
        if ( $product ) {
            if ( $product->is_in_stock() ) {
                $classes[] = 'product-in-stock';
            } else {
                $classes[] = 'product-out-of-stock';
            }

            // Ürün tipi
            $classes[] = 'product-type-' . $product->get_type();

            // İndirimde mi?
            if ( $product->is_on_sale() ) {
                $classes[] = 'product-on-sale';
            }
        }
    }

    // Hesap sayfalarında sekme bilgisi
    if ( is_account_page() && is_user_logged_in() ) {
        $current_endpoint = WC()->query->get_current_endpoint();
        if ( $current_endpoint ) {
            $classes[] = 'account-section-' . sanitize_html_class( $current_endpoint );
        }
    }

    return $classes;
}

Sayfa Şablonuna Göre Class Ekleme

Özel page template kullanıyorsanız, şablon adını da body class olarak almak düzeni kolaylaştırır:

add_filter( 'body_class', 'template_name_body_class' );

function template_name_body_class( $classes ) {

    if ( is_page() ) {
        // Kullanılan sayfa şablonunu al
        $template = get_page_template_slug();

        if ( $template ) {
            // template-landing-page.php -> landing-page
            $template_class = str_replace(
                array( 'template-', '.php', '/' ),
                array( '', '', '-' ),
                $template
            );
            $classes[] = 'tmpl-' . sanitize_html_class( $template_class );
        }

        // Belirli şablonlar için özel class'lar
        if ( is_page_template( 'template-full-width.php' ) ) {
            $classes[] = 'layout-full-width';
            $classes[] = 'no-sidebar';
        }

        if ( is_page_template( 'template-landing.php' ) ) {
            $classes[] = 'layout-landing';
            $classes[] = 'hide-header-nav';
            $classes[] = 'hide-footer-widgets';
        }

        if ( is_page_template( 'template-contact.php' ) ) {
            $classes[] = 'has-contact-form';
            $classes[] = 'layout-two-column';
        }
    }

    return $classes;
}

Cihaz ve Tarayıcı Bazlı Class Ekleme

Bazen kullanıcının cihazına göre de farklı görünümler gerekir. PHP tarafında User Agent’tan bu bilgiyi çekip body class olarak ekleyebilirsiniz:

add_filter( 'body_class', 'device_type_body_classes' );

function device_type_body_classes( $classes ) {

    if ( ! isset( $_SERVER['HTTP_USER_AGENT'] ) ) {
        return $classes;
    }

    $user_agent = sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] );

    // Mobil cihaz kontrolü
    $mobile_agents = array(
        'iPhone', 'iPod', 'Android', 'BlackBerry',
        'Windows Phone', 'webOS', 'Opera Mini', 'Mobile'
    );

    $is_mobile = false;
    foreach ( $mobile_agents as $agent ) {
        if ( stripos( $user_agent, $agent ) !== false ) {
            $is_mobile = true;
            break;
        }
    }

    if ( $is_mobile ) {
        $classes[] = 'device-mobile';
    }

    // Tablet kontrolü
    if ( stripos( $user_agent, 'iPad' ) !== false ||
        ( stripos( $user_agent, 'Android' ) !== false &&
          stripos( $user_agent, 'Mobile' ) === false ) ) {
        $classes[] = 'device-tablet';
    }

    // iOS kontrolü
    if ( stripos( $user_agent, 'iPhone' ) !== false ||
         stripos( $user_agent, 'iPad' ) !== false ||
         stripos( $user_agent, 'iPod' ) !== false ) {
        $classes[] = 'os-ios';
    }

    // Android kontrolü
    if ( stripos( $user_agent, 'Android' ) !== false ) {
        $classes[] = 'os-android';
    }

    return $classes;
}

Not: Günümüzde cihaz tespiti için PHP User Agent yaklaşımı yerine CSS media query veya JavaScript kullanmak daha sağlıklıdır. Bu fonksiyon yalnızca PHP tarafında kesinlikle yapılması gereken işlemler için referans alınabilir.

Tüm Fonksiyonları Birleştirme

Büyük projelerde bu fonksiyonları ayrı dosyalara bölmek iyi bir pratiktir. functions.php dosyanızda şu şekilde organize edebilirsiniz:

// functions.php

// Body class dosyasını dahil et
require_once get_template_directory() . '/inc/body-classes.php';

inc/body-classes.php dosyasında ise tüm class fonksiyonlarını tek bir ana fonksiyon altında toplayabilirsiniz:

<?php
// inc/body-classes.php

if ( ! function_exists( 'site_body_classes_master' ) ) {

    add_filter( 'body_class', 'site_body_classes_master', 20 );

    function site_body_classes_master( $classes ) {
        // Sayfa türü class'ları
        $classes = site_page_type_classes( $classes );

        // Kullanıcı durumu class'ları
        $classes = site_user_status_classes( $classes );

        // WooCommerce class'ları (sadece WC aktifse)
        if ( class_exists( 'WooCommerce' ) ) {
            $classes = site_woocommerce_classes( $classes );
        }

        // Temizlik: boş ve duplicate class'ları kaldır
        $classes = array_filter( $classes );
        $classes = array_unique( $classes );

        return $classes;
    }
}

function site_page_type_classes( $classes ) {
    if ( is_front_page() ) {
        $classes[] = 'is-front-page';
    }
    if ( is_404() ) {
        $classes[] = 'is-404';
    }
    if ( is_search() ) {
        $classes[] = 'is-search';
        $classes[] = have_posts() ? 'search-found' : 'search-not-found';
    }
    return $classes;
}

function site_user_status_classes( $classes ) {
    $classes[] = is_user_logged_in() ? 'user-logged-in' : 'user-guest';
    return $classes;
}

function site_woocommerce_classes( $classes ) {
    if ( WC()->cart && ! WC()->cart->is_empty() ) {
        $classes[] = 'has-cart-items';
    }
    return $classes;
}

array_unique() ve array_filter() kullanımına dikkat edin. Birden fazla plugin veya child theme fonksiyonu aynı class’ı ekleyebilir, duplicate class’lar hem HTML’i kirletir hem de bazen beklenmedik CSS özgüllük sorunlarına neden olur.

Güvenlik ve Performans

Body class fonksiyonları her sayfa yüklemesinde çalışır, bu yüzden performansa dikkat etmek gerekir.

  • Ağır sorgulardan kaçının: Body class fonksiyonu içinde karmaşık WP_Query çağrıları yapmayın. Eğer yapmanız gerekiyorsa sonucu transient ile cache’leyin.
  • Sanitize edin: Kullanıcı girdisinden gelen herhangi bir değeri sanitize_html_class() ile temizleyin.
  • Erken return kullanın: Koşul sağlanmıyorsa gereksiz kodu çalıştırmayın.
  • Priority değerini ayarlayın: add_filter( 'body_class', 'fonksiyon', 20 ) şeklinde priority 20 ile eklerseniz, diğer plugin’lerin eklediği class’lardan sonra çalışırsınız ve onları override edebilirsiniz.

Sonuç

body_class filtresi, WordPress tema geliştirmede en underrated araçlardan biri. Bir kez alışkanlık haline getirdiğinizde, JavaScript ile DOM manipülasyonuna, inline style’a ya da karmaşık PHP koşullarına template dosyaları içinde ihtiyaç duymaktan çıkıyorsunuz.

Temanızın tüm görsel mantığını CSS’e taşımak, hem bakım kolaylığı sağlar hem de tasarımcılarla iş birliğini çok daha kolay hale getirir. Tasarımcı “şu sayfada şu element görünmesin” dediğinde tek yapmanız gereken o sayfanın body class’ını öğrenip birkaç satır CSS yazmak oluyor.

Özellikle WooCommerce projelerinde sepet durumu, ürün stok bilgisi ve kullanıcı üyelik seviyesine göre body class eklemek, karmaşık conditional PHP bloklarından kurtulmanızı sağlar. Kodu çok daha temiz ve test edilebilir hale getirir.

Son olarak: Bu teknikleri uygulamaya başlamadan önce mevcut theme’inizin body_class filter’ına ne eklediğini inceleyin. Bir browser’da inspect element ile body tag’ine bakın ve üzerine ne inşa edeceğinizi planlayın. Sonra functions.php’ye koyduğunuz her fonksiyonun production’da çalışmadan önce staging ortamında test edildiğinden emin olun.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir