Versionamento dell'@import del file style.css del tema genitore

3 ott 2014, 03:50:31
Visualizzazioni: 97.1K
Voti: 29

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:

  1. 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.

  2. Nel file functions.php del mio tema child, 1) fare wp_dequeue_style del file style.css del tema child incluso e 2) fare wp_enqueue_style del file style.css del tema genitore direttamente CON la stringa di versione. Questo sconvolge l'ordine dei CSS in coda nel tema genitore.

  3. Utilizzare il filtro style_loader_tag per modificare il tag CSS <link> generato per style.css e modificare il percorso per puntare direttamente al file style.css del tema genitore CON una stringa di versione. Sembra piuttosto oscuro per un'esigenza così comune (cache busting).

  4. Riversare il file style.css del tema genitore nel file style.css del mio tema child. In realtà è uguale al punto (1), ma un po' più veloce.

  5. Fare in modo che il file style.css del mio tema child sia un symlink al file style.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:

  1. twentythirteen/genericons/genericons.css -> messo in coda dal tema genitore
  2. child-theme/style.css -> messo in coda dal tema genitore, importa twentythirteen/style.css
  3. twentythirteen/css/ie.css -> messo in coda dal tema genitore
  4. 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à:

  1. twentythirteen/genericons/genericons.css -> messo in coda dal tema genitore
  2. child-theme/style.css -> vuoto, messo in coda dal tema genitore
  3. twentythirteen/css/ie.css -> messo in coda dal tema genitore
  4. twentythirteen/style.css -> messo in coda dal tema child come dipendenza di main.css
  5. 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.

5
Commenti

Non usare mai @import, invece imposta il foglio di stile del tema genitore come una dipendenza del tuo foglio di stile.

fuxia fuxia
3 ott 2014 04:03:52

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

bernie bernie
3 ott 2014 04:09:44

Inoltre, fare ciò che hai suggerito non risolve il mio problema. Il style.css del tema genitore non verrebbe incluso nello stesso punto in cui è ora. Il genitore include altri file css che devono trovarsi tra il suo style.css e il css del mio tema figlio.

bernie bernie
3 ott 2014 04:10:54

Per favore ignora completamente il codex. È pieno di informazioni errate. Usare il parametro di dipendenza includerà i fogli di stile nell'ordine corretto.

fuxia fuxia
3 ott 2014 04:11:47

Per favore vedi la mia modifica.

bernie bernie
3 ott 2014 19:53:33
Tutte le risposte alla domanda 3
11
19

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.

3 ott 2014 20:25:45
Commenti

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.

bernie bernie
3 ott 2014 22:13:45

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.

bernie bernie
3 ott 2014 22:26:46

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.

Otto Otto
3 ott 2014 23:12:02

Ho modificato la mia risposta per includere un approccio diverso.

Otto Otto
3 ott 2014 23:29:48

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.

bernie bernie
4 ott 2014 17:20:16

"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.

bernie bernie
4 ott 2014 17:23:16

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

bernie bernie
23 mar 2015 19:19:45

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!

roshan roshan
3 apr 2016 18:53:50

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/

bg17aw bg17aw
1 set 2017 01:11:49

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.

bg17aw bg17aw
1 set 2017 01:14:42

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

360path 360path
2 apr 2020 20:51:48
Mostra i restanti 6 commenti
2

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.

23 mar 2015 19:13:13
Commenti

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.

bg17aw bg17aw
1 set 2017 01:19:58

@bg17aw usando wp_enqueue_style viene automaticamente aggiunta una stringa di query per il cache busting all'URL generato (es. ?ver=2013-07-18) basata sulla versione del tema. Questo non viene fatto con un'istruzione @import.

bernie bernie
14 set 2017 21:01:58
6

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.

6 ott 2014 21:25:47
Commenti

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.

Carl G Carl G
25 gen 2015 23:45:39

Ho dovuto cambiare [$parentNewHandle] in array($parentNewHandle)

Carl G Carl G
26 gen 2015 00:24:18

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

bernie bernie
26 gen 2015 06:47:14

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

bernie bernie
23 mar 2015 19:21:06

È 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.

bg17aw bg17aw
1 set 2017 01:23:01

@bg17aw l'uso di wp_enqueue_style aggiunge automaticamente una stringa di query per il busting della cache all'URL generato (es. ?ver=2013-07-18) basata sulla versione del tema. Questo non viene fatto con un'istruzione @import.

bernie bernie
14 set 2017 21:02:12
Mostra i restanti 1 commenti