W serwisach członkowskich, sklepach WooCommerce i portalach B2B pasek narzędzi WordPressa (#wpadminbar) pojawia się dla każdego zalogowanego użytkownika, także dla klienta bez dostępu do kokpitu. Na frontendzie wygląda jak obcy panel deweloperski: linki do pulpitu, powiadomienia o aktualizacjach, menu użytkownika. Ten tutorial pokazuje, jak wyłączyć go poprawnie po stronie PHP, dlaczego manage_options bije porównanie stringu roli, jak złożyć 32 px marginesu na html i dlaczego samo CSS to antypatern.
Materiał jest napisany pod polskie wdrożenia produkcyjne: motyw potomny albo mu-plugin, WooCommerce z rolą customer, staging z osobnym kontem testowym. Nie wymaga wtyczki „hide admin bar”; jeden filtr i checklista regresji wystarczą.
Dlaczego WordPress pokazuje admin bar każdemu zalogowanemu
WordPress domyślnie pokazuje admin bar każdemu użytkownikowi z sesją. Decyzja ma sens w blogu z kilkoma autorami, którzy edytują wpisy z frontu. W sklepie, akademii online albo strefie klienta ta sama decyzja psuje UX:
- Subskrybent widzi skróty do ekranów, których i tak nie otworzy.
- Klient WooCommerce dostaje czarny pasek nad koszykiem i nagłówkiem.
- Motyw z
position: stickyna headerze zaczyna „pływać” o 32 px względem viewportu. - Testerzy raportują „pustą przestrzeń” albo „złamany sticky”, choć winny jest
margin-topna elemenciehtml.
Ukrycie paska to nie kosmetyka. To świadome odcięcie warstwy administracyjnej od warstwy produktu.
Jak ukryć pasek admina filtrem show_admin_bar
Oficjalny punkt zaczepienia to filtr show_admin_bar. Funkcja show_admin_bar() ustawia flagę globalną, ale filtr jest tym, czego używa rdzeń przy decyzji o renderze paska i o wstrzyknięciu stylów.
Minimalny, czytelny wariant:
/**
* Pokaż admin bar tylko użytkownikom z manage_options.
*/
add_filter( 'show_admin_bar', 'wppoland_show_admin_bar_for_managers' );
function wppoland_show_admin_bar_for_managers( $show ) {
if ( is_admin() ) {
return $show;
}
return current_user_can( 'manage_options' );
}Co się tu dzieje:
- Filtr dostaje aktualną wartość bool i ją zwraca albo nadpisuje.
- W kokpicie (
is_admin()) nie ruszamy decyzji WordPressa. - Na frontendzie zwracamy wynik
current_user_can( 'manage_options' ).
Starszy wzorzec z after_setup_theme + show_admin_bar( false ) nadal działa, ale filtr jest czytelniejszy w debugowaniu (kolejność priorytetów, inne wtyczki nadpisujące ten sam hook) i lepiej dokumentowany w Codexie / DevHub.
Kiedy używać manage_options zamiast roli administrator
current_user_can() sprawdza capability, nie nazwę roli. Rola administratora w WordPressie ma capability manage_options (patrz rola Administrator i Capabilities API). Porównanie current_user_can( 'administrator' ) jest mylące:
- String
'administrator'to slug roli, nie capability. W wielu instalacjach ten warunek „przypadkiem” przechodzi przez legacy path w mapowaniu ról, ale nie jest to kontrakt, na którym warto budować. - Wtyczki membership / LMS często dodają własne role z częściowym dostępem do kokpitu. String roli ich nie obejmuje, a capability
edit_postsalbomanage_woocommercemoże. - Multisite: super admin i admin sieci mają inny zestaw uprawnień niż lokalny admin bloga. Capability jest bliżej intencji „kto może zarządzać stroną”.
Praktyczna macierz decyzji:
| Cel | Warunek |
|---|---|
| Tylko pełny admin witryny | current_user_can( 'manage_options' ) |
| Redaktorzy i wyżej widzą pasek | current_user_can( 'edit_pages' ) albo edit_others_posts |
| Ukryj tylko dla klientów sklepu | negacja current_user_can( 'customer' ) nie - lepiej lista ról lub ! current_user_can( 'edit_posts' ) |
| Multisite: tylko super admin | is_super_admin() |
Jeśli naprawdę potrzebujesz listy ról (np. ukryj dla subscriber, customer, contributor), czytaj $user->roles, ale trzymaj tę listę w stałej i testuj po każdej zmianie wtyczek ról:
add_filter( 'show_admin_bar', function ( $show ) {
if ( is_admin() || ! is_user_logged_in() ) {
return $show;
}
$user = wp_get_current_user();
$hide_for = array( 'subscriber', 'customer', 'contributor' );
if ( array_intersect( $hide_for, (array) $user->roles ) ) {
return false;
}
return $show;
} );Dla typowego sklepu albo strefy klienta wystarczy wariant z manage_options.
Jak naprawić margin-top html po ukryciu admin bara
Gdy pasek jest widoczny, WordPress ładuje admin-bar.min.css i ustawia html { margin-top: 32px !important; } (46 px na wąskich viewportach). Gdy filtr zwraca false, skrypt i style paska nie powinny się załadować. Czasem jednak:
- inna wtyczka wymusza CSS paska,
- motyw w customizerze zakłada stałe 32 px,
- Full Site Editing (FSE) trzyma sticky header z
top: 0, a wcześniej ktoś dodał body classadmin-barręcznie.
Objawy: szara dziura pod górą viewportu, sticky nawigacja przesunięta o wysokość paska, sticky CTA „ucieka” pod admin barem, którego już nie ma.
Diagnoza w DevTools:
- Zaloguj się jako subskrybent.
- Sprawdź, czy w DOM jest
#wpadminbar. - Sprawdź computed
margin-topnahtmlibody. - Sprawdź, czy klasa
admin-barsiedzi na<body>.
Jeśli filtr działa, a margin zostaje, usuń go warunkowo albo napraw źródło CSS. Nie doklejaj ślepo html { margin-top: 0 !important; } dla wszystkich - zniszczysz layout adminów, którzy pasek nadal widzą.
Bezpieczny kompromis w motywie potomnym:
/* Tylko gdy WordPress nie dodał klasy admin-bar */
body:not(.admin-bar) {
/* sticky / fixed elementy zakładają top: 0 względem viewportu */
}Albo w PHP upewnij się, że filtr leci wcześnie (priorytet domyślny 10 jest OK; unikaj late hooks typu wp_footer).
Blokowanie dostępu do kokpitu przez admin_init i template_redirect
Samo ukrycie paska narzędzi na frontendzie nie stanowi zabezpieczenia przed wejściem do panelu administracyjnego. Użytkownik z rolą Subskrybent lub Klient może ręcznie wpisać w przeglądarce adres /wp-admin/ i otworzyć ekran edycji profilu (/wp-admin/profile.php).
Aby stworzyć szczelną separację między klientem a kokpitem WordPressa, należy powiązać filtr paska z regułą przekierowania na akcji admin_init:
<?php
/**
* Blokada dostępu do /wp-admin/ dla użytkowników bez uprawnień zarządzania
*/
add_action( 'admin_init', 'wppoland_restrict_dashboard_access' );
function wppoland_restrict_dashboard_access(): void {
// Niezbędny wyjątek: zapytania asynchroniczne frontendu
if ( wp_doing_ajax() ) {
return;
}
// Administratorzy i menedżerowie zachowują dostęp
if ( current_user_can( 'manage_options' ) ) {
return;
}
// Przekierowanie klientów na stronę Moje konto lub stronę główną
wp_safe_redirect( home_url( '/moje-konto/' ) );
exit;
}Warunek wp_doing_ajax() jest krytyczny. Frontendowe skrypty koszyka, dynamicznych filtrów i formularzy wysyłają asynchroniczne zapytania POST pod adres /wp-admin/admin-ajax.php. Brak tego warunku spowoduje, że operacje koszyka u zalogowanych klientów zwrócą przekierowanie HTTP 302 zamiast oczekiwanej odpowiedzi JSON.
W przypadku archiwów autorów, WordPress domyślnie generuje publiczne widoki pod adresem /?author=1. W sklepach WooCommerce prowadzi to do wycieku loginów klientów. Dodatkowe zabezpieczenie na hooku template_redirect eliminuje to zjawisko:
<?php
add_action( 'template_redirect', 'wppoland_block_customer_author_archives' );
function wppoland_block_customer_author_archives(): void {
if ( is_author() ) {
$author = get_queried_object();
if ( $author instanceof WP_User && in_array( 'customer', (array) $author->roles, true ) ) {
wp_safe_redirect( home_url(), 301 );
exit;
}
}
}Specyfika sklepów WooCommerce i platform membership
Wdrożenia e-commerce i platformy subskrypcyjne stawiają odmienne wymagania przed paskiem narzędzi:
Portale klientów WooCommerce
Klienci sklepu realizują wszystkie operacje konta przez natywne punkty końcowe (/moje-konto/, /moje-konto/zamowienia/, /moje-konto/adresy/). Pasek narzędzi nie tylko wprowadza chaos wizualny, ale może kolidować z mobilnymi panelami off-canvas oraz pływającym koszykiem.
<?php
add_filter( 'show_admin_bar', function( bool $show ): bool {
if ( is_admin() ) {
return $show;
}
// Klienci WooCommerce nigdy nie widzą paska
$user = wp_get_current_user();
if ( in_array( 'customer', (array) $user->roles, true ) ) {
return false;
}
// Menedżerowie sklepu widzą pasek do szybkiej edycji produktów i stanów
if ( current_user_can( 'manage_woocommerce' ) ) {
return true;
}
return current_user_can( 'manage_options' );
} );Portale członkowskie i platformy kursowe
W platformach takich jak MemberPress czy LearnDash, subskrybenci płacą za dostęp do materiałów szkoleniowych. Pasek narzędzi WordPressa odwraca uwagę od lekcji, a nieprawidłowo skonfigurowane wtyczki cache mogą buforować pasek jednego użytkownika dla pozostałych. Umieszczenie reguły w pliku mu-plugins zapewnia odporność na aktualizacje szablonów lekcji.
Zarządzanie węzłami paska dla redaktorów
Czasami celem wdrożenia nie jest całkowite wygaszenie paska, lecz uproszczenie go dla redaktorów i autorów treści. Zamiast wyłączać pasek, usuwamy z niego zbędne elementy za pomocą klasy WP_Admin_Bar:
<?php
/**
* Usuwanie zbędnych węzłów paska narzędzi dla autorów
*/
add_action( 'admin_bar_menu', 'wppoland_simplify_editor_toolbar', 999 );
function wppoland_simplify_editor_toolbar( WP_Admin_Bar $wp_admin_bar ): void {
// Pełni administratorzy zachowują kompletny pasek
if ( current_user_can( 'manage_options' ) ) {
return;
}
// Usunięcie logo WordPressa, powiadomień i skrótów pomocy
$wp_admin_bar->remove_node( 'wp-logo' );
$wp_admin_bar->remove_node( 'about' );
$wp_admin_bar->remove_node( 'wporg' );
$wp_admin_bar->remove_node( 'documentation' );
$wp_admin_bar->remove_node( 'support-forums' );
$wp_admin_bar->remove_node( 'feedback' );
$wp_admin_bar->remove_node( 'comments' );
$wp_admin_bar->remove_node( 'new-content' );
$wp_admin_bar->remove_node( 'updates' );
}Dzięki temu redaktor widzi jedynie własny profil, przycisk wylogowania oraz skrót szybkiej edycji aktualnie przeglądanego wpisu na frontendzie.
Jak ukryć admin bar w must-use plugin
Kod w functions.php motywu znika przy zmianie skórki. W sklepach i portalach klienta logika „kto widzi pasek” należy do produktu, nie do wyglądu. Must-use plugin (wp-content/mu-plugins/) ładuje się zawsze, przed zwykłymi wtyczkami, bez przełącznika w UI.
Przykład kompletnego pliku wp-content/mu-plugins/wppoland-admin-bar.php:
<?php
/**
* Plugin Name: WPPoland Admin Bar Policy
* Description: Frontend admin bar tylko dla manage_options wraz z blokadą kokpitu.
* Author: wppoland.com
* Version: 1.0.0
*/
declare(strict_types=1);
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
add_filter( 'show_admin_bar', static function ( bool $show ): bool {
if ( is_admin() ) {
return $show;
}
return current_user_can( 'manage_options' );
}, 10 );
add_action( 'admin_init', static function (): void {
if ( wp_doing_ajax() ) {
return;
}
if ( ! current_user_can( 'manage_options' ) ) {
wp_safe_redirect( home_url( '/' ) );
exit;
}
}, 10 );Zalety mu-pluginu w tym przypadku:
- Przetrwa wymianę motywu i migrację ze stagingu na produkcję bez kopiowania
functions.php. - Nie da się wyłączyć przypadkiem z listy wtyczek.
- Łatwy do wrzucenia do repozytorium infrastruktury (Ansible, image Dockera, Git deploy).
Wady: brak GUI, trzeba dokumentować w README projektu, debug wymaga SSH lub menedżera plików. Dla agencji to zwykle zaleta.
Jeśli zespół nie używa mu-plugins, trzymaj kod w małej własnej wtyczce w wp-content/plugins/, ale nie w motywie sklepu, który wymieniasz co sezon.
Dlaczego nie ukrywać admin bara samym CSS
#wpadminbar { display: none !important; } wygląda na szybki fix i jest częstą radą na forach. To antypatern z kilku powodów:
- DOM i JS zostają. Pasek nadal się buduje, eventy hover/klik nadal wiszą, skrypty
admin-barnadal ładują się w<head>. - Margin 32 px zostaje.
html { margin-top: 32px !important; }pochodzi z tego samego arkusza. Ukryjesz pasek, zostawisz dziurę. - Dostępność. Elementy focusable w ukrytym pasku nadal mogą złapać Tab, zwłaszcza przy niedbałym
visibilityalboopacity. - Fałszywe poczucie bezpieczeństwa. Użytkownik bez
manage_optionsnadal „ma” warstwę admin UI w HTML. Filtr PHP jej nie renderuje.
CSS ma sens wyłącznie jako warstwa awaryjna przy motywach, które hardcodują odstęp, po poprawnym filtrze PHP. Nigdy jako jedyne rozwiązanie.
Jak FSE i sticky header reagują na admin bar
Bloki motywów Full Site Editing (Twenty Twenty-Four i pochodne) często używają sticky grupy nawigacji. Gdy body.admin-bar jest obecne, wiele motywów klasycznych dodaje top: 32px do fixed/sticky. Motywy blokowe bywają mniej przewidywalne: niektóre polegają wyłącznie na marginie html, inne na własnym CSS.
Scenariusze do przetestowania ręcznie:
- Admin zalogowany, frontend - pasek widoczny, sticky header pod paskiem, brak overlapu.
- Klient zalogowany, frontend - brak
#wpadminbar, brak klasyadmin-bar, sticky flush z górą viewportu. - Wylogowany - jak klient, bez sesji.
- Mobile - WordPress używa wyższego offsetu (46 px) przy wąskim viewportcie; po ukryciu paska sticky nie może zostawiać 46 px pustej przestrzeni.
- Edytor pełnoekranowy / Site Editor - nie ruszaj paska w
is_admin(); filtr z wcześniejszego przykładu już to zabezpiecza.
Jeśli sticky header w FSE nadal skacze po wdrożeniu filtra, sprawdź w Global Styles / Additional CSS motywu reguły typu body.admin-bar .wp-block-group.is-position-sticky. Usuń zależność od klasy albo uzależnij offset wyłącznie od obecności #wpadminbar.
Na stagingu warto porównać trzy viewporty obok siebie: desktop z adminem, desktop z klientem, telefon z klientem. Różnica w getBoundingClientRect().top sticky nawigacji od razu pokazuje, czy offset 32/46 px nadal funkcjonuje w CSS mimo braku paska.
Jak ukryć admin bar w after_setup_theme
Dla kompatybilności ze starszymi snippetami (i z naszym historycznym kodem) zostawiam wariant imperatywny. Działa, byle warunek opierał się o capability:
add_action( 'after_setup_theme', 'wppoland_remove_admin_bar' );
function wppoland_remove_admin_bar() {
if ( ! current_user_can( 'manage_options' ) && ! is_admin() ) {
show_admin_bar( false );
}
}Zalecenie na 2026: preferuj filtr show_admin_bar. Funkcja show_admin_bar( false ) jest poprawna jako skrót, ale filtr daje jeden punkt kontroli, gdy kilka wtyczek walczy o widoczność.
Zarządzanie preferencjami profilu użytkownika
W profilu każdego użytkownika w WordPressie znajduje się natywne pole wyboru „Pokaż pasek narzędzi podczas przeglądania witryny”. W bazie danych odpowiada ono metadanym użytkownika pod kluczem show_admin_bar_front.
Warto wiedzieć, w jakiej kolejności silnik WordPressa podejmuje decyzję o wyświetleniu paska:
- Sprawdza globalną zmienną
$show_admin_bar. - Jeśli zmienna nie została ustawiona, pobiera wartość z tabeli
usermetaprzez funkcjęget_user_option( 'show_admin_bar_front' ). - Ostateczny wynik przekazuje przez filtr
show_admin_bar.
Ponieważ filtr działa na samym końcu łańcucha wykonania, filtr z warunkiem current_user_can( 'manage_options' ) całkowicie nadpisuje wybór użytkownika z profilu. Jeśli jednak w zespole redakcyjnym niektórzy autorzy chcą samodzielnie wyłączać pasek dla własnej wygody czytania, można uwzględnić metadane profilu:
<?php
/**
* Warunkowe uwzględnienie preferencji profilu dla autorów
*/
add_filter( 'show_admin_bar', function( bool $show ): bool {
if ( is_admin() || ! is_user_logged_in() ) {
return $show;
}
// Subskrybenci i klienci sklepu nigdy nie widzą paska
if ( ! current_user_can( 'edit_posts' ) ) {
return false;
}
// Autorzy mogą odznaczyć pasek w ustawieniach własnego profilu
$user_id = get_current_user_id();
$pref = get_user_meta( $user_id, 'show_admin_bar_front', true );
if ( 'false' === $pref ) {
return false;
}
return true;
} );Rozwiązanie to daje elastyczność redaktorom pracującym nad długimi artykułami, uniemożliwiając jednocześnie subskrybentom wymuszenie paska przez formularze konta.
Gdzie nie umieszczać kodu ukrywającego admin bar
- Motyw rodzica - aktualizacja nadpisze plik.
- Customizer „Additional CSS” - wracamy do antypaternu CSS.
- Inline w szablonie page - zadziała tylko na jednej stronie.
- Wtyczka „snippet manager” bez eksportu do Git - kolejny punkt awarii przy migracji środowiskowej.
Mu-plugin albo mała wtyczka wersjonowana w repo projektu to domyślny wybór dla produkcji.
Warstwy pamięci podręcznej i nagłówki proxy
Serwisy o dużym natężeniu ruchu korzystają z mechanizmów cache po stronie serwera (Nginx FastCGI cache, Redis, Cloudflare). Zróżnicowanie widoku frontendowego dla użytkowników zalogowanych wymaga weryfikacji reguł pamięci podręcznej:
- Bypass dla ciasteczek sesyjnych: Odpowiedzi dla żądań z ciasteczkami
wordpress_logged_in_*nie mogą trafiać do wspólnego cache publicznego. W przeciwnym razie zwykły gość mógłby otrzymać zbuforowaną wersję strony z marginesem paska narzędzi. - Nagłówki Cache-Control: Widoki konta klienta i koszyka powinny zwracać
Cache-Control: private, no-cache, no-store, must-revalidate.
Jak przetestować ukrycie admin bara w 10 minut
- Utwórz użytkownika z rolą Subskrybent (albo Customer w WooCommerce).
- W oknie prywatnym zaloguj się jako on, otwórz stronę główną i koszyk.
- Potwierdź: brak
#wpadminbar,bodybezadmin-bar,margin-topnahtmlrówny 0. - Zaloguj się jako Administrator: pasek wraca, sticky header nie nachodzi na treść.
- Wejdź do
/wp-admin/jako admin: kokpit bez zmian. - Spróbuj wejść pod
/wp-admin/jako subskrybent: potwierdź przekierowanie na stronę główną lub stronę konta. - Wykonaj akcję dodania do koszyka w tle: upewnij się, że zapytanie do
admin-ajax.phpzakończyło się kodem 200.
Jakie praktyki stosować przy ukrywaniu admin bara
- Używaj filtra
show_admin_bar, nie samego CSS. - Warunek buduj na capability (
current_user_can), zwyklemanage_options. - Nie ruszaj zachowania w
is_admin(). - Po ukryciu sprawdź collapse 32 px / 46 px i sticky headery FSE.
- Kod trzymaj w mu-pluginie albo własnej wtyczce, nie w motywie sklepu.
- Dokumentuj politykę w README projektu, żeby kolejny deploy nie przywrócił paska przez CSS.
- Blokuj dostęp do zaplecza na hooku
admin_initz zachowaniem wyjątkuwp_doing_ajax().
Kiedy warto ukryć pasek administratora w WordPress
Ukrycie paska administratora dla nie-administratorów to mały filtr PHP z dużym wpływem na UX sklepu i strefy klienta. Filtr show_admin_bar plus manage_options daje przewidywalną politykę; lista stringów ról zostaje dla wyjątków. Po wyłączeniu paska zawsze weryfikuj margin na html i sticky w FSE. CSS-only to usterka czekająca na regresję. Mu-plugin izoluje regułę od rotacji motywów.
Po wdrożeniu zapisz w changelogu projektu: kto widzi pasek, gdzie leży plik (mu-plugin vs wtyczka), oraz datę weryfikacji na produkcyjnych rolach. Przy kolejnym audycie UX wystarczy powtórzyć checklistę z sekcji testów zamiast zgadywać, która wtyczka wywołała konflikt.
Jeśli budujesz portal klienta albo sklep na WordPressie i potrzebujesz spójnej warstwy UX poza samym paskiem, zobacz usługi developera WordPress.







