Versioning @import del estilo del tema principal.css

28

Contexto

Construí un tema infantil basado en Twenty Thirteen que funciona bastante bien. Después de actualizar el tema principal a la versión 1.3, noté un comportamiento extraño con el estilo que fue causado por un tema primario en caché style.css.

Aquí está el contenido del tema de mi hijo style.css(omitiendo encabezados)

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

Entonces, el tema secundario style.cssno hace más que importar el tema principal style.css.

También tengo otro archivo css con las personalizaciones de mi tema hijo que pongo en cola como en 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);

Esto me da una URL de CSS muy bonita como esta: domain.com/wp-content/themes/toutprettoutbon/css/main.css?ver=1.0.1eso asegura que la hoja de estilo se vuelva a cargar cuando se actualice el tema secundario.

Ahora el problema

La declaración @import url('../twentythirteen/style.css');es completamente independiente de la versión del tema principal subyacente. De hecho, el tema principal se puede actualizar sin actualizar el tema secundario, pero los navegadores seguirán utilizando versiones en caché del anterior ../twentythirteen/style.css.

Código relevante en Twenty Thirteen que pone en cola el 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' );

Se me ocurren algunas formas de resolver este problema, pero ninguna es realmente satisfactoria:

  1. Actualizar mi tema secundario cada vez que se actualiza el tema principal para cambiar una cadena de versión en style.css(p @import url('../twentythirteen/style.css?ver=NEW_VERSION');. Ej .). Esto crea un vínculo innecesario y molesto entre la versión del tema principal y el secundario.

  2. En mi hijo functions.php, 1) wp_dequeue_styleel tema hijo incluido style.cssy 2) wp_enqueue_styleel tema padrestyle.css directamente con la cadena de versión. Esto desordena el orden de css en cola en el tema principal.

  3. Utilice el style_loader_tagfiltro para modificar la <link>etiqueta css generada style.cssy modifique la ruta para que apunte directamente al tema principalstyle.css CON una cadena de versión. Parece bastante oscuro para una necesidad tan común (almacenamiento en caché).

  4. Volcar el tema principal en el tema de style.cssmi hijo style.css. Lo mismo que (1) realmente, pero un poco más rápido.

  5. Hacer que el tema de mi hijo style.csssea ​​un enlace simbólico con el tema principal style.css. Esto parece bastante hack ...

¿Me he perdido algo? ¿Alguna sugerencia?

editar

Añadido genericicons.cssy ie.csslas hojas de estilo en el tema de los padres para aclarar por qué no puedo cambiar la @importdeclaración CSS para wp_enqueue_styleen mi tema de niño. Actualmente, con una @importdeclaración en el tema de mi hijo style.css, tengo este orden en las páginas generadas:

  1. twentythirteen / genericons / genericons.css -> en cola por tema principal
  2. child-theme / style.css -> en cola por tema padre, @importes twentythirteen / style.css
  3. twentythirteen / css / ie.css -> en cola por tema principal
  4. child-theme / css / main.css -> en cola por tema hijo

Si pongo en cola a los padres style.csscomo una dependencia de main.css, esto se convertirá en:

  1. twentythirteen / genericons / genericons.css -> en cola por tema principal
  2. child-theme / style.css -> vacío, en cola por tema principal
  3. twentythirteen / css / ie.css -> en cola por tema principal
  4. twentythirteen / style.css -> en cola por tema hijo como dependencia de main.css
  5. child-theme / css / main.css -> en cola por tema hijo

Tenga en cuenta que ie.css ahora se incluye antes del tema principal style.css. No quiero cambiar el orden en cola de los archivos css del tema principal porque no puedo presumir que esto no causará problemas con la prioridad de las reglas css.

bernie
fuente
55
Nunca use @import, configure la hoja de estilo del tema principal como una dependencia de su propia hoja de estilo .
fuxia
Sé que no es el mejor enfoque, pero se recomienda aquí: codex.wordpress.org/Child_Themes
bernie
Además, hacer lo que sugirió no soluciona mi problema. El tema principal style.cssno se incluiría en el mismo lugar que ahora. El padre incluye otros archivos CSS que deben interponerse entre su style.cssCSS y el tema de mi hijo.
bernie
3
Por favor ignore el códice por completo. Está lleno de información errónea. El uso del parámetro de dependencia incluirá las hojas de estilo en el orden correcto.
fuxia
Por favor vea mi edición.
bernie

Respuestas:

19

No tiene que usar @import. Es mejor no hacerlo, en realidad. Usar un enfoque en cola probablemente sea mejor en todos los sentidos.

Aquí está la parte relevante del código de los veintitrés:

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

Esto es lo que haces en tu 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' );

Si su main.css tiene que venir después del estilo de los padres.css, entonces solo debe hacerlo dependiente de eso.

Ahora, si también tiene un B.css en el elemento secundario, configure las dependencias en consecuencia:

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

Haga que las dependencias que defina para cada elemento realmente reflejen cuáles son realmente esas dependencias. Si main.css debe venir después de B.css, entonces depende de ello. Si B.css debe ir después del estilo del padre.css, entonces B depende de eso. El sistema en cola lo resolverá por usted.

Y si no estás usando el style.css del niño para nada, entonces no tienes que ponerlo en cola . Puede ser solo un marcador de posición para mantener la información del encabezado de su tema. ¿No lo usas? No lo cargues.

Además, ¿qué estás haciendo exactamente que depende tanto de ordenar aquí? CSS no se preocupa por el orden de carga en la mayoría de las situaciones. CSS depende más de la especificidad de los selectores. Si desea anular algo, puede hacer que su selector sea más específico. Puede venir primero, o al final, o cualquier cosa intermedia, siempre gana el selector más específico.

Editar

Al leer sus comentarios y mirar más de cerca el código, veo dónde está el error aquí. El código veintitrés está poniendo en cola el "get_stylesheet_uri ()", que en un caso de tema hijo, sería el archivo style.css de su tema hijo, no el archivo padre. Es por eso que @import funciona y mantiene el mismo orden (que, una vez más, no importa tanto como crees).

En ese caso, si no desea utilizar la importación, recomendaría poner en cola directamente el style.css del padre. Al igual que:

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

El código en las funciones del tema secundario.php se ejecuta primero, por lo que sus propios wp_enqueue_scripts se ejecutarán primero, y esto pondrá en cola el style.css del tema principal, que el tema principal no está haciendo en sí mismo (porque en realidad está poniendo en cola style.css de su hijo). Al no hacerlo depender de nada, igual que el padre, simplemente se coloca correctamente en la salida. Tenga en cuenta que el orden de este archivo y el genericons.css no importa, porque el "estilo vigésimo trece" original no tiene el genericons.css como una dependencia listada.

Style.css de su propio hijo se cargará, y honestamente, aquí es donde debe colocar sus cambios para el tema hijo, no en un main.css separado. No hay nada que le impida poner sus cambios allí, pero no hay una razón real para tener un archivo css adicional.

Otón
fuente
Estoy totalmente de acuerdo en que los @imports no son la mejor manera de hacerlo. Consulte mi sección "editar" para obtener información más precisa. No tengo ninguna necesidad particular con respecto al pedido de CSS. Simplemente no quiero modificar el orden interno de los archivos CSS del tema principal, lo que puede causar problemas con la prioridad de las reglas CSS.
bernie
Para aclarar, B.css (ahora cambiado a ie.css en cuestión) no es parte del tema de mi hijo, pero en realidad es parte del tema principal.
bernie
2
Si desea que su estilo siga el estilo ie.css, haga que su propio estilo dependa de él. Su nombre es "vigésimo trece, es decir". El orden está completamente administrado por las dependencias que declaras, pero de nuevo, con CSS, el orden real de ellas en el documento generalmente no importa, por lo que no estoy seguro de por qué te importaría demasiado.
Otto
2
Edité mi respuesta para incluir un enfoque diferente.
Otto
Sí, supongo que me dejé llevar por la "necesidad" de mantener el pedido de CSS. Si el orden era realmente importante para el tema principal, debería indicarse en las dependencias.
bernie
9

Mi respuesta anterior es demasiado complicada y potencialmente no respeta la cadena de dependencia del tema principal (vea la nota en otra respuesta).

Aquí hay otra toma mucho más simple que debería funcionar mucho mejor:

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

La idea es simplemente filtrar la llamada get_stylesheet_uri()en el tema principal para devolver su propia hoja de estilo en lugar del tema secundario. La hoja de estilo del tema secundario se coloca en cola más adelante en el gancho de acción my_theme_styles.

bernie
fuente
Solo para el registro: 1) Su código generará exactamente el mismo html que el uso de la @importversión anterior, sin ningún impacto en el rendimiento, habrá dos solicitudes de style.css separadas para el servidor 2) Esta respuesta elimina toda la cuestión de dependencia juntos ... 3) puede comprobar qué get_template_directory_uriy get_template_stylesheet_uriestán haciendo aquí: core.trac.wordpress.org/browser/tags/4.8/src/wp-includes/... Una vez más, sin necesidad de que la mayor parte de ese código.
bg17aw
1
@ bg17aw mediante wp_enqueue_styleel uso agrega automáticamente una cadena de consulta de eliminación de caché a la url que genera (por ejemplo ?ver=2013-07-18) en función de la versión del tema. Esto no se hace mediante una @importdeclaración.
bernie
2

advertencia

¡Esta solución no respeta las dependencias del tema principal ! Cambiar el nombre del identificador del tema principal afecta la cadena de dependencias establecida en el tema principal. Vea mi otra respuesta mucho más simple .

respuesta original

Aunque la respuesta de Otto es bastante buena, terminé con esto en las funciones del tema de mi hijo.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);

Mantiene el style.cssorden del tema principal y los números de versión mientras controla la versión del tema secundario style.css.

bernie
fuente
55
Me sorprende que el software de blog más popular requiera más de 20 líneas de código solo para modificar el CSS de un tema existente. Supongo que es seguridad laboral.
Carl G
Tuve que cambiar [$parentNewHandle]aarray($parentNewHandle)
Carl G
@CarlG: la sintaxis de matriz que utilicé (paréntesis) se introdujo en PHP 5.4.
bernie
Para los votantes: vea mi otra respuesta que resuelve los problemas con esta.
bernie
Todo es un gran malentendido, no hay necesidad de nada de eso. De hecho, el @importmétodo anterior funciona igual de bien, por favor compare ambos métodos. En cuanto a la dependencia del tema secundario en el tema principal, tampoco es necesario. El niño style.csssiempre se carga después del padre, al menos desde mis pruebas. Me encanta que se demuestre lo contrario.
bg17aw