I am creating some dynamic template and I have an issue that I want to use PHP variables in external CSS file.
Example:
if stylesheet is styles.css and then I want to use this file as styles.php so that I can use variables in this file to make css dynamic.
What should I do for this.
Thanks in advance.
Rename file to styles.php (or configure server to run PHP interpreter in CSS files).
Send appropriate Content-Type header:
header('Content-Type: text/css');
Write your code:
<?php
header('Content-Type: text/css');
$a = '#123456';
$b = '#654321';
?>
body > a {
color: <?php echo $a ?>;
}
Use an .htaccess file and the following line:
AddType application/x-httpd-php .css
This will make your server parse .css files as if they were .php.
The problem with making dynamically generated CSS files is that they won't be cached. You'll be forcing to user to hit your server at least twice: once for the php output, and once for the css.
If you're only making a few minor parts of the CSS dynamic, consider creating a regular standard CSS file with suitable defaults in it, and then having your PHP pages output a suitable <style> block which issues the overrides. That way your main CSS file can be cached, and you get dynamic styles at the cost of a few lines of extra output in your PHP file.
I know this is old but #MarcB is incorrect on caching
Here is a cachable version of the php CSS
<?php
ob_start ("ob_gzhandler");
header("Content-type: text/css; charset: UTF-8");
header("Cache-Control: must-revalidate");
$offset = 60 * 60 ;
$ExpStr = "Expires: " .
gmdate("D, d M Y H:i:s",
time() + $offset) . " GMT";
header($ExpStr);
$blue="#00f";
$red="#f00";
$green="#0f0";
?>
#div{
color:<?=$blue?>;
background:<?=$red?>
}
Related
My idea is simple, take all css files and generate one minified in a time of change in some css file. Then tell the browser to clear the cache. If there is an unchanged file in browser cache then use it - so user don't need to redownload it every time.
I'm using the following snip of code to do that. But the part with using cache is a bit buggy, most of time it works but sometimes it tell the browser to use the cached version (as there is no change) and browser is using the old one and user must do client side cache refresh.
Could you give me some advice how to do that, so it would refresh client side browser cache everytime when the change occurs and if there is no change just use the cache?
$cssFiles = getCssFiles();
$fm = new FileMinifier(FileMinifier::TYPE_CSS);
$lastModified = $fm->lastModification($cssFiles);
$savedLastModified = DateUtils::convertToTimestamp($this->system->systemSettings['cssLastChange']);
$etagFile = md5('css-file');
header("Content-type: text/css");
header("Pragma: public");
header('Cache-Control: public');
header("Last-Modified: " . gmdate("D, d M Y H:i:s", $lastModified) . " GMT");
header("Etag: $etagFile");
// if there is a change - generate new minified css
if ($lastModified > $savedLastModified)
{
// take files minify them, save it and redirect to output, update last change time
...
}
// or use already generated
else
{
$ifModifiedSince = (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : 0);
$etagHeader = (isset($_SERVER['HTTP_IF_NONE_MATCH']) ? trim($_SERVER['HTTP_IF_NONE_MATCH']) : false);
// if it is in chache use it! - no need for redownloading
if (strtotime($ifModifiedSince) == $lastModified || $etagHeader == $etagFile)
{
header("HTTP/1.1 304 Not Modified");
exit;
}
$this->data['text'] = file_get_contents(SystemInfo::getServerRoot() . '/public/css/minified.css');
}
What you're trying to do is admirable, but it's a bit of re-inventing the wheel. As far as CSS files, JavaScript files, etc are concerned, modern browsers already do a fine job of pulling unchanged files from the cache.
Manipulating the HTTP headers to notify the browser of a file change is do-able, but there are browser differences (especially older browsers) in how the headers are interpreted which makes that approach fraught with nuance.
It is far easier to accomplish your goal by versioning your CSS includes. A change in file version will prompt the browser to re-download the file.
Example:
Before file change:
<link href="http://yourwebsite.com/file.css?_=1.0.0.1" rel="stylesheet" type="text/css">
After file change:
<link href="http://yourwebsite.com/file.css?_=1.0.0.2" rel="stylesheet" type="text/css">
All browsers will interpret the change in URI parameter as a new file and will re-download it.
It's also possible to automate the versioning so that you don't need to manually edit the include line after every change. Here's one way to do it...
Example:
<?php
$ver = filemtime($filename);
echo '<link href="http://yourwebsite.com/file.css?_='.$ver.'" rel="stylesheet" type="text/css">';
?>
That code will place append modified date of the file (Unix timestamp format) to the URI of the file include.
I renamed my stylesheet as full.css.php and on the very beginning of the file i wrote this code:
<?php
header("Content-type: text/css; charset: UTF-8");
//here I want to set all my css variables
$font_color = '#ccf';
?>
//here starts the css
body{
color: <?php echo $font_color?>;
}
The browser is giving me this: Resource interpreted as Script but transferred with MIME type text/css: "http://localhost/root/_Viewer/css/full.css.php"..
And then error: "Uncaught SyntaxError: Unexpected token {" (this is the first brace from body css declaration).
If I look in source, I find that my file was sent as application/javascript file, not as text/css:
<script type='application/javascript' src='_Viewer/css/full.css.php'></script>
I know dynamic CSS won't be cached, but it's fine with me. It's more important now to have some settings easy to access.
Need help to fix this.
Btw: I'm running this under XAMPP !
-i forgot to mention: i'm doing similar with one of my js files and it's working just fine ( header("Content-type: application/javascript"); )
Like everyone else I'm storing my site`s display information in style sheet files. And I want to create back-end cms so users will be able to, for example, change < h1 > color, size etc.
So, what's the right way to embed PHP code in my CSS file(s)?
Is adding this header:
<?php header("Content-type: text/css"); ?>
And changing file extension in link:
<link rel="stylesheet" type="text/css" media="screen" href="style.php">
Valid?
And what about JavaScript? At this moment I'm echoing <script type="text/javascript"> tags, but maybe there's also a way to embed everything in the .js files?
Thanks!
Yes, this is perfectly valid.
The same can be done for Javascript too by sending
<?php header("Content-type: application/javascript"); ?>
However, this is not optimal from a performance point of view because a PHP process has to be started for serving those resources.
If you have only very few dynamically changing CSS properties or JS variables, I would consider putting them into the document's head and continuing to serve the external files statically.
Remember that usually, there are no caching headers sent for PHP files. You'll have to take care of sending the correct headers inside your PHP script! Cheers #oracle certified professional for the reminder.
What you're doing is absolutely valid.
However if you're running a bigger site with many visitors, you should concern to just let PHP "build" a "real" CSS file when your user updates his or her design to save your servers performance to better needed things:
<?php
header("Content-type: text/css");
// Your database magic here to fetch the user-specific designs
// open the cached css
$cachefile = "cachedCSS/mycss.css";
if (file_exists($cachefile)) {
// the page has been cached from an earlier request
// output the contents of the cache file
include($cachefile);
// exit the script, so that the rest isnt executed
exit;
}
$fp = fopen($cachefile, 'w');
// save the contents of output buffer to the file
fwrite($fp, ob_get_contents());
// close the file
fclose($fp);
// Send the output to the browser
ob_end_flush();
Read more about it here: http://www.theukwebdesigncompany.com/articles/php-caching.php
Make sure you are parsing the php in those files.
In .htaccess :
AddType application/x-httpd-php .php .css .js
This will ensure that any <?php ?> tags in file types other than .php will be parsed by the server and the php code isn't readable by users.
I'm trying to optimize my web application and unfortunately have ended up with a javascript file size of around 450K - that too after compressing [it would take a while for me to redo the javascripting but until then I have to go live] - I initially had made a number of small javascript libraries to work upon. And what I do is I have a php file which includes all the javascript files and then I included my php file as below:
<script language="js/js.php"></script>
The thing is that I was hoping that my file would be cached upon the first load but it seems every time I refresh the page or come back to it the file is reloaded from the server - I checked this using firebug. Is there anything else that I must add to ensure that my file is cached on the user end.. or am I misunderstanding the idea of a cache here?
You'll need to set some headers in php to ensure the file is cached.
At the top of js.php put:
ob_start("ob_gzhandler");
$expires = 2678400; // 1 month in seconds
header("Pragma: public");
header("Cache-Control: maxage=".$expires);
header('Expires: ' . gmdate('D, d M Y H:i:s', time()+$expires) . ' GMT');
That will add both basic caching + gzip compression on the fly.
Why not to leave it .js file and let web-server take care of caching?
Compression is not the thing you really need but Conditional Get is
Right now I use a PHP script to pull together multiple CSS files into one script and then output them with a content-type of text/css.
The problem them with this is the browser wont cache the file.
Is there a better way of doing this?
Thanks
If you have to serve the CSS via PHP, you can force a cache header to be emitted, so the browser can cache the output if it so desires:
<?php
header('Cache-control: max-age=3600'); // cache for at least 1 hour
header('Content-type: text/css');
readfile('css1.css');
readfile('css2.css');
etc...
Why don't you just use #import in a global css file and link that into your html file?
see: http://www.cssnewbie.com/css-import-rule/
"Cascading style sheets" are so called before CSS files may include others. You can also specify several CSS files in your HTML file (using LINK) instead of including them inline.
Use these facilities and let your web server take care of sending the appropriate headers for client-side caching an handling of conditional HTTP requests.
I use the code posted bellow.
It follows Google's page speed recommendations.
Do notice that readfile is faster that include so should be used.
<?php
#$off = 0; # Set to a reasonable value later, say 3600 (1h);
$off = 604800; # Set to 1 week cache as suggested by google
$last_modified_time = filemtime('csscompressor.php');
$etag = md5_file('csscompressor.php');
ob_start("ob_gzhandler");
ob_start("compress");
header('Content-type: text/css; charset="utf-8"', true);
header("Cache-Control: private, x-gzip-ok=''");
header("Last-Modified: ".gmdate("D, d M Y H:i:s", $last_modified_time)." GMT");
header("Etag: $etag");
header("Expires: " . gmdate("D, d M Y H:i:s", time() + $off) . " GMT");
// load css files
readfile("global.css");
readfile('jquery-theme.css');
// ...
?>
You should also serve all CSS and JAVASCRIPT pages like this:
<script src="http://example.com/myjavascript.js?v=<?=$version=?>" ></script>
The $version variable is controlled by you. It should be set in a site-wide config file. Every time you push an update live you can just change the version on one place and everyone seeing the new content will just push it and not depend on cache.