WordPress.org

Forums

[resolved] Best way to create a css file dynamically (22 posts)

  1. victor_jonsson
    Member
    Posted 2 years ago #

    Hi there!

    What would be the best way to dynamically generate a stylesheet in a theme? I can think of three different solutions:

    1) Having a separate file in theme and assume where the file wp-load.php is located and include it like '/../../wp-load.php'.

    2) In the file functions.php check if a certain variable is set and if so generate the stylesheet and terminate the script.

    3) Register an ajax function and link to the url of the ajax function (not sure if wordpress checks if AJAX-requests is sent with correct request headers).

    Is there any other way to accomplish this? I know that the first solution is most straight forward but I consider it to be something of a hack, especially if it exists a "correct" way of doing it.

    / vic

  2. esmi
    Forum Moderator
    Posted 2 years ago #

    1. Assuming this file is .css, you'd ideally enqueue it and let WordPress handle the loading.

    2. Why not just add the .css to the head of the page - again by enqueueing it?

  3. victor_jonsson
    Member
    Posted 2 years ago #

    Sorry. I wasn't to clear about that. The stylesheet is generated on the fly, so it will have the extension .php. I could of course generate it and save it to a static file but that would actually become more complex in my case.

  4. esmi
    Forum Moderator
    Posted 2 years ago #

    Have you had a look at http://css-tricks.com/css-variables-with-php/ There's a couple of ways to use a css file with a .php extension. So you could generate the file on the fly and enqueue it using wp_enqueue_style. At worst, you'd end up enqueuing an empty file but, if you also bundled this in with a variable/flag, you could enqueue it only if it contains something. Either way, it should be possible to do the whole thing via the theme's functions.php file.

  5. victor_jonsson
    Member
    Posted 2 years ago #

    Sorry again, I guess my question still is to fuzzy :)

    I'm not asking how to dynamically generate a css file. My question is how to load wordpress from within the file that generates the CSS. (I guess my examples makes more sense now that I have explained that).

    Edit: I now realize how bad the title of this post is :)

  6. esmi
    Forum Moderator
    Posted 2 years ago #

    Sorry? You want to load that CSS file into WordPress?

  7. victor_jonsson
    Member
    Posted 2 years ago #

    1) I have a CSS-file that generates a piece of CSS code
    2) I enqueue the CSS file (that has .php as extension) in functions.php

    For example:

    function.php

    wp_enqueue_stylesheet('my-dynamic-css', get_stylesheet_directory_uri().'my-css.php');

    my-css.php

    <?php
    header('Content-type: text/css');
    
    require '/../../../wp-load.php'; // load wordpress bootstrap, this is what I don't like
    
    // and from here on generate the css file and having access to the
    // functions provided by wordpress

    So my questions is if it exists any alternative way to bootstrap wordpress. A way where you don't assume that you have knowledge about where the file wp-load.php is located?

  8. esmi
    Forum Moderator
    Posted 2 years ago #

    I don't understand why you're calling wp-load.php in the first place. Can you elaborate on why?

  9. victor_jonsson
    Member
    Posted 2 years ago #

    Because the administrator of the website gets the possibility to configure a bunch of stuff in wp-admin that's in regard to theme. The code could look something like:

    <?php
    header('Content-type: text/css');
    require '/../../../wp-load.php'; // load wordpress bootstrap, this is what I don't like
    $css_options = get_option('website_css');
    ?>
    body {
      background: <?php echo $css_options['background'] ?>;
    }
  10. esmi
    Forum Moderator
    Posted 2 years ago #

    Because the administrator of the website gets the possibility to configure a bunch of stuff in wp-admin that's in regard to theme.

    That still wouldn't need to you call wp-load.php, though. I've done similar themes and simply enqueued the custom CSS and let WP handle the rest.

  11. victor_jonsson
    Member
    Posted 2 years ago #

    How could that be possible? We must be talking about different things here. How do I get WordPress to know which CSS rules to put in the generated CSS? How do I make wordpress to dynamically generate a CSS from options added by the administrator in wp-admin? Could you please give me a code example?

  12. esmi
    Forum Moderator
    Posted 2 years ago #

    How do I get WordPress to know which CSS rules to put in the generated CSS?

    Via basic conditional statements. if..endif or switch statements. for example:

    // Output option-based style
    if( !function_exists( 'emporium_style') ) :
    function emporium_style() {
    	global $emporium_options;
    
    	// Slider controls
    	if( isset( $emporium_options['display_slider_controls'] ) && $emporium_options['display_slider_controls'] == 'no' ) :?>
    	<style type = "text/css">
    	.eslideshow .auto_controls,.eslideshow .prev, .eslideshow .next {display:none;}
    	</style>
    	<?php endif;
    
    	// eShop panels product title
    	if( isset( $emporium_options['display_eshoppanel_legend'] ) && $emporium_options['display_eshoppanel_legend'] == 'no' ) :?>
    	<style type = "text/css">
    	.eshoppanels a span {position:absolute;top:-9999px;left:-9999px;}
    	</style>
    	<?php endif;
    
    	// Site title font
    	if( isset( $emporium_options['header_font'] ) && $emporium_options['header_font'] != 'Default' ) :
    	switch ($emporium_options['header_font']) {
    
    		case 'Fredericka';
    		$font = 'Fredericka';
    		$family = 'serif';
    		$font_size = '2.3em;';
    		$font_face = "@font-face {font-family:Fredericka;
    		src: url('" . get_template_directory_uri() . "/fonts/FrederickatheGreat-Regular.ttf'),
    		url('" . get_template_directory_uri() . "/fonts/FrederickatheGreat-Regular.ttf');}";
    		break;
    
    		case 'HennyPenny';
    		$font = 'HennyPenny';
    		$family = 'serif';
    		$font_size = '2.8em;';
    		$font_face = "@font-face {font-family:HennyPenny;
    		src: url('" . get_template_directory_uri() . "/fonts/HennyPenny-Regular.ttf'),
    		url('" . get_template_directory_uri() . "/fonts/HennyPenny-Regular.ttf');}";
    		break;
    
    		case 'NovaSlim';
    		$font = 'NovaSlim';
    		$family = 'sans-serif';
    		$font_size = '2.5em;';
    		$font_face = "@font-face {font-family:NovaSlim;
    		src: url('". get_template_directory_uri() . "/fonts/NovaSlim.ttf'),
    		url('" . get_template_directory_uri() . "/fonts/NovaSlim.ttf');}";
    		break;
    
    		case 'Sofia';
    		$font = 'Sofia';
    		$family = 'cursive';
    		$font_size = '3em;';
    		$font_face = "@font-face {font-family:Sofia;
    		src: url('" . get_template_directory_uri() . "/fonts/Sofia-Regular.ttf'),
    		url('" . get_template_directory_uri() . "/fonts/Sofia-Regular.ttf');}";
    		break;
    
    		case 'Milonga';
    		$font = 'Milonga';
    		$family = 'serif';
    		$font_size = '2.5em;';
    		$font_face = "@font-face {font-family:Milonga;
    		src: url('" . get_template_directory_uri() . "/fonts/Milonga-Regular.ttf'),
    		url('" . get_template_directory_uri() . "/fonts/Milonga-Regular.ttf');}";
    		break;
    
    		case 'CabinSketch';
    		$font = 'CabinSketch';
    		$family = 'cursive';
    		$font_size = '2.7em;';
    		$font_face = "@font-face {font-family:CabinSketch;
    		src: url('" . get_template_directory_uri() . "/fonts/CabinSketch-Regular.ttf'),
    		url('" . get_template_directory_uri() . "/fonts/CabinSketch-Regula.ttf');}";
    		break;
    
    	}
    	?>
    	<style type = "text/css">
    	<?php echo $font_face;?>
    	#header h1 {font-family:<?php echo $font;?>, <?php echo $family;?>;font-size:<?php echo $font_size;?>;}
    	</style>
    	<?php endif;
    }
    endif;
    add_action( 'wp_head', 'emporium_style' );
    
    // Output sidebar positioning
    if( !function_exists( 'emporium_sidebar_position') ) :
    function emporium_sidebar_position() {
    	global $emporium_options;
    	if( isset( $emporium_options['sidebar_position'] ) && $emporium_options['sidebar_position'] == 'right' ) {
    		$emporium_c = 'left';
    		$emporium_v = 'right';
    		$emporium_innerwrap_bg = 'sidebar-right.png';
    	}
    	else {
    		$emporium_c = 'right';
    		$emporium_v = 'left';
    		$emporium_innerwrap_bg = 'sidebar-left.png';
    	}
    	?>
    <style type = "text/css">
    #content {float:<?php echo $emporium_c;?>;margin-<?php echo $emporium_c;?>:20px;}
    #vertical {float:<?php echo $emporium_v;?>;}
    #innerwrap {background-image:url(<?php echo get_stylesheet_directory_uri() . '/images/' . $emporium_innerwrap_bg;?>);background-position:<?php echo $emporium_v;?>}
    #vertical .wrapper {top;margin-<?php echo $emporium_c;?>:23px;margin-<?php echo $emporium_v;?>:2px;}
    </style>
    	<?php
    }
    endif;
    add_action( 'wp_head', 'emporium_sidebar_position' );
  13. victor_jonsson
    Member
    Posted 2 years ago #

    Okey, first off, thank you for trying to help me Esmi. It's really appreciated.

    But, If I would consider outputting the CSS code in the head of the HTML-document a reasonable solution I wouldn't have asked this question in the first place. It's way to much CSS to send along with every request in my case.

    All I really wanted to know (which i tried to explain in my first post) was if there is a "best practice" when you want to bootstrap wordpress from a file within a theme or a plugin. I'm starting to think there isn't :)

  14. blogger323
    Member
    Posted 2 years ago #

    Hi, victor_jonsson.

    I have also been interested in implementing dynamic CSS. My rough idea is to use the Rewrite API. I might learn from the way of making feed content. But I haven't done it.

    Another posibility is the way of localizing scripts with wp_localize_script. But it seems that we don't have any similar functions for CSS registerd by wp_enqueue_style.

    Sorry for being without concrete conclusion.

  15. Ming Sheu
    Member
    Posted 2 years ago #

    Is it possible to take a step back and explain what you are trying to accomplish and what your goals are?

    Are you trying to avoid bootstrapping WordPress altogether?

    Are you trying to build a plugin/theme that is not dependent on a specific/hardcoded WordPress install location?

    Is this single use code and customizations/hardcoding is acceptable?

    Are you trying to optimize for server performance?

    Are you trying to optimize for client side performance?

    Do you really need to generate CSS on the fly on any given page load?

    From your last post:

    All I really wanted to know (which i tried to explain in my first post) was if there is a "best practice" when you want to bootstrap wordpress from a file within a theme or a plugin. I'm starting to think there isn't :)

    If that is really all you want to know, then you are probably looking at using the query_vars filter and parse_request action hooks. This will allow you to generically leverage WordPress without having to know or care where WordPress is installed.

  16. victor_jonsson
    Member
    Posted 2 years ago #

    Are you trying to avoid bootstrapping WordPress altogether?
    I guess so. I want to bootstrap only what is needed to get access to the most basic functionality in WordPress. Ideally, WordPress shouldn't parse the request since that wouldn't be necessary in this case. If it's possible to hook into the request parsing process that might be an option.

    Are you trying to build a plugin/theme that is not dependent on a specific/hardcoded WordPress install location?

    Yes, this would be done in a theme. And yes, I don't want to write code that makes to much assumptions about how the files is structured in the application. I know this makes me come of as pedantic since probably 99.99% of all WordPress applications has the same file structure. But never the less, include '/../../some-file.php'does feel really hard coded and it makes wanna hurl when I'm forced to put code like that in my software :)

    Is this single use code and customizations/hardcoding is acceptable?

    There you "hit your head on the nail" (old Swedish saying :) ). It probably is acceptable. I just thought that I should ask you wp pros if there is any alternative solutions that would be preferable.

    Are you trying to optimize for server performance? / Are you trying to optimize for client side performance?

    I would prioritize the client side performance in this case. Like a said in an earlier post, I could simply write the generated CSS to a file and enqueue it but I felt that my programming logic would become more complex in that case (but I might end up using this solution anyway)

    Do you really need to generate CSS on the fly on any given page load?

    The answer would be yes!

    Thanks so much for your input Ming. I will look into query_vars and parse_request!

    / vic

  17. Ming Sheu
    Member
    Posted 2 years ago #

    It sounds like you have some competing goals as is usual in these situations. You should probably look at your objectives and prioritize them for your project.

    On one extreme, bootstrap WordPress and dynamically generate CSS for simple management and ultimate flexibility in install configurations/locations.

    On the other extreme, write custom code to directly access the database and pre-generate CSS that is minified, compressed and cacheable to squeeze every bit of performance on the server and for the client.

    And then, there's the gray area between the two.

  18. mobilewebexpert
    Member
    Posted 2 years ago #

    Hiya Victor,

    I have the same issue as you originally did. I can see your concern about referencing parent directories to load the bootstrap, but (as all wordpress themes are located 3 directories down from the main WP install directory) I do not see the
    require '/../../../wp-load.php'; // load wordpress bootstrap
    line causing any problems - unless this wp-load.php is renamed in a future version, which I'd guess is pretty unlikely(?).

    I know it's not a nice coding practice, but I am pretty confident that this technique is sturdy and future-proof.

    Anyway, I'm also just wondering what solution you used in the end??

  19. John Huebner
    Member
    Posted 1 year ago #

    I know this is an old thread, but I was looking for a solution to this same problem and a search for "creating dynamic css with wordpress" returned this as the first result so, I thought I would post my solution here so that others can find it.

    This can be done acceptably well by using admin-ajax.php which is designed to allow you to access WP and only load what is necessary to do so.

    When you enqueue your style sheet, do it like this:

    wp_enqueue_style('dynamic-css',
                     admin_url('admin-ajax.php').'?action=dynamic_css',
                     $deps,
                     $ver,
                     $media);

    then create s function to load you dynamic css file

    function dynaminc_css() {
      require(get_template_directory().'/css/dynamic.css.php');
      exit;
    }

    then add your ajax actions

    add_action('wp_ajax_dynamic_css', 'dynaminc_css');
    add_action('wp_ajax_nopriv_dynamic_css', 'dynaminc_css');
  20. Paul van Zyl
    Member
    Posted 1 year ago #

    @hube2

    thats the first answer that seems to be on the right track, I'd like the neatness of having styles set in options in a separate file without essentially loading WP twice,

    the above looks like it might work, can you explain a little bit more ?

    regards.

    Paul

  21. John Huebner
    Member
    Posted 1 year ago #

    That's pretty much the entire explanation. You basically enqueue an AJAX function as your css file. The AJAX function loads the script that will output your dynamic css. If you need additional information about using AJAX in WP you can see the codex page.

    The file that I would require "dynamic.css.php" would look something like this:

    <?php
      header('Content-type: text/css');
      // I can access any WP or theme functions
      // here to get values that will be used in
      // dynamic css below
    ?>
    /* CSS Starts Here */
    
    .example-selector {
      color: <?php echo $color; ?>;
    }
  22. Endlyss
    Member
    Posted 1 year ago #

    @Hube2

    You are my savior at the moment :P
    This has been racking my brain all day, and you set in motion the solution for my case, so thank you very much.

    originally I figured the above would work. and it did to a point, yet I still could not define or access variables or use certain functions. (of_get_option in this case).
    Then I remembered that if you are using a framework you have to make sure to require their framework options as well.

    so my in my functions.php I added what you had mentioned.

    wp_enqueue_style('dynamic-css',
                     admin_url('admin-ajax.php').'?action=dynamic_css',
                     $deps,
                     $ver,
                     $media);
    function dynaminc_css() {
      require(get_template_directory().'/css/dynamic.css.php');
      exit;
    }
    add_action('wp_ajax_dynamic_css', 'dynaminc_css');
    add_action('wp_ajax_nopriv_dynamic_css', 'dynaminc_css');

    and I am using Options framework, so in the dynamic stylsheet I had to include this at the top.

    <?require('../inc/options-framework.php');
        header("Content-type: text/css; charset: UTF-8");
    //Now here, I can define any variables I need using the "of_get_option"
    //That comes with the Options Framework (for example the below to get
    //the background.
        $body_background = of_get_option('background_picker');
    ?>
    /*--End PHP, Begin CSS---*/
    body
    {
    background: <?php echo $body_background['color'] . ' url(' . $body_background['image'] . ') ' . $body_background['repeat'] . ' ' . $body_background['position'] . ' ' . $body_background['attachment'];?>;
    }

    I tip my hat to you, good sir. Thanks again...figured I would share that it worked for me. Maybe someone will find it useful.

Topic Closed

This topic has been closed to new replies.

About this Topic

Tags

No tags yet.