Cum să adaugi o clasă unică tag-ului HTML/elementului

28 mai 2017, 02:34:13
Vizualizări: 16K
Voturi: 0

Ș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?

4
Comentarii

Te superi să explici de ce ai nevoie să faci asta? (Sunt doar curios.) De asemenea, este acceptabilă o soluție JavaScript sau ai prefera o abordare PHP?

Dave Romsey Dave Romsey
28 mai 2017 02:52:14

@DaveRomsey motivul meu principal pentru asta este că creez o pagină personalizată unică pe un site WordPress existent. Este o pagină care va fi folosită pentru un Slideshow pe un TV 4K.

Tema curentă setează CSS-ul pentru font-size și line-height pe elementul <html>. În plus, unele dintre stilurile de conținut ale temei folosesc rem pentru dimensiunea fontului.

În esență, aș dori să măresc drastic dimensiunea fontului și înălțimea liniei elementului HTML — doar pentru această pagină — astfel încât să pot continua să folosesc dimensiunile în rem (deoarece rem funcționează pe baza dimensiunilor HTML).

Garconis Garconis
28 mai 2017 04:27:18

Aș prefera cu siguranță PHP în loc de JS. Pentru moment folosesc doar CSS intern pentru a schimba dimensiunile elementului HTML, dar aș prefera să adaug CSS-ul în fișierul CSS extern principal... de aceea și dorința de a putea ținti elementul HTML al acestei pagini specifice.

Garconis Garconis
28 mai 2017 04:30:35

Verifică acest răspuns, mi-a rezolvat problema.

hayatbiralem hayatbiralem
5 sept. 2017 10:57:27
Toate răspunsurile la întrebare 5
1

De ce să nu adăugați clasa direct în tag?

<html <?php language_attributes(); ?> class="page-id-<?php the_ID(); ?>">
10 oct. 2019 00:00:35
Comentarii

Încerc să evit suprascrierea fișierelor temei.

Garconis Garconis
10 oct. 2019 04:04:45
1

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;
    }
28 mai 2017 14:28:51
Comentarii

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.

TonyG TonyG
13 oct. 2023 23:56:34
3

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

11 dec. 2020 01:06:17
Comentarii

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.

Garconis Garconis
11 dec. 2020 16:30:56

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.

James0r James0r
11 dec. 2020 21:03:27

Ah, la mine deja există o clasă no-js sau js din tema, deci poate dacă există deja o clasă, nu poate adăuga alta?

Garconis Garconis
12 dec. 2020 01:20:36
1

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(); ?>>
28 mai 2017 03:32:07
Comentarii

Aș prefera să nu modific fișierul PHP actual. Tema are deja clase (nu neapărat unice) pe elementul HTML. De asemenea, aș prefera să nu adaug clasele din body pe elementul HTML, deoarece sunt sigur că tema nu este pregătită pentru asta.

Garconis Garconis
28 mai 2017 04:33:11
0

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' );
11 dec. 2020 16:39:29