Versionando @import do style.css do tema pai

28

Contexto

Eu construí um tema infantil baseado no Twenty Treze, que funciona muito bem. Após atualizar o tema pai para a versão 1.3, notei um comportamento estranho com o estilo causado por um tema pai em cache style.css.

Aqui está o conteúdo dos temas do meu filho style.css(omitindo cabeçalhos)

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

Portanto, o tema filho style.cssnada mais faz do que importar o tema pai style.css.

Eu também tenho outro arquivo css com as personalizações do meu tema filho, as quais coloco assim 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);

Isso me fornece um URL de CSS muito bom como este: domain.com/wp-content/themes/toutprettoutbon/css/main.css?ver=1.0.1que garante que a folha de estilos seja recarregada quando o tema filho for atualizado.

Agora o problema

A declaração @import url('../twentythirteen/style.css');é completamente independente da versão do tema pai subjacente. De fato, o tema pai pode ser atualizado sem atualizar o tema filho, mas os navegadores ainda usarão as versões em cache do antigo ../twentythirteen/style.css.

Código relevante no Twenty Treze que enfileira o 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 pensar em algumas maneiras de resolver esse problema, mas nenhuma é realmente satisfatória:

  1. Atualizar o tema filho sempre que o tema pai for atualizado para alterar uma sequência de versão em style.css(por exemplo @import url('../twentythirteen/style.css?ver=NEW_VERSION');). Isso cria um link desnecessário e irritante entre a versão do tema pai e o filho.

  2. No meu filho functions.php, 1) wp_dequeue_styleo tema filho incluído style.csse 2) wp_enqueue_styleo tema paistyle.css diretamente com a string de versão. Isso atrapalha a ordem do CSS na fila no tema pai.

  3. Use o style_loader_tagfiltro para modificar a <link>tag css gerada style.csse modificar o caminho para apontar diretamente para a sequência WITH version de um tema paistyle.css . Parece bastante obscuro para uma necessidade tão comum (bloqueio de cache).

  4. Despejar o tema pai no tema do style.cssmeu filho style.css. O mesmo que (1) realmente, mas um pouco mais rápido.

  5. Faça com que meu tema filho style.cssseja um link simbólico para o tema pai style.css. Isso parece muito hackish ...

Perdi alguma coisa? Alguma sugestão?

editar

Adicionadas genericicons.csse ie.cssfolhas de estilo no tema pai para esclarecer por que não posso alterar a @importinstrução css para wp_enqueue_styleno meu tema filho. Atualmente, com uma @importdeclaração no tema do meu filho style.css, tenho essa ordem nas páginas geradas:

  1. twentythteenteen / genericons / genericons.css -> enfileirado pelo tema pai
  2. child-theme / style.css -> enfileirado pelo tema pai, @imports twentythirteen / style.css
  3. décimo terceiro / css / ie.css -> enfileirado pelo tema pai
  4. child-theme / css / main.css -> enfileirado pelo tema filho

Se eu enfileirar os pais style.csscomo uma dependência de main.css, isso se tornará:

  1. twentythteenteen / genericons / genericons.css -> enfileirado pelo tema pai
  2. child-theme / style.css -> vazio, enfileirado pelo tema pai
  3. décimo terceiro / css / ie.css -> enfileirado pelo tema pai
  4. décimo terceiro / style.css -> enfileirado pelo tema filho como dependência do main.css
  5. child-theme / css / main.css -> enfileirado pelo tema filho

Observe que o arquivo ie.css agora está incluído antes do tema principal style.css. Não quero alterar a ordem de enfileiramento dos arquivos css do tema pai, porque não posso presumir que isso não causará problemas com a prioridade das regras de css.

Bernie
fonte
5
Nunca use @import, defina a folha de estilo do tema pai como uma dependência da sua própria folha de estilo .
fuxia
Eu sei que não é a melhor abordagem, mas é recomendado aqui: codex.wordpress.org/Child_Themes
Bernie
Além disso, fazer o que você sugeriu não resolve o meu problema. O tema principal style.cssnão seria incluído no mesmo local em que está agora. O pai inclui outros arquivos css que devem estar entre style.csso css e o tema do meu filho.
Bernie
3
Por favor, ignore o codex completamente. Está cheio de desinformação. O uso do parâmetro dependency incluirá as folhas de estilo na ordem correta.
fuxia
Por favor, veja minha edição.
Bernie

Respostas:

19

Você não precisa usar @import. É melhor não, na verdade. Usar uma abordagem enfileirada é provavelmente melhor ao redor.

Aqui está a parte relevante do código de vinte e treze:

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

Aqui está o que você faz no seu código:

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 o seu main.css precisar seguir o style.css dos pais, basta torná-lo dependente.

Agora, se você também tiver um B.css no filho, configure as dependências adequadamente:

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

Torne as dependências que você define para cada item realmente refletem o que realmente são essas dependências. Se o main.css deve vir depois do B.css, isso depende disso. Se o B.css deve vir após o style.css do pai, então B depende disso. O sistema de enfileiramento resolverá isso para você.

E se você não está usando o style.css da criança para nada, não precisa enfileirá-lo . Pode ser apenas um espaço reservado para armazenar as informações do cabeçalho do seu tema. Não está usando? Não carregue.

Além disso, o que exatamente você está fazendo é tão dependente de encomendar aqui? O CSS não se importa com a ordem de carregamento na maioria das situações. CSS é mais dependente da especificidade dos seletores. Se você deseja substituir algo, torne seu seletor mais específico. Pode vir em primeiro, último ou qualquer outro meio, o seletor mais específico sempre vence.

Editar

Lendo seus comentários e olhando mais de perto o código, vejo onde está o erro. O código de vinte e treze está enfileirando o "get_stylesheet_uri ()", que em um caso de tema filho, seria o arquivo style.css do tema filho, não o arquivo pai. É por isso que o @import funciona e mantém a mesma ordem (que, novamente, não importa tanto quanto você pensa).

Nesse caso, se você não quiser usar a importação, recomendo enfileirar o style.css do pai diretamente. Igual a:

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

O código no functions.php do tema filho é executado primeiro, para que o seu próprio wp_enqueue_scripts seja executado primeiro, e isso enfileirará o style.css do tema pai, que o tema pai não está fazendo sozinho (porque na verdade está enfileirando o style.css do seu filho). Ao não fazê-lo depender de nada, igual ao pai, ele simplesmente é colocado na saída corretamente. Observe que a ordem desse arquivo e do genericons.css não importa, porque o "estilo décimo treze" original não possui o genericons.css como uma dependência listada.

O style.css do seu próprio filho será carregado e, honestamente, é aqui que você deve colocar as alterações no tema filho, não em um main.css separado. Não há nada impedindo que você faça as alterações, mas não há motivo real para ter um arquivo css extra.

Otto
fonte
Eu concordo totalmente que @importnão é o melhor caminho a percorrer. Por favor, consulte minha seção "editar" para obter informações mais precisas. Eu não tenho nenhuma necessidade específica em relação à encomenda de css. Eu simplesmente não quero modificar a ordem interna dos arquivos css do tema pai, o que pode causar problemas com a prioridade das regras css.
22413 bernie
Para esclarecer, B.css (agora alterado para ie.css em questão) não faz parte do meu tema filho, mas na verdade faz parte do tema pai.
Bernie
2
Se você deseja que seu estilo seja posterior ao estilo ie.css, faça com que seu próprio estilo dependa. Seu nome é "vinte e treze-ie". O pedido é totalmente gerenciado por quais dependências você declara, mas, novamente, com CSS, a ordem real delas no documento geralmente não importa, por isso não sei por que você se importaria muito com isso.
Otto
2
Editou minha resposta para incluir uma abordagem diferente.
Otto
Sim, eu acho que me empolguei com a "necessidade" de manter o pedido de CSS. Se o pedido for realmente importante para o tema pai, ele deverá ser declarado nas dependências.
Bernie
9

Minha resposta anterior é excessivamente complicada e potencialmente não respeita a cadeia de dependência do tema pai (consulte a observação em outra resposta).

Aqui está outra tomada muito mais simples que deve funcionar muito melhor:

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

A idéia é simplesmente filtrar a chamada get_stylesheet_uri()no tema pai para retornar sua própria folha de estilo, em vez da tema filho. A folha de estilo do tema filho é enfileirada posteriormente no gancho de ação my_theme_styles.

Bernie
fonte
Apenas para registro: 1) Seu código gerará exatamente o mesmo html que o uso da @importversão antiga , sem nenhum impacto no desempenho. Haverá duas solicitações style.css separadas para o servidor 2) Essa resposta descarta toda a dependência juntos ... 3) Você pode verificar o que get_template_directory_urie get_template_stylesheet_uriestão fazendo aqui: core.trac.wordpress.org/browser/tags/4.8/src/wp-includes/... Novamente, não há necessidade para a maioria desse código.
precisa saber é
1
@ bg17aw usando wp_enqueue_styleadiciona automaticamente uma string de consulta de bloqueio de cache ao URL que ele gera (por exemplo ?ver=2013-07-18) com base na versão do tema. Isso não foi feito por uma @importdeclaração.
bernie
2

Atenção

Esta solução não respeita as dependências do tema pai ! Alterar o nome do identificador do tema pai afeta a cadeia de dependências configuradas no tema pai. Veja minha outra resposta muito mais simples .

resposta original

Embora a resposta de Otto seja muito boa, acabei com isso nas funções do meu tema filho.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);

Ele mantém os style.cssnúmeros de pedido e versão do tema pai enquanto controla a versão do tema filho style.css.

Bernie
fonte
5
Surpreende-me que o software de blog mais popular exija mais de 20 linhas de código apenas para ajustar o CSS de um tema existente. Eu acho que é segurança no emprego.
Carl G
Eu tive que mudar [$parentNewHandle]paraarray($parentNewHandle)
Carl G
@CarlG: a sintaxe do array que usei (colchetes) foi introduzida no PHP 5.4.
Bernie
Para promotores: veja minha outra resposta que resolve problemas com esta.
Bernie
É tudo um grande mal-entendido, não há necessidade disso. De fato, o @importmétodo antigo também funciona, compare os dois métodos. Quanto à dependência do tema filho no tema pai, também não é necessário. O filho style.cssé sempre carregado após o pai, pelo menos nos meus testes. Amor para ser provado errado.
precisa saber é