Nowoczesna nawigacja po wpisach na stronie WordPress
Dobrze zorganizowana lista artykułów to ogromna zaleta każdej witryny. Szczególnie wtedy, gdy prezentujemy dużą ilość treści. Dzięki prostemu kodowi możesz wyświetlić wszystkie wpisy blogowe na jednej stronie. Dodatkowo użytkownik może filtrować je według kategorii i przeszukiwać tytuły wpisów. Takie rozwiązanie zapewnia większy komfort dla czytelnika i jednocześnie podnosi jakość UX.
Zastosowanie funkcji AJAX pozwala na dynamiczne filtrowanie zawartości bez przeładowywania strony. To sprawia, że przeglądanie postów staje się szybsze i bardziej płynne. Co ważne, użytkownik widzi wyniki od razu, co zwiększa jego zaangażowanie.
Cały mechanizm działa w pełni responsywnie – wygląda dobrze zarówno na komputerach, jak i na urządzeniach mobilnych. W wersji mobilnej zastosowano akordeon, który ukrywa przyciski kategorii. Dzięki temu nie zajmują one zbyt dużo miejsca na ekranie.
Szybkie filtrowanie dzięki dynamicznemu kodowi
Zamiast sięgać po kolejne wtyczki, warto samodzielnie wdrożyć filtr postów WordPress. Kod, który prezentujemy, oparty jest o prosty shortcode. Dzięki niemu możesz dodać system przeszukiwania i filtrowania w dowolnym miejscu strony.
Shortcode ten wykorzystuje wewnętrzne mechanizmy WordPressa oraz AJAX. Działa płynnie i eliminuje konieczność ładowania kolejnych podstron. Całość została przygotowana tak, by była łatwa w dostosowaniu do indywidualnych potrzeb strony.
Co więcej, styl CSS również uwzględnia różne rozdzielczości ekranu. Dzięki temu nie musisz martwić się o mobilną wersję witryny. Wszystko wygląda spójnie i działa poprawnie.
Dlaczego warto zastosować tę funkcję
Z technicznego punktu widzenia, filtr postów WordPress poprawia dostępność treści. Z punktu widzenia użytkownika natomiast – daje możliwość szybkiego dotarcia do interesujących wpisów. To ważne, szczególnie na stronach z dużą ilością treści blogowych lub poradnikowych.
Nie musisz być programistą, by wdrożyć takie rozwiązanie. Wystarczy, że skopiujesz kod i wkleisz go do pliku functions.php lub do wtyczki Code Snippets. Następnie użyj shortcode’a [ostatnie_wpisy] w wybranym miejscu.
// 1. Shortcode – zachowujemy oryginalną nazwę: [ostatnie_wpisy] function custom_recent_posts_shortcode() { ob_start(); ?> <!-- NOWE: Filtry kategorii z akordeonem mobilnym --> <?php $categories = get_categories(array( 'hide_empty' => true, 'exclude' => array(103) )); ?> <style> @media (max-width: 768px) { #category-accordion-toggle { display: flex; justify-content: space-between; align-items: center; padding: 10px 15px; background: #f1f1f1; cursor: pointer; border: 1px solid #ddd; margin-bottom: 10px; } #category-accordion-toggle span { font-weight: bold; } #category-accordion-toggle .arrow { transition: transform 0.3s; } #category-accordion-toggle.active .arrow { transform: rotate(180deg); } #custom-category-buttons { display: none; flex-direction: column; gap: 10px; margin-bottom: 20px; } #custom-category-buttons.show { display: flex; } .category-filter-btn { width: 100%; text-align: left; } } @media (min-width: 769px) { #category-accordion-toggle { display: none; } #custom-category-buttons { display: flex !important; flex-wrap: wrap; gap: 10px; margin-bottom: 20px; } } </style> <div id="category-accordion-toggle"> <span>Kategorie</span> <span class="arrow">▼</span> </div> <div id="custom-category-buttons"> <button class="category-filter-btn active" data-category="all" style="padding: 8px 15px;">Wszystkie</button> <?php foreach ($categories as $category): ?> <button class="category-filter-btn" data-category="<?php echo esc_attr($category->term_id); ?>" style="padding: 8px 15px;"><?php echo esc_html($category->name); ?></button> <?php endforeach; ?> </div> <script> document.addEventListener('DOMContentLoaded', function () { const toggle = document.getElementById('category-accordion-toggle'); const categoryList = document.getElementById('custom-category-buttons'); if (toggle && categoryList) { toggle.addEventListener('click', function () { toggle.classList.toggle('active'); categoryList.classList.toggle('show'); }); } }); </script> <div id="custom-post-search" style="margin-bottom: 20px;"> <input type="text" id="search-input" placeholder="Szukaj po tytule..." style="width: 100%; padding: 10px; font-size: 1em;" /> </div> <div id="custom-post-list"> <?php echo get_custom_all_posts_html(); ?> </div> <?php return ob_get_clean(); } add_shortcode('ostatnie_wpisy', 'custom_recent_posts_shortcode'); // 2. Funkcja do pobierania WSZYSTKICH wpisów function get_custom_all_posts_html() { $args = array( 'post_type' => 'post', 'posts_per_page' => -1, 'post_status' => 'publish', 'orderby' => 'date', 'order' => 'DESC' ); $query = new WP_Query($args); $total_posts = $query->found_posts; ob_start(); if ($query->have_posts()) { $i = 0; while ($query->have_posts()) { $query->the_post(); $i++; $post_number = $total_posts - $i + 1; ?> <div class="custom-post-item" style="display: flex; margin-bottom: 20px;"> <div class="custom-post-image" style="width: 40%; margin-right: 20px;"> <?php the_post_thumbnail('full'); ?> </div> <div class="custom-post-content" style="width: 60%;"> <?php $categories = get_the_category(); if (!empty($categories)) { echo '<div class="kategoria-wpisu" style="font-size: 0.85em; color: #777; margin-bottom: 5px;">Kategoria:<b> ' . esc_html($categories[0]->name) . '</b></div>'; } ?> <div class="tytul-wpisu"> <h2 style="margin-top: 0;"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2> </div> <div class="streszczenie-wpisu"> <p><?php echo wp_trim_words(get_the_excerpt(), 25, ' [...]'); ?></p> </div> <div class="data-i-godzina-wpisu"> <p style="font-size: 0.9em; color: #555;">Autor: <?php the_author(); ?> | <?php the_time('d.m.Y H:i'); ?></p> </div> <div class="czytajwiecej" style="margin-top: 10px;"> <a class="czytaj-wiecej" href="<?php the_permalink(); ?>" style="display: inline-block;">Czytaj więcej</a> <span style="margin-left: 10px; font-size: 0.9em; color: #999;">Post #<?php echo $post_number; ?></span> </div> </div> </div> <?php } } wp_reset_postdata(); return ob_get_clean(); } // 3. JavaScript – live search + filtr kategorii function custom_search_script() { ?> <script> document.addEventListener('DOMContentLoaded', function() { const searchInput = document.getElementById('search-input'); const filterPosts = (categoryId, searchText) => { const data = new FormData(); data.append('action', 'filter_posts'); data.append('category_id', categoryId); data.append('search_text', searchText); fetch('<?php echo admin_url("admin-ajax.php"); ?>', { method: 'POST', body: data }) .then(response => response.text()) .then(html => { document.getElementById('custom-post-list').innerHTML = html; }); }; document.querySelectorAll('.category-filter-btn').forEach(button => { button.addEventListener('click', function() { document.querySelectorAll('.category-filter-btn').forEach(btn => btn.classList.remove('active')); this.classList.add('active'); const catId = this.dataset.category; const searchText = searchInput?.value || ''; filterPosts(catId, searchText); }); }); if (searchInput) { searchInput.addEventListener('input', function() { const activeBtn = document.querySelector('.category-filter-btn.active'); const categoryId = activeBtn ? activeBtn.dataset.category : 'all'; filterPosts(categoryId, this.value); }); } }); </script> <?php } add_action('wp_footer', 'custom_search_script'); // 4. AJAX backend handler (filtrowanie postów) add_action('wp_ajax_filter_posts', 'ajax_filter_posts_callback'); add_action('wp_ajax_nopriv_filter_posts', 'ajax_filter_posts_callback'); function ajax_filter_posts_callback() { $cat_id = sanitize_text_field($_POST['category_id']); $search = sanitize_text_field($_POST['search_text']); $args = array( 'post_type' => 'post', 'posts_per_page' => -1, 'post_status' => 'publish', 'orderby' => 'date', 'order' => 'DESC', ); if ($cat_id && $cat_id !== 'all') { $args['cat'] = intval($cat_id); } if (!empty($search)) { $args['s'] = $search; } $query = new WP_Query($args); $total = $query->found_posts; $i = 0; if ($query->have_posts()) { ob_start(); while ($query->have_posts()) { $query->the_post(); $i++; $post_number = $total - $i + 1; ?> <div class="custom-post-item" style="display: flex; margin-bottom: 20px;"> <div class="custom-post-image" style="width: 40%; margin-right: 20px;"> <?php the_post_thumbnail('full'); ?> </div> <div class="custom-post-content" style="width: 60%;"> <?php $categories = get_the_category(); if (!empty($categories)) { echo '<div class="kategoria-wpisu" style="font-size: 0.85em; color: #777; margin-bottom: 5px;">Kategoria:<b> ' . esc_html($categories[0]->name) . '</b></div>'; } ?> <div class="tytul-wpisu"> <h2 style="margin-top: 0;"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2> </div> <div class="streszczenie-wpisu"> <p><?php echo wp_trim_words(get_the_excerpt(), 25, ' [...]'); ?></p> </div> <div class="data-i-godzina-wpisu"> <p style="font-size: 0.9em; color: #555;">Autor: <?php the_author(); ?> | <?php the_time('d.m.Y H:i'); ?></p> </div> <div class="czytajwiecej" style="margin-top: 10px;"> <a class="czytaj-wiecej" href="<?php the_permalink(); ?>" style="display: inline-block;">Czytaj więcej</a> <span style="margin-left: 10px; font-size: 0.9em; color: #999;">Post #<?php echo $post_number; ?></span> </div> </div> </div> <?php } wp_reset_postdata(); echo ob_get_clean(); } else { echo '<p>Brak wyników.</p>'; } wp_die(); }