Versionamento dell'@import del file style.css del tema genitore
Contesto
Ho creato un tema child basato su Twenty Thirteen che funziona abbastanza bene. Dopo aver aggiornato il tema genitore alla versione 1.3, ho notato un comportamento strano con lo stile, causato da una versione in cache del file style.css
del tema genitore.
Ecco il contenuto del file style.css
del mio tema child (omettendo le intestazioni)
/* =Importa gli stili dal tema genitore
-------------------------------------------------------------- */
@import url('../twentythirteen/style.css');
Quindi il file style.css
del tema child non fa altro che importare il file style.css
del tema genitore.
Ho anche un altro file css con le personalizzazioni del mio tema child che metto in coda così nel file functions.php
:
// Mette in coda il file style.css del tema genitore (più veloce che usare @import nel nostro style.css)
$themeVersion = wp_get_theme()->get('Version');
// Mette in coda le personalizzazioni del tema child
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.1
che assicura che il foglio di stile venga ricaricato quando il tema child viene aggiornato.
Ora il problema
L'istruzione @import url('../twentythirteen/style.css');
è completamente indipendente dalla versione sottostante del tema genitore. Infatti, il tema genitore può essere aggiornato senza aggiornare il tema child, ma i browser continueranno a utilizzare versioni memorizzate nella cache del vecchio file ../twentythirteen/style.css
.
Codice rilevante in Twenty Thirteen che mette in coda il file style.css
:
function twentythirteen_scripts_styles() {
// ...
// Aggiunge il font Genericons, utilizzato nel foglio di stile principale.
wp_enqueue_style( 'genericons', get_template_directory_uri() . '/genericons/genericons.css', array(), '3.03' );
// Carica il nostro foglio di stile principale.
wp_enqueue_style( 'twentythirteen-style', get_stylesheet_uri(), array(), '2013-07-18' );
// Nota l'uso di get_stylesheet_uri() che in realtà mette in coda child-theme/style.css
// Carica il foglio di stile specifico per Internet Explorer.
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 a alcuni modi per risolvere questo problema, ma nessuno è davvero soddisfacente:
Aggiornare il mio tema child ogni volta che il tema genitore viene aggiornato per modificare una stringa di versione in
style.css
(ad es.@import url('../twentythirteen/style.css?ver=NEW_VERSION');
). Ciò crea un legame inutile e fastidioso tra la versione del tema genitore e quella del child.Nel file
functions.php
del mio tema child, 1) farewp_dequeue_style
del filestyle.css
del tema child incluso e 2) farewp_enqueue_style
del filestyle.css
del tema genitore direttamente CON la stringa di versione. Questo sconvolge l'ordine dei CSS in coda nel tema genitore.Utilizzare il filtro
style_loader_tag
per modificare il tag CSS<link>
generato perstyle.css
e modificare il percorso per puntare direttamente al filestyle.css
del tema genitore CON una stringa di versione. Sembra piuttosto oscuro per un'esigenza così comune (cache busting).Riversare il file
style.css
del tema genitore nel filestyle.css
del mio tema child. In realtà è uguale al punto (1), ma un po' più veloce.Fare in modo che il file
style.css
del mio tema child sia un symlink al filestyle.css
del tema genitore. Questo sembra abbastanza approssimativo...
Mi sono perso qualcosa? Qualche suggerimento?
edit
Ho aggiunto i fogli di stile genericicons.css
e ie.css
nel tema genitore per chiarire perché non posso cambiare l'istruzione CSS @import
in wp_enqueue_style
nel mio tema child. Attualmente, con un'istruzione @import
nel file style.css
del mio tema child, ho questo ordine nelle pagine generate:
- twentythirteen/genericons/genericons.css -> messo in coda dal tema genitore
- child-theme/style.css -> messo in coda dal tema genitore, importa twentythirteen/style.css
- twentythirteen/css/ie.css -> messo in coda dal tema genitore
- child-theme/css/main.css -> messo in coda dal tema child
Se metto in coda il file style.css
del genitore come dipendenza di main.css
, questo diventerà:
- twentythirteen/genericons/genericons.css -> messo in coda dal tema genitore
- child-theme/style.css -> vuoto, messo in coda dal tema genitore
- twentythirteen/css/ie.css -> messo in coda dal tema genitore
- twentythirteen/style.css -> messo in coda dal tema child come dipendenza di main.css
- child-theme/css/main.css -> messo in coda dal tema child
Si noti che ie.css è ora incluso prima del file style.css
del tema genitore. Non voglio cambiare l'ordine di accodamento dei file CSS del tema genitore perché non posso presumere che questo non causerà problemi con la priorità delle regole CSS.

Non devi usare @import. In effetti, è meglio evitarlo. Utilizzare un approccio con enqueue è probabilmente la scelta migliore in ogni caso.
Ecco la parte rilevante del codice di twentythirteen:
function twentythirteen_scripts_styles() {
...
// Carica il foglio di stile principale
wp_enqueue_style( 'twentythirteen-style', get_stylesheet_uri(), array(), '2013-07-18' );
...
}
add_action( 'wp_enqueue_scripts', 'twentythirteen_scripts_styles' );
Ecco cosa dovresti fare nel tuo codice:
function child_scripts_styles() {
wp_enqueue_style( 'child-style', get_stylesheet_directory_uri().'/css/main.css', array('twentythirteen-style'), 'LA_TUA_VERSIONE_TEMA' );
}
add_action( 'wp_enqueue_scripts', 'child_scripts_styles' );
Se il tuo main.css deve essere caricato dopo lo style.css del tema genitore, basta renderlo dipendente da quest'ultimo.
Ora, se hai anche un file B.css nel child theme, imposti le dipendenze di conseguenza:
function child_scripts_styles() {
wp_enqueue_style( 'child-B-style', get_stylesheet_directory_uri().'/B.css', array('twentythirteen-style'), 'LA_TUA_VERSIONE_TEMA' );
wp_enqueue_style( 'child-style', get_stylesheet_directory_uri().'/css/main.css', array('child-B-style'), 'LA_TUA_VERSIONE_TEMA' );
}
add_action( 'wp_enqueue_scripts', 'child_scripts_styles' );
Assicurati che le dipendenze che definisci per ogni elemento riflettano effettivamente le dipendenze reali. Se main.css deve essere caricato dopo B.css, allora dipende da esso. Se B.css deve essere caricato dopo lo style.css del tema genitore, allora B dipende da quello. Il sistema di enqueue risolverà l'ordinamento per te.
E se in realtà non stai utilizzando lo style.css del child theme per nulla, non sei obbligato a caricarlo. Può essere semplicemente un segnaposto per le informazioni dell'header del tuo tema. Non lo usi? Non caricarlo.
Inoltre, cosa stai facendo che è così dipendente dall'ordine di caricamento qui? Nella maggior parte dei casi, al CSS non interessa l'ordine di caricamento. Il CSS dipende maggiormente dalla specificità dei selettori. Se vuoi sovrascrivere qualcosa, rendi il tuo selettore più specifico. Può essere il primo, l'ultimo o qualsiasi posizione intermedia, il selettore più specifico vince sempre.
Modifica
Leggendo i tuoi commenti e osservando più da vicino il codice, vedo dove sta l'errore. Il codice di twenty-thirteen sta caricando "get_stylesheet_uri()", che nel caso di un child theme sarebbe il file style.css del child theme, non quello del genitore. Ecco perché l'@import funziona e mantiene lo stesso ordine (che, ripeto, non è così importante come pensi).
In tal caso, se non vuoi usare l'import, ti consiglio di caricare direttamente lo style.css del tema genitore. In questo modo:
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 nel functions.php del child theme viene eseguito per primo, quindi il tuo wp_enqueue_scripts verrà eseguito per primo e caricherà lo style.css del tema genitore, cosa che il tema genitore non fa da solo (perché in realtà sta caricando lo style.css del tuo child theme). Non rendendolo dipendente da nulla, come nel caso del tema genitore, verrà semplicemente inserito nell'output correttamente. Nota che l'ordine di questo file e di genericons.css non ha importanza, perché l'originale "twentythirteen-style" non ha genericons.css come dipendenza elencata.
Il tuo style.css del child theme verrà caricato e, onestamente, è qui che dovresti inserire le modifiche per il child theme, non in un main.css separato. Non c'è nulla che ti impedisca di inserire le tue modifiche lì, ma non c'è una vera ragione per avere un file CSS aggiuntivo.

Sono completamente d'accordo che gli @import
non siano la soluzione migliore. Per favore consulta la mia sezione "modifica" per informazioni più precise. Non ho esigenze particolari riguardo all'ordinamento dei css. Semplicemente non voglio modificare l'ordinamento interno dei file css del tema genitore che potrebbe causare problemi con la priorità delle regole css.

Per chiarire, B.css (ora cambiato in ie.css nella domanda) non fa parte del mio child theme, ma in realtà è parte del tema genitore.

Se vuoi che il tuo stile venga dopo lo stile ie.css, allora fai in modo che il tuo stile dipenda da esso. Il suo nome è "twentythirteen-ie". L'ordine è gestito interamente dalle dipendenze che dichiari, ma ancora una volta, con i CSS, l'ordine effettivo nel documento di solito non ha importanza, quindi non sono sicuro del perché te ne preoccupi così tanto.

Sì, immagino di essermi lasciato trasportare dalla "necessità" di mantenere l'ordine del css. Se l'ordine fosse davvero importante per il tema genitore, dovrebbe essere indicato nelle dipendenze.

"Il tuo style.css del child theme verrà caricato, e onestamente, è qui che dovresti inserire le tue modifiche per il child theme, non in un main.css separato." Questo è vero, ma voglio aggiungere una stringa di versione al css del mio child theme.
Se uso semplicemente l'enqueuing del tema genitore per lo style.css del child theme, il genitore controlla la versione poiché è lui che chiama enqueue_style
. Voglio poter aggiornare il child theme e cambiare la stringa di versione dei suoi fogli di stile per il cache busting indipendentemente dalla versione del tema genitore.

Mi piacerebbe conoscere il tuo parere sulla nuova risposta molto più semplice che ho appena aggiunto.

Il tuo aggiornamento aiuta davvero a risolvere molti problemi. Il mio tema parent aveva bootstrap.css incluso prima di style.css. Con il tuo approccio ho solo dovuto specificare bootstrap come dipendenza per parent-style nel file style.css del child theme. E tutto il resto si sistema da solo. Grazie!

Non c'è nulla di sbagliato nell'usare @import
, non influisce sulle prestazioni in alcun modo, per favore controlla il codice sorgente dei child theme creati con entrambi i metodi, troverai due richieste al server generate in entrambi i casi. Una buona lettura qui: https://wordpress.org/support/topic/needs-update-12/

Penso che non si possa evitare il caricamento del file style.css
del child theme. Verifica, verrà caricato anche se non lo metti in coda specificamente.

Non ho abbastanza reputazione per pubblicare una mia risposta, ma ecco la mia soluzione: https://pastebin.com/iDr6Hy79

La mia risposta precedente è eccessivamente complicata e potenzialmente non rispetta la catena di dipendenze del tema genitore (vedi nota nell'altra risposta).
Ecco un approccio molto più semplice che dovrebbe funzionare meglio:
function use_parent_theme_stylesheet() {
// Utilizza il foglio di stile del tema genitore
return get_template_directory_uri() . '/style.css';
}
function my_theme_styles() {
$themeVersion = wp_get_theme()->get('Version');
// Includi il nostro style.css con la nostra versione
wp_enqueue_style('child-theme-style', get_stylesheet_directory_uri() . '/style.css',
array(), $themeVersion);
}
// Filtra get_stylesheet_uri() per restituire il foglio di stile del tema genitore
add_filter('stylesheet_uri', 'use_parent_theme_stylesheet');
// Includi script e stili di questo tema (dopo il tema genitore)
add_action('wp_enqueue_scripts', 'my_theme_styles', 20);
L'idea è semplicemente di filtrare la chiamata a get_stylesheet_uri()
nel tema genitore per fargli restituire il proprio foglio di stile invece di quello del tema figlio. Il foglio di stile del tema figlio viene poi incluso successivamente tramite l'hook my_theme_styles
.

Solo per completezza: 1) Il tuo codice genererà lo stesso identico HTML della vecchia versione con @import
, nessun impatto sulle prestazioni, ci saranno due richieste separate di style.css al server 2) Questa soluzione elimina completamente la questione delle dipendenze... 3) Puoi verificare cosa fanno get_template_directory_uri
e get_template_stylesheet_uri
qui: https://core.trac.wordpress.org/browser/tags/4.8/src/wp-includes/class-wp-theme.php#L9 Ancora una volta, la maggior parte di quel codice non è necessaria.

avviso
Questa soluzione non rispetta le dipendenze del tema genitore! Cambiando il nome dell'handle del tema genitore si influisce sulla catena delle dipendenze impostata nel tema genitore. Vedi la mia soluzione molto più semplice nella mia altra risposta.
risposta originale
Sebbene la risposta di Otto sia abbastanza buona, alla fine ho implementato questo nel functions.php del mio tema child
function my_theme_styles() {
global $wp_styles;
$parentOriginalHandle = 'twentythirteen-style';
$parentNewHandle = 'parent-style';
// Deregistra il nostro style.css che era stato accodato dal tema genitore; vogliamo
// controllare noi stessi la versione.
$parentStyleVersion = $wp_styles->registered[$parentOriginalHandle]->ver;
$parentDeps = $wp_styles->registered[$parentOriginalHandle]->deps;
wp_deregister_style($parentOriginalHandle);
// Accoda lo style.css del tema genitore con la versione originale invece
// di importarlo via @import nello style.css del tema child
wp_register_style($parentNewHandle, get_template_directory_uri() . '/style.css',
$parentDeps, $parentStyleVersion);
// Accoda il nostro style.css con la nostra versione
$themeVersion = wp_get_theme()->get('Version');
wp_enqueue_style($parentOriginalHandle, get_stylesheet_directory_uri() . '/style.css',
[$parentNewHandle], $themeVersion);
}
// Esegui questa azione dopo che il tema genitore ha accodato i suoi stili.
add_action('wp_enqueue_scripts', 'my_theme_styles', 20);
Mantiene l'ordinamento e i numeri di versione dello style.css
del tema genitore mentre controlla la versione dello style.css
del tema child.

Mi sconvolge che il software di blog più popolare richieda 20+ righe di codice solo per modificare il CSS di un tema esistente. Immagino che sia sicurezza lavorativa.

@CarlG : la sintassi di array che ho usato (parentesi quadre) è stata introdotta in PHP 5.4.

Per chi vota positivo: vi prego di vedere la mia altra risposta che risolve i problemi di questa.

È tutto un enorme malinteso, non c'è bisogno di nulla di tutto ciò. In effetti, il vecchio metodo @import
funziona altrettanto bene, vi invito a confrontare entrambi i metodi. Per quanto riguarda la dipendenza del tema figlio dal tema genitore, non ce n'è bisogno neanche lì. Il file style.css
del tema figlio viene sempre caricato dopo quello del genitore, almeno dai miei test. Sarei felice di essere smentito.
