Versionado de @import del style.css del tema padre

3 oct 2014, 03:50:31
Vistas: 97.1K
Votos: 29

Contexto

Construí un tema hijo basado en Twenty Thirteen que funciona bastante bien. Después de actualizar el tema padre a la versión 1.3, noté un comportamiento extraño con los estilos que fue causado por una versión en caché del style.css del tema padre.

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

/* =Importa estilos del tema padre
-------------------------------------------------------------- */
@import url('../twentythirteen/style.css');

Entonces el style.css del tema hijo no hace nada más que importar el style.css del tema padre.

También tengo otro archivo css con las personalizaciones de mi tema hijo que encolo así en functions.php:

// Encola style.css del tema padre (más rápido que usar @import en nuestro style.css)
$themeVersion = wp_get_theme()->get('Version');

// Encola personalizaciones del tema hijo
wp_enqueue_style('child_main', get_stylesheet_directory_uri() . '/css/main.css',
    null, $themeVersion);

Esto me da una URL css muy agradable como esta: domain.com/wp-content/themes/toutprettoutbon/css/main.css?ver=1.0.1 que asegura que la hoja de estilos se recargue cuando se actualiza el tema hijo.

Ahora el problema

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

Código relevante en Twenty Thirteen que encola el style.css:

function twentythirteen_scripts_styles() {
    // ...

    // Agrega la fuente Genericons, usada en la hoja de estilos principal.
    wp_enqueue_style( 'genericons', get_template_directory_uri() . '/genericons/genericons.css', array(), '3.03' );

    // Carga nuestra hoja de estilos principal.
    wp_enqueue_style( 'twentythirteen-style', get_stylesheet_uri(), array(), '2013-07-18' );
    // Nota el uso de get_stylesheet_uri() que en realidad encola child-theme/style.css

    // Carga la hoja de estilos específica para 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' );

Puedo pensar en algunas formas de resolver este problema pero ninguna es realmente satisfactoria:

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

  2. En mi functions.php del hijo, 1) wp_dequeue_style el style.css incluido del tema hijo y 2) wp_enqueue_style el style.css del tema padre directamente CON cadena de versión. Esto desordena el orden de los css encolados en el tema padre.

  3. Usar el filtro style_loader_tag para modificar la etiqueta <link> css generada para style.css y modificar la ruta para apuntar directamente al style.css del tema padre CON una cadena de versión. Parece bastante oscuro para una necesidad tan común (invalidación de caché).

  4. Volcar el style.css del tema padre en el style.css de mi tema hijo. Igual que (1) realmente, pero un poco más rápido.

  5. Hacer que el style.css de mi tema hijo sea un enlace simbólico al style.css del tema padre. Esto parece bastante improvisado...

¿Me he perdido algo? ¿Alguna sugerencia?

edición

Agregué las hojas de estilo genericicons.css y ie.css en el tema padre para aclarar por qué no puedo cambiar la declaración css @import a wp_enqueue_style en mi tema hijo. Actualmente, con una declaración @import en el style.css de mi tema hijo, tengo este orden en las páginas generadas:

  1. twentythirteen/genericons/genericons.css -> encolado por el tema padre
  2. child-theme/style.css -> encolado por el tema padre, @imports twentythirteen/style.css
  3. twentythirteen/css/ie.css -> encolado por el tema padre
  4. child-theme/css/main.css -> encolado por el tema hijo

Si encolo el style.css del padre como una dependencia de main.css, esto se convertirá en:

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

Nótese que ie.css ahora está incluido antes del style.css del tema padre. No quiero cambiar el orden de encolado de los archivos css del tema padre porque no puedo presumir que esto no causará problemas con la prioridad de las reglas css.

5
Comentarios

Nunca uses @import, en su lugar establece la hoja de estilos del tema padre como una dependencia de tu propia hoja de estilos.

fuxia fuxia
3 oct 2014 04:03:52

Sé que no es el mejor enfoque pero está recomendado aquí: http://codex.wordpress.org/Child_Themes

bernie bernie
3 oct 2014 04:09:44

Además, hacer lo que sugieres no soluciona mi problema. La style.css del tema padre no se incluiría en el mismo lugar que ahora. El tema padre incluye otros archivos css que deben ir entre su style.css y el css de mi tema hijo.

bernie bernie
3 oct 2014 04:10:54

Por favor ignora completamente el codex. Está lleno de información errónea. Usar el parámetro de dependencia incluirá las hojas de estilo en el orden correcto.

fuxia fuxia
3 oct 2014 04:11:47

Por favor revisa mi edición.

bernie bernie
3 oct 2014 19:53:33
Todas las respuestas a la pregunta 3
11
19

No es necesario usar @import. De hecho, es mejor no hacerlo. Utilizar el enfoque de encolado probablemente sea mejor en todos los aspectos.

Aquí está la parte relevante del código de twentythirteen:

function twentythirteen_scripts_styles() {
...
    // Carga nuestra hoja de estilos principal.
    wp_enqueue_style( 'twentythirteen-style', get_stylesheet_uri(), array(), '2013-07-18' );
...
}
add_action( 'wp_enqueue_scripts', 'twentythirteen_scripts_styles' );

Esto es lo que debes hacer en tu código:

function child_scripts_styles() {
    wp_enqueue_style( 'child-style', get_stylesheet_directory_uri().'/css/main.css', array('twentythirteen-style'), 'TU_VERSION_DEL_TEMA' );
}
add_action( 'wp_enqueue_scripts', 'child_scripts_styles' );

Si tu main.css debe cargarse después del style.css del tema padre, simplemente lo haces dependiente de él.

Ahora, si también tienes un B.css en el tema hijo, configuras las dependencias acordemente:

function child_scripts_styles() {
    wp_enqueue_style( 'child-B-style', get_stylesheet_directory_uri().'/B.css', array('twentythirteen-style'), 'TU_VERSION_DEL_TEMA' );
    wp_enqueue_style( 'child-style', get_stylesheet_directory_uri().'/css/main.css', array('child-B-style'), 'TU_VERSION_DEL_TEMA' );
}
add_action( 'wp_enqueue_scripts', 'child_scripts_styles' );

Define las dependencias para cada elemento que realmente reflejen cuáles son esas dependencias. Si main.css debe ir después de B.css, entonces depende de él. Si B.css debe ir después del style.css del tema padre, entonces B depende de él. El sistema de encolado lo resolverá por ti.

Y si en realidad no estás usando el style.css del tema hijo para nada, entonces no necesitas encolarlo en absoluto. Puede ser solo un marcador de posición para guardar la información del encabezado de tu tema. ¿No lo usas? No lo cargues.

Además, ¿qué es exactamente lo que estás haciendo que depende tanto del orden aquí? A CSS no le importa el orden de carga en la mayoría de las situaciones. CSS depende más de la especificidad de los selectores. Si quieres sobrescribir algo, haces que tu selector sea más específico. Puede ir primero, o último, o en cualquier lugar intermedio, el selector más específico siempre gana.

Edición

Leyendo tus comentarios y mirando más de cerca el código, veo dónde está el error aquí. El código de twenty-thirteen está encolando "get_stylesheet_uri()", que en el caso de un tema hijo sería el archivo style.css de tu tema hijo, no el del tema padre. Por eso el @import funciona, y mantiene el mismo orden (que nuevamente, no importa tanto como crees).

En ese caso, si no quieres usar import, recomendaría encolar directamente el style.css del tema padre. Así:

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 el functions.php del tema hijo se ejecuta primero, así que tu propio wp_enqueue_scripts correrá primero, y esto encolará el style.css del tema padre, lo cual el tema padre no está haciendo por sí mismo (porque en realidad está encolando el style.css de tu tema hijo). Al no hacerlo dependiente de nada, igual que el tema padre, simplemente se coloca en la salida correctamente. Nota que el orden de este archivo y el genericons.css no importa, porque el "twentythirteen-style" original no tiene a genericons.css como una dependencia listada.

Tu propio style.css del tema hijo se cargará, y honestamente, aquí es donde deberías poner los cambios para tu tema hijo, no en un main.css separado. No hay nada que te impida poner tus cambios ahí, pero no hay una razón real para tener un archivo css extra.

3 oct 2014 20:25:45
Comentarios

Estoy totalmente de acuerdo en que los @import no son la mejor opción. Por favor, revisa mi sección de "edición" para información más precisa. No tengo necesidades particulares respecto al orden del css. Simplemente no quiero modificar el orden interno de los archivos css del tema padre, lo que puede causar problemas con la prioridad de las reglas css.

bernie bernie
3 oct 2014 22:13:45

Para aclarar, B.css (ahora cambiado a ie.css en la pregunta) no es parte de mi tema hijo, sino que en realidad es parte del tema padre.

bernie bernie
3 oct 2014 22:26:46

Si quieres que tu estilo venga después del estilo ie.css, entonces haz que tu propio estilo dependa de él. Su nombre es "twentythirteen-ie". El orden se gestiona completamente por las dependencias que declares, pero nuevamente, con CSS, el orden real de estos en el documento generalmente no importa, así que no estoy seguro de por qué te preocuparía demasiado por ello.

Otto Otto
3 oct 2014 23:12:02

Edité mi respuesta para incluir un enfoque diferente.

Otto Otto
3 oct 2014 23:29:48

Sí, supongo que me dejé llevar por la "necesidad" de mantener el orden del css. Si el orden fuera realmente importante para el tema padre, debería indicarse en las dependencias.

bernie bernie
4 oct 2014 17:20:16

"Tu propio style.css del hijo se cargará, y honestamente, aquí es donde deberías poner los cambios para el tema hijo, no en un main.css separado." Esto es cierto, pero quiero agregar una cadena de versión al css de mi tema hijo.

Si simplemente uso el enqueue del tema padre para el style.css del tema hijo, el padre controla la versión ya que es él quien llama a enqueue_style. Quiero poder actualizar el tema hijo y cambiar la cadena de versión de sus hojas de estilo para el cache busting independientemente de la versión del tema padre.

bernie bernie
4 oct 2014 17:23:16

Me encantaría conocer tu opinión sobre la nueva respuesta mucho más simple que acabo de añadir.

bernie bernie
23 mar 2015 19:19:45

Tu actualización realmente ayuda a resolver muchos problemas. Mi tema padre tenía bootstrap.css incluido antes de style.css. Con tu enfoque solo tuve que especificar bootstrap como dependencia para parent-style en el style.css del tema hijo. Y todo lo demás encaja perfectamente. ¡Gracias!

roshan roshan
3 abr 2016 18:53:50

No hay nada malo en usar @import, no afecta el rendimiento de ninguna manera, por favor revisa el código fuente de temas hijos creados con cualquier método, encontrarás que se generan dos solicitudes al servidor en cualquier caso. Una buena lectura aquí: https://wordpress.org/support/topic/needs-update-12/

bg17aw bg17aw
1 sept 2017 01:11:49

No creo que puedas evitar cargar el archivo style.css del tema hijo. Por favor verifica, se cargará incluso si no lo encolas específicamente.

bg17aw bg17aw
1 sept 2017 01:14:42

No tengo suficiente reputación para publicar mi propia respuesta, pero aquí está mi aporte: https://pastebin.com/iDr6Hy79

360path 360path
2 abr 2020 20:51:48
Mostrar los 6 comentarios restantes
2

Mi respuesta anterior es demasiado complicada y potencialmente no respeta la cadena de dependencias del tema padre (ver nota en la otra respuesta).

Aquí hay un enfoque mucho más simple que debería funcionar mejor:

function use_parent_theme_stylesheet() {
    // Usar la hoja de estilos del tema padre
    return get_template_directory_uri() . '/style.css';
}

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

    // Cargar nuestro style.css con nuestra propia versión
    wp_enqueue_style('child-theme-style', get_stylesheet_directory_uri() . '/style.css',
        array(), $themeVersion);
}

// Filtrar get_stylesheet_uri() para devolver la hoja de estilos del tema padre
add_filter('stylesheet_uri', 'use_parent_theme_stylesheet');

// Cargar los scripts y estilos de este tema (después del tema padre)
add_action('wp_enqueue_scripts', 'my_theme_styles', 20);

La idea es simplemente filtrar la llamada a get_stylesheet_uri() en el tema padre para que devuelva su propia hoja de estilos en lugar de la del tema hijo. La hoja de estilos del tema hijo se carga después en el gancho de acción my_theme_styles.

23 mar 2015 19:13:13
Comentarios

Solo para dejar constancia: 1) Tu código generará exactamente el mismo html que usar la versión antigua con @import, sin impacto en el rendimiento, habrá dos solicitudes separadas de style.css al servidor 2) Esta respuesta elimina por completo todo el tema de dependencias... 3) Puedes ver qué hacen get_template_directory_uri y get_template_stylesheet_uri aquí: https://core.trac.wordpress.org/browser/tags/4.8/src/wp-includes/class-wp-theme.php#L9 Nuevamente, no es necesario la mayor parte de ese código.

bg17aw bg17aw
1 sept 2017 01:19:58

@bg17aw usar wp_enqueue_style agrega automáticamente una cadena de consulta para evitar caché a la url que genera (ej. ?ver=2013-07-18) basado en la versión del tema. Esto no se hace con una declaración @import.

bernie bernie
14 sept 2017 21:01:58
6

advertencia

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

respuesta original

Aunque la respuesta de Otto es bastante buena, terminé usando esto en el functions.php de mi tema hijo:

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

    // Desregistramos nuestro style.css que fue encolado por el tema padre; queremos
    // controlar la versión nosotros mismos.
    $parentStyleVersion = $wp_styles->registered[$parentOriginalHandle]->ver;
    $parentDeps = $wp_styles->registered[$parentOriginalHandle]->deps;
    wp_deregister_style($parentOriginalHandle);

    // Encolamos el style.css del tema padre con la versión que usaba en lugar
    // de importarlo con @import en el style.css del tema hijo
    wp_register_style($parentNewHandle, get_template_directory_uri() . '/style.css',
        $parentDeps, $parentStyleVersion);

    // Encolamos nuestro style.css con nuestra propia versión
    $themeVersion = wp_get_theme()->get('Version');
    wp_enqueue_style($parentOriginalHandle, get_stylesheet_directory_uri() . '/style.css',
        [$parentNewHandle], $themeVersion);
}

// Ejecutamos esta acción después de que el tema padre haya encolado sus estilos.
add_action('wp_enqueue_scripts', 'my_theme_styles', 20);

Mantiene el orden y los números de versión del style.css del tema padre mientras controla la versión del style.css del tema hijo.

6 oct 2014 21:25:47
Comentarios

Me sorprende que el software de blogs más popular requiera más de 20 líneas de código solo para ajustar el CSS de un tema existente. Supongo que eso es seguridad laboral.

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

Tuve que cambiar [$parentNewHandle] por array($parentNewHandle)

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

@CarlG : la sintaxis de array que usé (corchetes) se introdujo en PHP 5.4.

bernie bernie
26 ene 2015 06:47:14

A los votantes positivos: por favor lean mi otra respuesta que soluciona los problemas con esta.

bernie bernie
23 mar 2015 19:21:06

Todo es un gran malentendido, no hay necesidad de nada de eso. De hecho, el antiguo método @import funciona igual de bien, por favor comparen ambos métodos. En cuanto a la dependencia del tema hijo del tema padre, tampoco hay necesidad de eso. El style.css del tema hijo siempre se carga después del padre, al menos según mis pruebas. Me encantaría que me demostraran lo contrario.

bg17aw bg17aw
1 sept 2017 01:23:01

@bg17aw usar wp_enqueue_style automáticamente añade una cadena de consulta para evitar caché a la URL que genera (ej. ?ver=2013-07-18) basada en la versión del tema. Esto no se hace con una declaración @import.

bernie bernie
14 sept 2017 21:02:12
Mostrar los 1 comentarios restantes