Wersjonowanie @import style.css motywu nadrzędnego

28

Kontekst

Zbudowałem motyw potomny na podstawie Twenty Thirteen, który działa całkiem dobrze. Po zaktualizowaniu motywu nadrzędnego do wersji 1.3 zauważyłem dziwne zachowanie w stylu, które było spowodowane buforowanym motywem nadrzędnym style.css.

Oto treść motywu mojego dziecka style.css(z pominięciem nagłówków)

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

Zatem motyw potomny style.cssnie robi nic poza importowaniem motywu macierzystego style.css.

Mam również inny plik css z dostosowaniami motywu podrzędnego, które umieszczam w kolejce tak 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);

Daje mi to bardzo ładny adres URL css: domain.com/wp-content/themes/toutprettoutbon/css/main.css?ver=1.0.1zapewnia to, że arkusz stylów zostanie ponownie załadowany, gdy motyw potomny zostanie zaktualizowany.

Teraz problem

Instrukcja @import url('../twentythirteen/style.css');jest całkowicie niezależna od podstawowej wersji motywu nadrzędnego. W rzeczywistości motyw nadrzędny można zaktualizować bez aktualizacji motywu podrzędnego, ale przeglądarki nadal będą używać starych wersji z pamięci podręcznej ../twentythirteen/style.css.

Odpowiedni kod w Twenty Thirteen, który wymienia 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' );

Mogę wymyślić kilka sposobów rozwiązania tego problemu, ale żaden z nich nie jest naprawdę zadowalający:

  1. Aktualizuj motyw podrzędny za każdym razem, gdy motyw nadrzędny jest aktualizowany, aby zmienić ciąg wersji w style.css(np @import url('../twentythirteen/style.css?ver=NEW_VERSION');.). Tworzy to niepotrzebne i irytujące połączenie między wersją motywu nadrzędnego a dzieckiem.

  2. W moich dziecka functions.php, 1) wp_dequeue_styledołączony dziecko motywu style.cssi 2) dominującym tematem jest bezpośrednio z wersją ciąg. Zmienia to kolejność css w kolejce w motywie nadrzędnym.wp_enqueue_stylestyle.css

  3. Użyj style_loader_tagfiltru, aby zmodyfikować wygenerowany <link>znacznik css style.cssi zmodyfikować ścieżkę, aby wskazywała bezpośrednio na motyw nadrzędnystyle.css Z łańcuchem wersji. Wydaje się raczej niejasne w przypadku tak powszechnej potrzeby (niszczenie pamięci podręcznej).

  4. Zrzuć motyw nadrzędny do motywu style.cssmojego potomka style.css. To samo co (1), ale trochę szybciej.

  5. Niech motyw mojego dziecka style.cssbędzie dowiązaniem symbolicznym do motywu nadrzędnego style.css. To wydaje się dość hackerskie ...

Czy coś przeoczyłem? Jakieś sugestie?

edytować

Dodano genericicons.cssi ie.cssstylizuję arkusze w motywie nadrzędnym, aby wyjaśnić, dlaczego nie mogę zmienić instrukcji @importcss wp_enqueue_stylew moim motywie potomnym. Obecnie z @importoświadczeniem w motywie mojego dziecka style.cssmam następującą kolejność na wygenerowanych stronach:

  1. twentythirteen / genericons / genericons.css -> kolejkowane przez motyw nadrzędny
  2. child-theme / style.css -> kolejkowane przez temat nadrzędny, @imports twentythirteen / style.css
  3. twentythirteen / css / ie.css -> kolejkowane przez motyw nadrzędny
  4. child-theme / css / main.css -> kolejkowane przez motyw potomny

Jeśli uznaję rodzic style.cssza zależność main.css, będzie to:

  1. twentythirteen / genericons / genericons.css -> kolejkowane przez motyw nadrzędny
  2. child-theme / style.css -> puste, kolejkowane przez motyw nadrzędny
  3. twentythirteen / css / ie.css -> kolejkowane przez motyw nadrzędny
  4. twentythirteen / style.css -> kolejkowane przez motyw potomny jako zależność main.css
  5. child-theme / css / main.css -> kolejkowane przez motyw potomny

Pamiętaj, że ie.css jest teraz dołączony przed motywem nadrzędnym style.css. Nie chcę zmieniać kolejności kolejkowania plików css tematu nadrzędnego, ponieważ nie mogę zakładać, że nie spowoduje to problemów z priorytetem reguł css.

bernie
źródło
5
Nigdy nie używaj @import, zamiast tego ustaw arkusz stylów motywu nadrzędnego jako zależność własnego arkusza stylów .
fuxia
Wiem, że nie jest to najlepsze podejście, ale jest zalecane tutaj: codex.wordpress.org/Child_Themes
bernie
Robienie tego, co zasugerowałeś, nie rozwiązuje mojego problemu. Temat nadrzędny style.cssnie zostanie uwzględniony w tym samym miejscu, co teraz. Nadrzędny zawiera inne pliki css, które muszą znajdować się między css jego style.cssi mojego podrzędnego motywu.
bernie
3
Proszę całkowicie zignorować kodeks. Jest pełen dezinformacji. Użycie parametru zależności uwzględni arkusze stylów we właściwej kolejności.
fuxia
Proszę zobaczyć moją edycję.
bernie

Odpowiedzi:

19

Nie musisz używać @import. Właściwie najlepiej tego nie robić. Korzystanie z kolejkowania jest prawdopodobnie lepsze dookoła.

Oto odpowiednia część kodu dwudziestego:

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

Oto, co robisz w kodzie:

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

Jeśli twój main.css musi być zgodny ze stylem.css rodzica, po prostu uzależnij go od tego.

Teraz, jeśli masz również B.css w dziecku, to odpowiednio skonfiguruj zależności:

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

Spraw, aby zależności zdefiniowane dla każdego elementu odzwierciedlały rzeczywiste zależności. Jeśli main.css musi pojawić się po B.css, to zależy od tego. Jeśli B.css musi wystąpić po stylu style.css rodzica, B zależy od tego. System kolejki załatwi to za ciebie.

A jeśli tak naprawdę nie używasz stylu child.css do niczego, to nie musisz go kolejkować . Może to być tylko symbol zastępczy do przechowywania informacji nagłówka motywu. Nie używasz tego? Nie ładuj tego.

Co dokładnie robisz, tak bardzo zależy od zamówienia tutaj? CSS nie dba o porządek ładowania w większości sytuacji. CSS jest bardziej zależny od specyficzności selektorów. Jeśli chcesz coś przesłonić, sprecyzuj selektor. Może to być pierwsze, ostatnie lub cokolwiek pomiędzy, bardziej szczegółowy selektor zawsze wygrywa.

Edytować

Czytając twoje komentarze i przyglądając się bliżej kodowi, widzę, gdzie jest błąd. Dwudziesty trzynasty kod kolejkuje „get_stylesheet_uri ()”, który w przypadku motywu podrzędnego byłby plikiem style.css motywu podrzędnego, a nie plikiem nadrzędnym. Właśnie dlatego @import działa i zachowuje tę samą kolejność (co znowu nie ma większego znaczenia, niż myślisz).

W takim przypadku, jeśli nie chcesz używać importu, zaleciłbym bezpośrednie umieszczenie w kolejce style.css rodzica. Tak jak:

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

Kod w funkcjach motywu podrzędnego jest uruchamiany jako pierwszy, więc najpierw uruchomią się twoje własne skrypty wp_enqueue_script, co spowoduje kolejkowanie style.css motywu nadrzędnego, którego sam motyw nadrzędny nie wykonuje (ponieważ w rzeczywistości kolejkuje style.css Twojego dziecka). Nie uzależniając go od niczego, tak jak rodzic, wtedy po prostu zostaje poprawnie wstawiony do wyniku. Zauważ, że kolejność tego pliku i pliku genericons.css nie ma znaczenia, ponieważ w oryginalnym stylu „twentythirteen” nie ma wymienionej zależności genericons.css.

Załaduje się style.css własnego dziecka, i szczerze mówiąc, tutaj należy umieścić zmiany dla motywu potomnego, a nie w osobnym pliku main.css. Nic nie stoi na przeszkodzie, aby wprowadzić tam zmiany, ale nie ma żadnego powodu, aby mieć dodatkowy plik css.

Otto
źródło
Całkowicie się zgadzam, że @importnie jest to najlepsza droga. Proszę zobaczyć moją sekcję „edycja”, aby uzyskać bardziej szczegółowe informacje. Nie mam żadnych szczególnych potrzeb dotyczących zamawiania css. Po prostu nie chcę modyfikować wewnętrznej kolejności plików css motywu nadrzędnego, co może powodować problemy z priorytetem reguł css.
bernie
Aby wyjaśnić, B.css (teraz zmieniony na omawiany np. CSS) nie jest częścią motywu podrzędnego, ale w rzeczywistości jest częścią motywu nadrzędnego.
bernie
2
Jeśli chcesz, aby twój styl następował po stylu ie.css, to zależ od niego swój własny styl. Jego nazwa to „dwadzieścia trzynaście”. Kolejność jest w całości zarządzana przez zależności, które zadeklarujesz, ale ponownie, w CSS, rzeczywista kolejność ich w dokumencie zwykle nie ma znaczenia, więc nie jestem pewien, dlaczego przejmujesz się tym zbytnio.
Otto
2
Zmodyfikowałem moją odpowiedź, aby uwzględnić inne podejście.
Otto
Tak, chyba pociągnęła mnie „potrzeba”, aby utrzymać porządek w css. Jeśli kolejność była naprawdę ważna dla motywu nadrzędnego, należy to określić w zależnościach.
bernie
9

Moja poprzednia odpowiedź jest zbyt skomplikowana i potencjalnie nie szanuje łańcucha zależności motywu nadrzędnego (patrz uwaga w innej odpowiedzi).

Oto kolejne, znacznie prostsze podejście, które powinno działać znacznie lepiej:

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

Chodzi o to, aby po prostu odfiltrować wywołanie get_stylesheet_uri()w motywie nadrzędnym, aby zwrócić własny arkusz stylów zamiast motywu potomnego. Arkusz stylów motywu podrzędnego jest następnie umieszczany w kolejce w haku akcji my_theme_styles.

bernie
źródło
Dla przypomnienia: 1) Twój kod wygeneruje dokładnie taki sam html jak przy użyciu starej @importwersji, bez żadnego wpływu na wydajność, będą dwa osobne żądania style.css do serwera 2) Ta odpowiedź porzuca całą zależność razem ... 3) Możesz sprawdzić, co get_template_directory_urii get_template_stylesheet_urirobisz tutaj: core.trac.wordpress.org/browser/tags/4.8/src/wp-include/... Ponownie, nie potrzebujesz większości tego kodu.
bg17aw
1
@ bg17aw przy użyciu wp_enqueue_styleautomatycznie dodaje ciąg zapytania o pomijanie pamięci podręcznej do generowanego adresu URL (np. ?ver=2013-07-18) na podstawie wersji motywu. Tego nie uczyniło @importoświadczenie.
bernie
2

ostrzeżenie

To rozwiązanie nie uwzględnia zależności motywu nadrzędnego ! Zmiana nazwy uchwytu kompozycji nadrzędnej wpływa na łańcuch zależności ustawiony w kompozycji nadrzędnej. Zobacz moją znacznie prostszą inną odpowiedź .

oryginalna odpowiedź

Chociaż odpowiedź Otto jest całkiem dobra, skończyłem z tym w funkcjach motywu mojego dziecka. Php

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

Utrzymuje style.cssnumery porządkowe i numery wersji nadrzędnych , kontrolując jednocześnie wersję motywu podrzędnego style.css.

bernie
źródło
5
Przeraża mnie myśl, że najpopularniejsze oprogramowanie blogowe wymaga ponad 20 linii kodu, aby ulepszyć CSS istniejącego motywu. To chyba bezpieczeństwo pracy.
Carl G
Musiałem zmienić [$parentNewHandle]naarray($parentNewHandle)
Carl G
@CarlG: używana przeze mnie składnia tablicy (nawiasy kwadratowe) została wprowadzona w PHP 5.4.
bernie
Do głosujących: proszę zobaczyć moją drugą odpowiedź, która rozwiązuje problemy z tym.
bernie
To ogromne nieporozumienie, nie ma takiej potrzeby. W rzeczywistości stara @importmetoda działa równie dobrze, porównaj obie metody. Jeśli chodzi o zależność motywu potomnego od motywu macierzystego, nie ma takiej potrzeby. Dziecko style.cssjest zawsze ładowane po rodzicu, przynajmniej z moich testów. Uwielbiam udowodnić, że się mylą.
bg17aw