Cum să adaugi o clasă unică tag-ului HTML/elementului
Știu că există funcția body_class în WordPress. Dar există vreo funcție (sau metodă) pentru a adăuga o clasă la elementul HTML?
Scopul meu este să pot adăuga o clasă unică (sau ID) la elementul HTML al unei pagini. Momentan tema mea adaugă clasa page-id-XXXX la elementul body, dar am nevoie să am o clasă sau ID unic pe elementul HTML propriu-zis. Aș fi mulțumit dacă page-id-XXXX ar fi adăugat și pe elementul HTML, deși aș prefera să pot folosi un câmp personalizat pe fiecare pagină, unde să pot introduce clasa/ID care să fie adăugat la elementul HTML.
Măcar există vreo funcție pe care o pot folosi pentru a adăuga o clasă sau ID la elementul HTML, similar cu cum funcționează body_class?

WordPress nu are un echivalent al funcției body_class()
pentru tag-ul HTML.
Iată o abordare care utilizează bufferizarea ieșirii pentru a captura rezultatul final al documentului HTML care este randat. Codul de bufferizare de mai jos a fost adaptat din soluțiile postate aici și aici. Acest lucru ne permite să accesăm rezultatul final al documentului HTML, pe care îl analizăm și edităm, fără a fi nevoie să modificăm fișierele de șablon ale temei.
Mai întâi, începem bufferizarea ieșirii și conectăm funcția noastră shutdown
, care
funcționează parcurgând toate nivelurile deschise ale bufferului, închizându-le și capturând ieșirea lor. Apoi declanșează filtrul wpse_final_output
, afișând conținutul filtrat.
/**
* Începe bufferizarea ieșirii
*/
add_action( 'wp', 'wpse_ob_start' );
function wpse_ob_start() {
// Renunță imediat dacă suntem în zona de administrare.
if ( is_admin() ) {
return;
}
// Renunță imediat dacă este un feed.
if ( is_feed() ) {
return;
}
// Începe bufferizarea ieșirii.
ob_start();
add_action( 'shutdown', 'wpse_ob_clean', 0 );
}
/**
* Asigură că bufferul este curat și apoi declanșează filtrul wpse_final_output.
* Acest lucru se întâmplă chiar înaintea funcționalității similare de shutdown din WP.
*/
function wpse_ob_clean() {
$final = '';
// Avem nevoie să obținem numărul de niveluri de ob în care ne aflăm, astfel încât să putem
// itera peste fiecare, colectând ieșirea acelui buffer în ieșirea finală.
$levels = ob_get_level();
for ( $i = 0; $i < $levels; $i++ ) {
$final .= ob_get_clean();
}
// Aplică orice filtre asupra ieșirii finale
echo apply_filters( 'wpse_final_output', $final );
}
Aici HTML-ul este analizat și filtrul personalizat wpse_additional_html_classes
este declanșat, permițându-ne să adăugăm clasele noastre suplimentare într-o funcție separată. Acest cod este un pic verbose, dar acoperă mai multe cazuri limită pe care le-am întâlnit când am folosit DOMDocument
pentru a analiza HTML.
add_filter( 'wpse_final_output', 'wpse_html_tag', 10, 1 );
/**
* Analizează ieșirea finală a bufferului. Declanșează wpse_additional_html_classes, care
* ne permite să adăugăm clase la elementul HTML.
*/
function wpse_html_tag( $output ) {
// Listă de clase HTML care pot fi filtrate.
$additional_html_classes = apply_filters( 'wpse_additional_html_classes', array() );
// Renunță dacă nu există clase de adăugat, deoarece nu va fi nevoie să facem nimic.
if ( ! $additional_html_classes ) {
return $output;
}
// Creează o instanță a DOMDocument.
$dom = new \DOMDocument();
// Suprimă erorile datorate HTML-ului malformat.
// Vezi http://stackoverflow.com/a/17559716/3059883
$libxml_previous_state = libxml_use_internal_errors( true );
// Populează $dom cu bufferul, asigurându-ne că gestionăm UTF-8, altfel
// vor apărea probleme cu caracterele UTF-8.
// De asemenea, asigură-te că doctype și tag-urile HTML nu sunt adăugate fragmentului nostru HTML. http://stackoverflow.com/a/22490902/3059883
$dom->loadHTML( mb_convert_encoding( $output, 'HTML-ENTITIES', 'UTF-8' ), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
// Restaurează starea anterioară a libxml_use_internal_errors() acum că am terminat.
// Din nou, vezi http://stackoverflow.com/a/17559716/3059883
libxml_use_internal_errors( $libxml_previous_state );
// Creează o instanță a DOMXpath.
$xpath = new \DOMXpath( $dom );
// Obține primul element HTML.
$html = $xpath->query( "/descendant::html[1]" );
// Obține clasele existente pentru elementul HTML.
$definedClasses = explode( ' ', $dom->documentElement->getAttribute( 'class' ) );
// Adaugă clasele noastre suplimentare la clasele existente. Asigură-te că se folosește spațierea corectă a numelor de clase
// și că nu se adaugă nume de clase duplicate.
foreach ( $html as $html_tag ) {
$spacer = ' ';
// Spacer va fi setat la un șir gol dacă nu există clase existente.
if ( isset( $definedClasses[0] ) && false == $definedClasses[0] ) {
$spacer = '';
}
foreach ( $additional_html_classes as $additional_html_class ) {
if ( ! in_array( $additional_html_class , $definedClasses ) ) {
$html_tag->setAttribute(
'class', $html_tag->getAttribute( 'class' ) . $spacer . $additional_html_class
);
}
$spacer = ' ';
}
}
// Salvează HTML-ul actualizat.
$output = $dom->saveHTML();
return $output;
}
Filtrul wpse_additional_html_classes
ne permite să filtrăm ușor clasele suplimentare adăugate elementului HTML. În exemplul de mai jos, se adaugă o clasă specială pentru ID-ul postului (desigur, există multe cazuri în care nu va exista un ID de post). De asemenea, se adaugă o matrice de nume de clase personalizate. Personalizează clasele/logica pentru adăugarea claselor în funcție de nevoile tale, apoi returnează matricea cu numele claselor.
add_filter( 'wpse_additional_html_classes', 'wpse_add_additional_html_classes', 10, 1 );
/**
* Filtrează lista de nume de clase care trebuie adăugate la elementul HTML.
*
* @param array $classes
* @return array
*/
function wpse_add_additional_html_classes( $classes ) {
// Exemplu de adăugare a unei clase pentru ID-ul postului.
if ( is_singular() ) {
$post_id = get_the_ID();
if ( $post_id ) {
$post_id_class = "post-id-{$post_id}";
if ( ! in_array( $post_id_class, $classes ) ) {
$classes[] = $post_id_class;
}
}
}
// Adaugă câteva clase suplimentare.
$additional_classes = [
'class-1',
'class-2',
'class-3',
];
$classes = array_merge( $classes, $additional_classes );
return $classes;
}

Mă gândesc să folosesc cod temporar pentru a modifica toate tagurile de antet pentru a ocoli o eroare din WP v6 - iar o căutare m-a adus aici. Îți mulțumesc frumos pentru acest cod care ar face exact ceea ce mă gândesc eu. Având în vedere însă performanța, îți mulțumesc în special pentru că m-ai ajutat să înțeleg că exact asta nu aș vrea să fac pe un site de producție. Da, aceasta este o soluție excelentă, dar cred că doar ca ultimă soluție. Sper că acest comentariu va ajuta pe cineva care este tentat să copieze/lipească pur și simplu.

Aceasta a funcționat perfect pentru mine
add_filter( 'language_attributes', 'add_no_js_class_to_html_tag', 10, 2 );
function add_no_js_class_to_html_tag( $output, $doctype ) {
if ( 'html' !== $doctype ) {
return $output;
}
$output .= ' class="no-js"';
return $output;
}
Nu am găsit nimic despre aceasta în codex. Credit către https://gist.github.com/nickdavis/73d91d674b843b77a1cd0a21f9c0353a

A funcționat pentru a adăuga o clasă personalizată? La mine nu face nimic. Dacă setez să fie un alt atribut în loc de clasă, atunci funcționează. De exemplu, acest cod funcționează: function add_class_to_html_element( $output ) { $output .= ' attribute="value"'; return $output; } add_filter( 'language_attributes', 'add_class_to_html_element' );
... dar imediat ce schimbi attribute
în class
, nu mai apare. Se pare că id
va funcționa totuși.

Eu folosesc ClassicPress 1.2, care s-a despărțit de WP 4.9, dar la mine funcționează. <html lang="en-US" class="no-focus-outline"> așa arată acum capul meu.

Deoarece te afli în afara buclei, cea mai curată soluție este să creezi propria funcție, astfel:
function wpse_268339_get_post_class() {
global $post;
if ( ! empty( $post->ID ) ) {
return 'post-' . $post->ID;
}
}
Apoi, în template-ul tău header.php
, apelează funcția și escaphează output-ul într-o clasă a tag-ului body. Acest exemplu presupune că ai deja câteva clase pe tag-ul <html>
.
<html <?php language_attributes(); ?> class="no-js no-svg <?php echo esc_attr( wpse_268339_get_post_class() ); ?>">
Aceasta va afișa un nume de clasă doar dacă te afli pe o Postare / Pagină.
Alternativ, dacă toate clasele normale ale body-ului nu afectează nimic, poți folosi direct body_class()
pe tag-ul <html>
. Funcția funcționează oriunde.
<html <?php body_class(); ?>>

Mulțumesc pentru ajutorul din acest răspuns, am descoperit că această soluție funcționează pentru adăugarea unui id
. Totuși, nu sunt sigur despre adăugarea la atributul class
.
function add_id_to_html_element( $output ) {
global $post;
$output .= ' id="custom-id-' . $post->ID . '"';
return $output;
}
add_filter( 'language_attributes', 'add_id_to_html_element' );
