Versionarea @import a fișierului style.css din tema părinte

3 oct. 2014, 03:50:31
Vizualizări: 97.1K
Voturi: 29

Context

Am creat o temă copil bazată pe Twenty Thirteen care funcționează destul de bine. După actualizarea temei părinte la versiunea 1.3, am observat un comportament ciudat la stilizare, cauzat de un fișier style.css din tema părinte care era cache-uit.

Iată conținutul fișierului style.css al temei mele copil (fără antet):

/* =Importă stilurile din tema părinte
-------------------------------------------------------------- */
@import url('../twentythirteen/style.css');

Deci fișierul style.css al temei copil nu face altceva decât să importe fișierul style.css al temei părinte.

Am un alt fișier CSS cu personalizările temei copil pe care îl încarc astfel în functions.php:

// Încarcă style.css din tema părinte (mai rapid decât folosind @import în style.css)
$themeVersion = wp_get_theme()->get('Version');

// Încarcă personalizările temei copil
wp_enqueue_style('child_main', get_stylesheet_directory_uri() . '/css/main.css',
    null, $themeVersion);

Aceasta îmi oferă un URL CSS frumos de genul: domain.com/wp-content/themes/toutprettoutbon/css/main.css?ver=1.0.1 care asigură reîncărcarea fișierului CSS când tema copil este actualizată.

Problema

Instrucțiunea @import url('../twentythirteen/style.css'); este complet independentă de versiunea temei părinte. De fapt, tema părinte poate fi actualizată fără a actualiza tema copil, dar browserele vor continua să folosească versiunile cache-uite ale vechiului ../twentythirteen/style.css.

Codul relevant din Twenty Thirteen care încarcă style.css:

function twentythirteen_scripts_styles() {
    // ...

    // Adaugă fontul Genericons, folosit în fișierul principal de stiluri
    wp_enqueue_style( 'genericons', get_template_directory_uri() . '/genericons/genericons.css', array(), '3.03' );

    // Încarcă fișierul principal de stiluri
    wp_enqueue_style( 'twentythirteen-style', get_stylesheet_uri(), array(), '2013-07-18' );
    // Observați folosirea get_stylesheet_uri() care de fapt încarcă child-theme/style.css

    // Încarcă fișierul de stiluri specific pentru 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' );

Pot să mă gândesc la câteva soluții, dar niciuna nu este cu adevărat satisfăcătoare:

  1. Actualizez tema copil de fiecare dată când tema părinte este actualizată pentru a schimba un șir de versiune în style.css (de ex. @import url('../twentythirteen/style.css?ver=NEW_VERSION');). Aceasta creează o legătură inutilă și enervantă între versiunea temei părinte și copil.

  2. În functions.php al temei copil, 1) wp_dequeue_style pentru fișierul style.css al temei copil și 2) wp_enqueue_style pentru fișierul style.css al temei părinte direct CU șir de versiune. Aceasta încurcă ordinea încărcării fișierelor CSS în tema părinte.

  3. Folosesc filtrul style_loader_tag pentru a modifica tag-ul <link> generat pentru style.css și pentru a modifica calea să indice direct către fișierul style.css al temei părinte CU un șir de versiune. Pare destul de obscur pentru o nevoie atât de comună (cache busting).

  4. Copiază conținutul fișierului style.css al temei părinte în fișierul style.css al temei copil. La fel ca la (1), dar puțin mai rapid.

  5. Fac ca fișierul style.css al temei copil să fie un symlink către fișierul style.css al temei părinte. Pare destul de hack-ish...

Am omis ceva? Aveți sugestii?

edit

Am adăugat fișierele genericicons.css și ie.css din tema părinte pentru a clarifica de ce nu pot schimba instrucțiunea CSS @import cu wp_enqueue_style în tema copil. În prezent, cu o instrucțiune @import în fișierul style.css al temei copil, am această ordine în paginile generate:

  1. twentythirteen/genericons/genericons.css -> încărcat de tema părinte
  2. child-theme/style.css -> încărcat de tema părinte, importă twentythirteen/style.css
  3. twentythirteen/css/ie.css -> încărcat de tema părinte
  4. child-theme/css/main.css -> încărcat de tema copil

Dacă încărc fișierul style.css al temei părinte ca dependință a main.css, ordinea devine:

  1. twentythirteen/genericons/genericons.css -> încărcat de tema părinte
  2. child-theme/style.css -> gol, încărcat de tema părinte
  3. twentythirteen/css/ie.css -> încărcat de tema părinte
  4. twentythirteen/style.css -> încărcat de tema copil ca dependință a main.css
  5. child-theme/css/main.css -> încărcat de tema copil

Observați că ie.css este acum inclus înaintea fișierului style.css al temei părinte. Nu vreau să schimb ordinea încărcării fișierelor CSS ale temei părinte pentru că nu pot presupune că acest lucru nu va cauza probleme cu prioritatea regulilor CSS.

5
Comentarii

Niciodată nu folosi @import, în schimb setează fișierul de stil al temei părinte ca dependință a propriului tău fișier de stil.

fuxia fuxia
3 oct. 2014 04:03:52

Știu că nu este cea mai bună abordare, dar este recomandată aici: http://codex.wordpress.org/Child_Themes

bernie bernie
3 oct. 2014 04:09:44

De asemenea, făcând ce ai sugerat nu rezolvă problema mea. Fișierul style.css al temei părinte nu ar fi inclus în același loc ca acum. Tema părinte include alte fișiere CSS care trebuie să fie plasate între style.css al său și fișierul CSS al temei mele copil.

bernie bernie
3 oct. 2014 04:10:54

Te rog să ignori complet codex-ul. Este plin de informații greșite. Folosirea parametrului de dependență va include fișierele de stil în ordinea corectă.

fuxia fuxia
3 oct. 2014 04:11:47

Te rog să vezi ediția mea.

bernie bernie
3 oct. 2014 19:53:33
Toate răspunsurile la întrebare 3
11
19

Nu trebuie să folosești @import. De fapt, este mai bine să nu o faci. Folosirea metodei de încărcare prin enqueue este probabil mai bună din toate punctele de vedere.

Iată partea relevantă din codul temei twentythirteen:

function twentythirteen_scripts_styles() {
...
    // Încarcă fișierul nostru principal de stiluri.
    wp_enqueue_style( 'twentythirteen-style', get_stylesheet_uri(), array(), '2013-07-18' );
...
}
add_action( 'wp_enqueue_scripts', 'twentythirteen_scripts_styles' );

Iată ce ar trebui să faci în codul tău:

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' );

Dacă main.css trebuie să fie încărcat după style.css al părintelui, atunci pur și simplu îl faci dependent de acesta.

Dacă ai și un fișier B.css în tema copil, atunci configurezi dependențele în consecință:

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' );

Asigură-te că dependențele pe care le definești pentru fiecare element reflectă realitatea. Dacă main.css trebuie să vină după B.css, atunci depinde de acesta. Dacă B.css trebuie să vină după style.css al părintelui, atunci B depinde de acesta. Sistemul de încărcare va rezolva ordinea pentru tine.

Și dacă nu folosești style.css al temei copil pentru nimic, atunci nu trebuie să-l încarci deloc. Poate fi doar un placeholder pentru informațiile din header-ul temei tale. Nu-l folosești? Nu-l încărca.

De asemenea, ce anume faci care este atât de dependent de ordinea de încărcare aici? În majoritatea situațiilor, CSS-ului nu îi pasă de ordinea de încărcare. CSS-ul depinde mai mult de specificitatea selectorilor. Dacă vrei să suprascrii ceva, faci selectorul tău mai specific. Poate veni primul, ultimul sau oriunde între, selectorul mai specific câștigă întotdeauna.

Editare

Citind comentariile tale și analizând mai atent codul, văd unde este greșeala. Codul twenty-thirteen încarcă "get_stylesheet_uri()", care în cazul unei teme copil, ar fi fișierul style.css al temei copil, nu al părintelui. De aceea @import funcționează și păstrează aceeași ordine (care, repet, nu contează atât de mult pe cât crezi).

În acest caz, dacă nu vrei să folosești import, aș recomanda să încarci style.css al părintelui direct. Astfel:

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

Codul din functions.php al temei copil rulează primul, deci wp_enqueue_scripts personal va rula primul, iar acesta va încărca style.css al părintelui, pe care tema părinte nu-l încarcă singură (pentru că de fapt încarcă style.css al copilului tău). Prin a nu-l face dependent de nimic, la fel ca părintele, atunci va fi plasat corect în output. Reține că ordinea acestui fișier și genericons.css nu contează, deoarece originalul "twentythirteen-style" nu are genericons.css ca dependență listată.

style.css al copilului tău se va încărca și, sincer, aici ar trebui să pui modificările pentru tema copil, nu într-un main.css separat. Nu te împiedică nimic să pui modificările acolo, dar nu există un motiv real pentru a avea un fișier CSS în plus.

3 oct. 2014 20:25:45
Comentarii

Sunt complet de acord că folosirea @import nu este cea mai bună abordare. Vă rugăm să consultați secțiunea mea "edit" pentru informații mai precise. Nu am nevoi speciale legate de ordonarea fișierelor css. Pur și simplu nu doresc să modific ordonarea internă a fișierelor css ale temei părinte, deoarece aceasta poate cauza probleme cu prioritatea regulilor css.

bernie bernie
3 oct. 2014 22:13:45

Pentru a clarifica, B.css (acum schimbat în ie.css în întrebare) nu face parte din tema mea copil, ci de fapt face parte din tema părinte.

bernie bernie
3 oct. 2014 22:26:46

Dacă doriți ca stilul dumneavoastră să apară după stilul ie.css, atunci faceți ca stilul dumneavoastră să depindă de acesta. Numele său este "twentythirteen-ie". Ordinea este gestionată în întregime de dependențele pe care le declarați, dar din nou, în cazul CSS-ului, ordinea efectivă a acestora în document nu contează de obicei, așa că nu sunt sigur de ce ați fi atât de preocupat de acest aspect.

Otto Otto
3 oct. 2014 23:12:02

Am editat răspunsul meu pentru a include o abordare diferită.

Otto Otto
3 oct. 2014 23:29:48

Da, cred că m-am lăsat dus de valul "necesității" de a păstra ordinea CSS. Dacă ordinea era cu adevărat importantă pentru tema părinte, ar fi trebuit să fie specificată în dependențe.

bernie bernie
4 oct. 2014 17:20:16

"Propriul tău fișier style.css al temei copil se va încărca și, sincer, aici ar trebui să pui modificările pentru tema copil, nu într-un fișier main.css separat." Asta este adevărat, dar vreau să adaug un șir de versiune la CSS-ul temei mele copil.

Dacă folosesc simpla încărcare a fișierului style.css al temei copil din tema părinte, părintele controlează versiunea deoarece apelează enqueue_style. Vreau să pot actualiza tema copil și să schimb șirul de versiune al fișierelor sale de stil pentru a evita cache-ul, independent de versiunea temei părinte.

bernie bernie
4 oct. 2014 17:23:16

Aș fi curios să aud părerea ta despre noul răspuns mult mai simplu pe care tocmai l-am adăugat.

bernie bernie
23 mar. 2015 19:19:45

Actualizarea ta chiar ajută la rezolvarea multor probleme. Tema mea părinte avea bootstrap.css inclus înainte de style.css. Cu abordarea ta, a trebuit doar să specific bootstrap ca dependență pentru parent-style în style.css-ul temei copil. Și restul lucrurilor au funcționat perfect. Mulțumesc!

roshan roshan
3 apr. 2016 18:53:50

Nu e nimic în neregulă cu folosirea @import, nu afectează performanța în niciun fel, te rog verifică codul sursă al temelor copil create cu oricare metodă, vei descoperi că se generează două cereri către server în ambele cazuri. O lectură utilă aici: https://wordpress.org/support/topic/needs-update-12/

bg17aw bg17aw
1 sept. 2017 01:11:49

Nu cred că poți evita încărcarea fișierului copil style.css. Te rog verifică, acesta va fi încărcat chiar dacă nu îl încarci explicit.

bg17aw bg17aw
1 sept. 2017 01:14:42

Nu am suficiente reputații pentru a posta propriul răspuns, dar iată părerea mea: https://pastebin.com/iDr6Hy79

360path 360path
2 apr. 2020 20:51:48
Arată celelalte 6 comentarii
2

Răspunsul meu anterior este excesiv de complicat și poate nu respectă lanțul de dependențe al temei părinte (vezi nota din celălalt răspuns).

Iată o abordare mult mai simplă care ar trebui să funcționeze mult mai bine:

function use_parent_theme_stylesheet() {
    // Folosește fișierul de stil al temei părinte
    return get_template_directory_uri() . '/style.css';
}

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

    // Încarcă fișierul nostru style.css cu versiunea noastră
    wp_enqueue_style('child-theme-style', get_stylesheet_directory_uri() . '/style.css',
        array(), $themeVersion);
}

// Filtrează get_stylesheet_uri() pentru a returna fișierul de stil al temei părinte
add_filter('stylesheet_uri', 'use_parent_theme_stylesheet');

// Încarcă scripturile și stilurile acestei teme (după tema părinte)
add_action('wp_enqueue_scripts', 'my_theme_styles', 20);

Ideea este să filtrăm simplu apelul către get_stylesheet_uri() în tema părinte pentru a returna propriul fișier de stil în locul celui al temei copil. Fișierul de stil al temei copil este încărcat mai târziu în acțiunea my_theme_styles.

23 mar. 2015 19:13:13
Comentarii

Doar pentru clarificare: 1) Codul tău va genera exact același HTML ca și versiunea veche cu @import, fără niciun impact asupra performanței, vor fi două cereri separate către server pentru style.css 2) Acest răspuns elimină complet dependența... 3) Poți verifica ce fac get_template_directory_uri și get_template_stylesheet_uri aici: https://core.trac.wordpress.org/browser/tags/4.8/src/wp-includes/class-wp-theme.php#L9 Din nou, nu este nevoie de cea mai mare parte din acel cod.

bg17aw bg17aw
1 sept. 2017 01:19:58

@bg17aw folosirea wp_enqueue_style adaugă automat un șir de interogare pentru invalidarea cache-ului la URL-ul generat (de ex. ?ver=2013-07-18) bazat pe versiunea temei. Acest lucru nu se face cu o instrucțiune @import.

bernie bernie
14 sept. 2017 21:01:58
6

avertisment

Această soluție nu respectă dependențele temei părinte! Schimbarea numelui handle-ului temei părinte afectează lanțul de dependențe setat în tema părinte. Vezi răspunsul meu mult mai simplu aici.

răspuns original

Deși răspunsul lui Otto este destul de bun, am ajuns la această implementare în functions.php al temei mele copil:

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

    // Deregistrăm style.css care a fost încărcat de tema părinte; vrem
    // să controlăm versiunea noi înșine.
    $parentStyleVersion = $wp_styles->registered[$parentOriginalHandle]->ver;
    $parentDeps = $wp_styles->registered[$parentOriginalHandle]->deps;
    wp_deregister_style($parentOriginalHandle);

    // Încărcăm style.css al temei părinte cu versiunea originală în loc
    // să-l importăm via @import în style.css al temei copil
    wp_register_style($parentNewHandle, get_template_directory_uri() . '/style.css',
        $parentDeps, $parentStyleVersion);

    // Încărcăm style.css al temei noastre cu propria versiune
    $themeVersion = wp_get_theme()->get('Version');
    wp_enqueue_style($parentOriginalHandle, get_stylesheet_directory_uri() . '/style.css',
        [$parentNewHandle], $themeVersion);
}

// Rulează această acțiune după ce tema părinte a încărcat stilurile sale.
add_action('wp_enqueue_scripts', 'my_theme_styles', 20);

Menține ordinea și numerele de versiune ale fișierului style.css al temei părinte, în timp ce controlează versiunea fișierului style.css al temei copil.

6 oct. 2014 21:25:47
Comentarii

Mi se pare incredibil că cel mai popular software pentru bloguri necesită peste 20 de linii de cod doar pentru a ajusta CSS-ul unui temă existentă. Presupun că asta înseamnă securitate jobului.

Carl G Carl G
25 ian. 2015 23:45:39

A trebuit să schimb [$parentNewHandle] în array($parentNewHandle)

Carl G Carl G
26 ian. 2015 00:24:18

@CarlG: sintaxa de array pe care am folosit-o (paranteze pătrate) a fost introdusă în PHP 5.4.

bernie bernie
26 ian. 2015 06:47:14

Pentru cei care votează pozitiv: vă rugăm să consultați alt răspuns al meu care rezolvă problemele acestuia.

bernie bernie
23 mar. 2015 19:21:06

Este o mare neînțelegere, nu este nevoie de nimic din toate acestea. De fapt, vechea metodă @import funcționează la fel de bine, vă rugăm să comparați ambele metode. În ceea ce privește dependența temei copil de tema părinte, nici pentru aceasta nu este nevoie. Fișierul copil style.css este întotdeauna încărcat după cel părinte, cel puțin din testele mele. Aș fi bucuros să fiu contrazis.

bg17aw bg17aw
1 sept. 2017 01:23:01

@bg17aw folosirea wp_enqueue_style adaugă automat un șir de interogare pentru invalidarea cache-ului la URL-ul generat (de ex. ?ver=2013-07-18) pe baza versiunii temei. Acest lucru nu se face printr-o instrucțiune @import.

bernie bernie
14 sept. 2017 21:02:12
Arată celelalte 1 comentarii