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.
