Aggiungi una classe unica al tag/elemento HTML

28 mag 2017, 02:34:13
Visualizzazioni: 16K
Voti: 0

So che esiste la funzione body_class per WordPress. Ma esiste una funzione (o un modo) per aggiungere una classe all'elemento HTML?

Il mio obiettivo è poter aggiungere una classe unica (o un ID) all'elemento HTML di una pagina. Attualmente il mio tema aggiunge la classe page-id-XXXX all'elemento body, ma ho bisogno di un modo per avere una classe o ID unico sull'elemento HTML vero e proprio. Andrei bene anche con page-id-XXXX aggiunto all'elemento HTML, anche se preferirei poter avere un campo personalizzato aggiunto a ogni pagina, dove posso inserire la classe/ID che verrebbe poi aggiunta all'elemento HTML.

Come minimo, esiste una funzione che posso usare per aggiungere una classe o ID all'elemento HTML, simile a come funziona la funzione body_class?

4
Commenti

Potresti spiegarmi perché hai bisogno di fare questo? (Sono solo curioso.) Inoltre, una soluzione JavaScript è accettabile o preferisci un approccio PHP?

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

@DaveRomsey la mia ragione principale è che sto creando una pagina personalizzata una tantum su un sito WordPress esistente. È una pagina che verrà utilizzata per una slideshow su TV 4K.

L'attuale tema imposta il CSS di font-size e line-height sull'elemento <html>. Inoltre, alcuni degli stili di contenuto del tema utilizzano rem per la dimensione del carattere.

In sostanza, vorrei aumentare drasticamente la dimensione del carattere e l'interlinea dell'elemento HTML - solo per questa pagina - in modo da poter continuare a utilizzare il dimensionamento rem (dato che rem lavora in base alle dimensioni dell'HTML).

Garconis Garconis
28 mag 2017 04:27:18

Preferirei decisamente PHP rispetto a JS. Per ora sto usando CSS interno per modificare le dimensioni dell'elemento HTML, ma preferirei aggiungere il CSS al file CSS esterno principale... da qui il desiderio di poter targettare specificamente l'elemento HTML di questa pagina.

Garconis Garconis
28 mag 2017 04:30:35

Controlla questa risposta, ha risolto il mio problema.

hayatbiralem hayatbiralem
5 set 2017 10:57:27
Tutte le risposte alla domanda 5
1

Perché non aggiungere direttamente la classe al tag?

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

Sto cercando di evitare di sovrascrivere i file del tema.

Garconis Garconis
10 ott 2019 04:04:45
1

WordPress non ha un equivalente di body_class() per il tag html.

Ecco un approccio che utilizza l'output buffering per catturare l'output finale del documento HTML in fase di rendering. Il codice di output buffering qui sotto è stato adattato dalle soluzioni pubblicate qui e qui. Questo ci permette di accedere all'output finale del documento HTML che poi analizziamo e modifichiamo, tutto senza bisogno di modificare i file template del tema.

Per prima cosa, iniziamo l'output buffering e colleghiamo la nostra funzione shutdown, che funziona iterando attraverso tutti i livelli di buffer aperti, chiudendoli e catturandone l'output. Poi attiva il filtro wpse_final_output, stampando il contenuto filtrato.

    /**
     * Avvia l'output buffering
     */
    add_action( 'wp', 'wpse_ob_start' );
    function wpse_ob_start() {
        // Interrompi immediatamente se siamo nell'area amministrativa.
        if ( is_admin() ) {
            return;
        }
    
        // Interrompi immediatamente se è un feed.
        if ( is_feed() ) {
            return;
        }
        
        // Avvia l'output buffering.
        ob_start();
        add_action( 'shutdown', 'wpse_ob_clean', 0 );
    }
    
    /**
     * Assicura che il buffer sia pulito e poi attiva il filtro wpse_final_output.
     * Questo viene eseguito subito prima della funzionalità di shutdown simile di WP.
     */
    function wpse_ob_clean() {
        $final = '';
    
        // Dobbiamo ottenere il numero di livelli ob in cui ci troviamo, così possiamo
        // iterare su ognuno, raccogliendo l'output di quel buffer nell'output finale.
        $levels = ob_get_level();
    
        for ( $i = 0; $i < $levels; $i++ ) {
            $final .= ob_get_clean();
        }
    
        // Applica eventuali filtri all'output finale
        echo apply_filters( 'wpse_final_output', $final );
    }

Qui l'HTML viene analizzato e viene attivato il filtro personalizzato wpse_additional_html_classes che ci permette di aggiungere le nostre classi aggiuntive in una funzione separata. Questo codice è un po' dettagliato, ma copre diversi casi limite che ho incontrato usando DOMDocument per analizzare l'HTML.

    add_filter( 'wpse_final_output', 'wpse_html_tag', 10, 1 );
    /**
     * Analizza l'output finale del buffer. Attiva wpse_additional_html_classes, che 
     * ci permette di aggiungere classi all'elemento html.
     */
    function wpse_html_tag( $output ) {
        
        // Lista delle classi html filtrabili.
        $additional_html_classes = apply_filters( 'wpse_additional_html_classes', array() );
        
        // Interrompi se non ci sono classi da aggiungere poiché non c'è nulla da fare.
        if ( ! $additional_html_classes ) {
            return $output;
        }
    
        // Crea un'istanza di DOMDocument.
        $dom = new \DOMDocument();
        
        // Soppressione degli errori dovuti a HTML malformato.
        // Vedi http://stackoverflow.com/a/17559716/3059883
        $libxml_previous_state = libxml_use_internal_errors( true );
    
        // Popola $dom con il buffer, assicurandosi di gestire UTF-8, altrimenti
        // si verificheranno problemi con i caratteri UTF-8.
        // Inoltre, assicurati che il doctype e i tag HTML non vengano aggiunti al nostro frammento HTML. Vedi http://stackoverflow.com/a/22490902/3059883
        $dom->loadHTML( mb_convert_encoding( $output, 'HTML-ENTITIES', 'UTF-8' ), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
        
        // Ripristina lo stato precedente di libxml_use_internal_errors() ora che abbiamo finito.
        // Vedi di nuovo http://stackoverflow.com/a/17559716/3059883
        libxml_use_internal_errors( $libxml_previous_state );
        
        // Crea un'istanza di DOMXpath.
        $xpath = new \DOMXpath( $dom );
    
        // Ottieni il primo elemento html.
        $html = $xpath->query( "/descendant::html[1]" );
        
        // Ottieni le classi esistenti per l'elemento html.
        $definedClasses = explode( ' ', $dom->documentElement->getAttribute( 'class' ) );
        
        // Aggiunge le nostre classi aggiuntive a quelle esistenti. Assicura che venga usato lo spazio corretto tra i nomi delle classi
        // e che non vengano aggiunti nomi di classe duplicati.
        foreach ( $html as $html_tag ) {
            $spacer = ' ';
            // Lo spacer sarà impostato a una stringa vuota se non ci sono classi esistenti.
            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 = ' ';
            }
        }
        
        // Salva l'HTML aggiornato.
        $output = $dom->saveHTML();     
    
        return $output;
    }

Il filtro wpse_additional_html_classes ci permette di filtrare facilmente le classi aggiuntive da aggiungere all'elemento HTML. Nell'esempio sotto, viene aggiunta una classe speciale per l'ID del post (ovviamente ci sono molti casi in cui non ci sarà un ID del post). Viene anche aggiunto un array di nomi di classi personalizzate. Personalizza le classi/la logica per aggiungere classi in base alle tue esigenze, poi restituisci l'array dei nomi delle classi.

    add_filter( 'wpse_additional_html_classes', 'wpse_add_additional_html_classes', 10, 1 );
    /**
     * Filtra la lista dei nomi di classe da aggiungere all'elemento HTML.
     *
     * @param array $classes
     * @return array
     */
    function wpse_add_additional_html_classes( $classes ) {
        // Esempio di aggiunta di una classe con l'ID del post.
        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;
                }
            }
        }
        
        // Aggiungi altre classi.
        $additional_classes = [
            'class-1',
            'class-2',
            'class-3',
        ];
        $classes = array_merge( $classes, $additional_classes );
        
        return $classes;
    }
28 mag 2017 14:28:51
Commenti

Sto valutando codice temporaneo per modificare tutti i tag di intestazione per aggirare un bug di WP v6 - e una ricerca mi ha portato qui. Ti ringrazio vivamente per questo codice che farebbe esattamente quello che stavo considerando. Tuttavia, considerando le prestazioni, ti ringrazio particolarmente per avermi aiutato a capire che questo è esattamente ciò che non voglio fare in un sito di produzione. Sì, questa è un'ottima soluzione, ma penso solo come ultima risorsa. Spero che questo commento aiuti qualcuno che è tentato di semplicemente copiare/incollare.

TonyG TonyG
13 ott 2023 23:56:34
3

Questo metodo ha funzionato perfettamente per me

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;
}

Non ho trovato nulla nel codex a riguardo. Crediti a https://gist.github.com/nickdavis/73d91d674b843b77a1cd0a21f9c0353a

11 dic 2020 01:06:17
Commenti

Ha funzionato per aggiungere una classe personalizzata? A me non fa nulla. Se imposto un attributo diverso invece della classe, allora funziona. Ad esempio, questo funziona: function add_class_to_html_element( $output ) { $output .= ' attribute="value"'; return $output; } add_filter( 'language_attributes', 'add_class_to_html_element' ); ... ma non appena cambi attribute in class, non viene visualizzato. Sembra che id funzioni però.

Garconis Garconis
11 dic 2020 16:30:56

Sto usando ClassicPress 1.2, che si è separato da WP 4.9 ma per me funziona. <html lang="en-US" class="no-focus-outline"> è come si presenta ora il mio head.

James0r James0r
11 dic 2020 21:03:27

Ah, il mio ha già una classe no-js o js dal tema, quindi forse se ha già una classe, non può aggiungerne un'altra?

Garconis Garconis
12 dic 2020 01:20:36
1

Dato che ti trovi al di fuori del loop, la soluzione più pulita è semplicemente creare la tua funzione in questo modo

function wpse_268339_get_post_class() {
    global $post;
    if ( ! empty( $post->ID ) ) {
        return 'post-' . $post->ID;
    }
}

Poi, nel tuo template header.php chiama semplicemente la funzione e gestisci l'output in una classe del body. Questo esempio presuppone che tu abbia già un paio di classi sul tag <html>.

<html <?php language_attributes(); ?> class="no-js no-svg <?php echo esc_attr( wpse_268339_get_post_class() ); ?>">

Questo produrrà un nome di classe solo se ti trovi su un Post/Page.

In alternativa, se tutte le normali classi del body non causano problemi, puoi semplicemente usare body_class() anche sul tag <html>. La funzione funziona ovunque.

<html <?php body_class(); ?>>
28 mag 2017 03:32:07
Commenti

Preferirei non modificare il file PHP effettivo. Il tema attualmente ha delle classi (non uniche) sull'elemento HTML. Preferirei anche non aggiungere le classi del body all'elemento HTML, poiché sono sicuro che il tema non lo preveda.

Garconis Garconis
28 mag 2017 04:33:11
0

Grazie all'aiuto di questa risposta, ho scoperto che questa soluzione funziona per aggiungere un id. Tuttavia non sono sicuro riguardo all'aggiunta all'attributo 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 dic 2020 16:39:29