Versioning @import of style.css del tema principale


28

Contesto

Ho creato un tema per bambini basato su Twenty Thirteen che funziona abbastanza bene. Dopo aver aggiornato il tema principale alla versione 1.3, ho notato un comportamento strano con lo stile causato da un tema principale memorizzato nella cache style.css.

Ecco il contenuto del tema di mio figlio style.css(omettendo le intestazioni)

/* =Imports styles from the parent theme
-------------------------------------------------------------- */
@import url('../twentythirteen/style.css');

Quindi il tema figlio style.cssnon fa altro che importare il tema principale style.css.

Ho anche un altro file CSS con le personalizzazioni del tema di mio figlio che accodero così in functions.php:

// Enqueue parent theme's style.css (faster than using @import in our style.css)
$themeVersion = wp_get_theme()->get('Version');

// Enqueue child theme customizations
wp_enqueue_style('child_main', get_stylesheet_directory_uri() . '/css/main.css',
    null, $themeVersion);

Questo mi dà un URL CSS molto bello come questo: domain.com/wp-content/themes/toutprettoutbon/css/main.css?ver=1.0.1questo assicura che il foglio di stile venga ricaricato quando il tema figlio viene aggiornato.

Ora il problema

L'istruzione @import url('../twentythirteen/style.css');è completamente indipendente dalla versione del tema genitore sottostante. In effetti, il tema principale può essere aggiornato senza aggiornare il tema secondario, ma i browser useranno comunque le versioni memorizzate nella cache del vecchio ../twentythirteen/style.css.

Codice rilevante in Twenty Thirteen che accoda il style.css:

function twentythirteen_scripts_styles() {
    // ...

    // Add Genericons font, used in the main stylesheet.
    wp_enqueue_style( 'genericons', get_template_directory_uri() . '/genericons/genericons.css', array(), '3.03' );

    // Loads our main stylesheet.
    wp_enqueue_style( 'twentythirteen-style', get_stylesheet_uri(), array(), '2013-07-18' );
    // Note usage of get_stylesheet_uri() which actually enqueues child-theme/style.css

    // Loads the Internet Explorer specific stylesheet.
    wp_enqueue_style( 'twentythirteen-ie', get_template_directory_uri() . '/css/ie.css', array( 'twentythirteen-style' ), '2013-07-18' );
}
add_action( 'wp_enqueue_scripts', 'twentythirteen_scripts_styles' );

Posso pensare ad alcuni modi per risolvere questo problema, ma nessuno è davvero soddisfacente:

  1. Aggiorna il tema di mio figlio ogni volta che il tema principale viene aggiornato per modificare una stringa di versione in style.css(ad es @import url('../twentythirteen/style.css?ver=NEW_VERSION');.). Ciò crea un collegamento non necessario e fastidioso tra la versione del tema padre e il figlio.

  2. In mio figlio functions.php, 1) wp_dequeue_styleil tema figlio incluso style.csse 2) wp_enqueue_styleil tema genitore è style.cssdirettamente CON stringa di versione. Questo incasina l'ordine dei CSS in coda nel tema principale.

  3. Utilizzare il style_loader_tagfiltro per modificare il <link>tag css generato per style.csse modificare il percorso in modo che punti direttamente al tema padrestyle.css CON una stringa di versione. Sembra piuttosto oscuro per un bisogno così comune (busting della cache).

  4. Scarica il tema principale style.cssin quello di mio figlio style.css. Lo stesso di (1) in realtà, ma un po 'più veloce.

  5. Fai in modo che il tema di mio figlio style.csssia un collegamento simbolico al tema principale style.css. Questo sembra abbastanza hacker ...

Ho perso qualcosa? Eventuali suggerimenti?

modificare

Aggiunti genericicons.csse ie.cssfogli di stile nel tema principale per chiarire perché non riesco a cambiare l' @importistruzione css wp_enqueue_stylenel tema mio figlio. Attualmente, con una @importdichiarazione nel tema di mio figlio style.css, ho questo ordine nelle pagine generate:

  1. venti tredici / genericons / genericons.css -> accodati dal tema principale
  2. child-theme / style.css -> accodato dal tema principale, @imports twentythirteen / style.css
  3. venti tredici / css / ie.css -> accodato dal tema principale
  4. tema-bambino / css / main.css -> accodato dal tema figlio

Se accoda i genitori style.csscome dipendenza di main.css, questo diventerà:

  1. venti tredici / genericons / genericons.css -> accodati dal tema principale
  2. child-theme / style.css -> vuoto, accodato dal tema principale
  3. venti tredici / css / ie.css -> accodato dal tema principale
  4. twentythirteen / style.css -> accodato dal tema figlio come dipendenza di main.css
  5. tema-bambino / css / main.css -> accodato dal tema figlio

Nota che ie.css è ora incluso prima del tema principale style.css. Non voglio cambiare l'ordine di accodamento dei file CSS del tema principale perché non posso presumere che ciò non causerà problemi con la priorità delle regole CSS.


5
Non usare mai @import, imposta invece il foglio di stile del tema principale come dipendenza del tuo foglio di stile .
fuxia

So che non è l'approccio migliore ma è consigliato qui: codex.wordpress.org/Child_Themes
bernie

Inoltre, fare ciò che hai suggerito non risolve il mio problema. Il tema principale style.cssnon verrebbe incluso nello stesso posto in cui è ora. Il genitore include altri file css che devono trovarsi tra i suoi style.csscss e quelli di mio figlio.
Bernie,

3
Ignora completamente il codice. È pieno di disinformazione. L'uso del parametro di dipendenza includerà i fogli di stile nell'ordine corretto.
fuxia

Si prega di vedere la mia modifica.
Bernie,

Risposte:


19

Non è necessario utilizzare @import. È meglio non farlo, in realtà. L'uso di un approccio accattivante è probabilmente meglio tutto intorno.

Ecco la parte rilevante del codice di ventitré:

function twentythirteen_scripts_styles() {
...
    // Loads our main stylesheet.
    wp_enqueue_style( 'twentythirteen-style', get_stylesheet_uri(), array(), '2013-07-18' );
...
}
add_action( 'wp_enqueue_scripts', 'twentythirteen_scripts_styles' );

Ecco cosa fai nel tuo codice:

function child_scripts_styles() {
    wp_enqueue_style( 'child-style', get_stylesheet_directory_uri().'/css/main.css', array('twentythirteen-style'), 'YOUR_THEME_VERSION' );
}
add_action( 'wp_enqueue_scripts', 'child_scripts_styles' );

Se il tuo main.css deve seguire il style.css del genitore, allora devi solo dipenderlo.

Ora, se hai anche un B.css nel figlio, allora imposti le dipendenze di conseguenza:

function child_scripts_styles() {
    wp_enqueue_style( 'child-B-style', get_stylesheet_directory_uri().'/B.css', array('twentythirteen-style'), 'YOUR_THEME_VERSION' );
    wp_enqueue_style( 'child-style', get_stylesheet_directory_uri().'/css/main.css', array('child-B-style'), 'YOUR_THEME_VERSION' );
}
add_action( 'wp_enqueue_scripts', 'child_scripts_styles' );

Rendi le dipendenze che definisci per ciascun elemento effettivamente riflettenti su cosa siano realmente tali dipendenze. Se main.css deve venire dopo B.css, allora dipende da esso. Se B.css deve seguire lo stile.css del genitore, allora B dipende da quello. Il sistema di accodamento lo risolverà per te.

E se in realtà non stai usando style.css del bambino per nulla, allora non devi affatto accodarlo . Può essere solo un segnaposto per contenere le informazioni dell'intestazione del tema. Non lo usi? Non caricarlo

Inoltre, cosa stai facendo esattamente che dipende così dall'ordinare qui? Ai CSS non importa l'ordine di caricamento nella maggior parte delle situazioni. Il CSS dipende maggiormente dalla specificità dei selettori. Se vuoi sovrascrivere qualcosa, rendi il tuo selettore più specifico. Può venire prima, o per ultimo, o qualsiasi altra via di mezzo, vince sempre il selettore più specifico.

modificare

Leggendo i tuoi commenti e guardando più da vicino il codice, vedo dove si trova l'errore. Il codice tredici è accodando "get_stylesheet_uri ()", che in un caso a tema figlio sarebbe il file style.css del tema figlio, non il file del genitore. Ecco perché @import funziona e mantiene lo stesso ordine (che di nuovo, non importa quasi quanto pensi che faccia).

In tal caso, se non si desidera utilizzare l'importazione, consiglierei di accodare direttamente il file style.css del genitore. Così:

function child_scripts_styles() {
    wp_enqueue_style( 'parent-style', get_template_directory_uri().'/style.css', array() );
}
add_action( 'wp_enqueue_scripts', 'child_scripts_styles' );

Il codice nelle funzioni.php del tema figlio viene eseguito per primo, quindi i tuoi wp_enqueue_scripts verranno eseguiti per primi, e questo accoderà lo stile.css del tema principale, che il tema principale non sta facendo da solo (perché in realtà accoda lo stile.css di tuo figlio). Non facendolo dipendere da nulla, come il genitore, quindi viene semplicemente inserito correttamente nell'output. Notare che l'ordine di questo file e il file genericons.css non ha importanza, poiché l'originale "stile trediciquattro" non ha il genericons.css come dipendenza elencata.

Lo style.css di tuo figlio verrà caricato e, onestamente, è qui che dovresti inserire le modifiche per il tema child, non in un main.css separato. Non c'è nulla che ti impedisca di apportare le modifiche lì, ma non c'è alcun motivo reale per avere un file CSS aggiuntivo.


Concordo pienamente sul fatto che i @imports non sono il modo migliore di procedere. Si prega di consultare la mia sezione "modifica" per informazioni più precise. Non ho particolari esigenze in merito all'ordinazione di CSS. Semplicemente non voglio modificare l'ordinamento interno dei file CSS del tema principale che può causare problemi con priorità alle regole CSS.
Bernie,

Per chiarire, B.css (ora cambiato in ie.css in questione) non fa parte del tema di mio figlio, ma in realtà fa parte del tema principale.
Bernie,

2
Se vuoi che il tuo stile segua lo stile ie.css, allora fai in modo che il tuo stile dipenda da esso. Il suo nome è "ventitredici-ie". L'ordine è interamente gestito da quali dipendenze dichiari, ma di nuovo, con i CSS, il loro ordine effettivo nel documento di solito non ha importanza, quindi non sono sicuro del perché ti interessi troppo.
Otto,

2
Modificato la mia risposta per includere un approccio diverso.
Otto,

Sì, credo di essermi lasciato trasportare dalla "necessità" di mantenere l'ordinamento dei CSS. Se l'ordine era davvero importante per il tema principale, dovrebbe essere indicato nelle dipendenze.
Bernie,

9

La mia risposta precedente è eccessivamente complicata e potenzialmente non rispetta la catena di dipendenze del tema principale (vedi nota in altre risposte).

Ecco un altro approccio molto più semplice che dovrebbe funzionare molto meglio:

function use_parent_theme_stylesheet() {
    // Use the parent theme's stylesheet
    return get_template_directory_uri() . '/style.css';
}

function my_theme_styles() {
    $themeVersion = wp_get_theme()->get('Version');

    // Enqueue our style.css with our own version
    wp_enqueue_style('child-theme-style', get_stylesheet_directory_uri() . '/style.css',
        array(), $themeVersion);
}

// Filter get_stylesheet_uri() to return the parent theme's stylesheet 
add_filter('stylesheet_uri', 'use_parent_theme_stylesheet');

// Enqueue this theme's scripts and styles (after parent theme)
add_action('wp_enqueue_scripts', 'my_theme_styles', 20);

L'idea è semplicemente di filtrare la chiamata a get_stylesheet_uri()nel tema principale per restituire il proprio foglio di stile anziché quello del tema figlio. Il foglio di stile del tema figlio viene poi accodato successivamente nel gancio di azione my_theme_styles.


Solo per la cronaca: 1) Il tuo codice genererà lo stesso html esatto dell'utilizzo della @importversione precedente, senza alcun impatto sulle prestazioni, ci saranno due richieste style.css separate per il server 2) Questa risposta lascia cadere tutta la dipendenza insieme ... 3) Puoi controllare cosa get_template_directory_urie cosa get_template_stylesheet_uristanno facendo qui: core.trac.wordpress.org/browser/tags/4.8/src/wp-includes/… Ancora una volta, non è necessario per gran parte di quel codice.
bg17aw,

1
@ bg17aw using wp_enqueue_styleaggiunge automaticamente una stringa di query di busting della cache all'URL che genera (ad es. ?ver=2013-07-18) in base alla versione del tema. Questo non è fatto da una @importdichiarazione.
Bernie,

2

avvertimento

Questa soluzione non rispetta le dipendenze del tema principale ! La modifica del nome dell'handle del tema principale influisce sulla catena di dipendenze impostata nel tema principale. Vedi la mia altra risposta molto più semplice .

risposta originale

Sebbene la risposta di Otto sia abbastanza buona, ho finito con questo nelle funzioni.php di mio figlio

function my_theme_styles() {
    global $wp_styles;
    $parentOriginalHandle = 'twentythirteen-style';
    $parentNewHandle = 'parent-style';

    // Deregister our style.css which was enqueued by the parent theme; we want
    // to control the versioning ourself.
    $parentStyleVersion = $wp_styles->registered[$parentOriginalHandle]->ver;
    $parentDeps = $wp_styles->registered[$parentOriginalHandle]->deps;
    wp_deregister_style($parentOriginalHandle);

    // Enqueue the parent theme's style.css with whatever version it used instead
    // of @import-ing it in the child theme's style.css
    wp_register_style($parentNewHandle, get_template_directory_uri() . '/style.css',
        $parentDeps, $parentStyleVersion);

    // Enqueue our style.css with our own version
    $themeVersion = wp_get_theme()->get('Version');
    wp_enqueue_style($parentOriginalHandle, get_stylesheet_directory_uri() . '/style.css',
        [$parentNewHandle], $themeVersion);
}

// Run this action action the parent theme has enqueued its styles.
add_action('wp_enqueue_scripts', 'my_theme_styles', 20);

Mantiene l' style.cssordinamento e i numeri di versione del tema padre controllando la versione del tema figlio style.css.


5
Mi sorprende che il software per blog più popolare richiede oltre 20 righe di codice solo per modificare il CSS di un tema esistente. Immagino sia la sicurezza del lavoro.
Carl G,

Ho dovuto cambiare [$parentNewHandle]inarray($parentNewHandle)
Carl G

@CarlG: la sintassi dell'array che ho usato (parentesi) è stata introdotta in PHP 5.4.
Bernie,

Ai votanti: per favore vedi la mia altra risposta che risolve problemi con questo.
Bernie,

È tutto un grande fraintendimento, non c'è bisogno di nulla di tutto ciò. In effetti, il vecchio @importmetodo funziona altrettanto bene, si prega di confrontare entrambi i metodi. Per quanto riguarda la dipendenza del tema figlio dal tema principale, non è nemmeno necessario. Il bambino style.cssviene sempre caricato dopo il genitore, almeno dai miei test. Adoro essere smentito.
bg17aw,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.