How does one create Dynamic CSS and JavaScript On-The-Fly (using PHP).
This needs to be done as different pages have different set of elements sometimes, so wrapping and sending a large CSS/JS everytime would be overkill.
And why do many sites have link tags like this:
<link rel='stylesheet' type='text/css' href='css/style.css?pg_id=43&post=62'>
How does the CSS come to know the GET parameters?
Since this might involve URL rewriting or using the header function, please supply short examples
So, there's a few different approaches you can take here. First, if you have access to apache's virtualhost files, you can set CSS to be read by a php interpreter. I've never done this and wouldnt exactly recommend it but an example is:
<VirtualHost *:80>
AddType application/x-httpd-php .css
</VirtualHost>
This can also be done in your .htaccess file.
Alternatively, you can make a link like
<link rel='stylesheet' type='text/css' href='css/style.php?pg_id=43&post=62'>
and put
<?php header("Content-type: text/css"); ?>
as the first line.
I've never considered Vinicius' technique but I don't doubt that has its own set of advantages and disadvantages too.
PS - sometimes GET variables are uses for caching purposes (or actually to prevent caching by appending the current unix timestamp to the css link with php like
<link href="style.css?<?php echo time()" type="text/css" rel="stylesheet" />
A request to a .css or .js file can be redirected to a PHP script using, for example, an .htaccess (in Apache), so even if the src attribute is "style.css", it's actually a PHP script that is responding to the user.
Your CSS and Javascript files are cached, I would not recommend serving different style sheets / js files unless they're >200KB or so in size.
And yes, you can reference any server-side page with parameters (.php or whatever extension) as long as it returns the correct Content-Type for that file.
Sidenote: Usually if you have parameters and are dynamically serving files in this manner, I believe they will not be cached automatically unless you set it up to do so.
Simple example:
<link rel="stylesheet" type="text/css" href="/css.php?color=wide-red">
<?php
header('Content-Type', 'text/css; charset=utf-8');
$colorScheme = (string)$_GET['color'];
switch ( $colorScheme ) {
case 'wide-red':
$bgColor = 'c0c0c0';
$fgColor = 'ffffff';
$width = '1280px';
break;
case 'normal-gray':
$bgColor = '333333';
$fgColor = 'ffffff';
$width = '960px';
}
break;
}
?>
body {
background:<?php echo $bgColor;?>;
color:<?php echo $fgColor;?>;
width:<?php echo $width;?>;
}
You can use echo, you can use a templating system, you can pull in other css files with file_get_contents, key thing is you need to send the right Content-Type, grab the right parameters and have a default fallback if no parameters are given.
Related
I'm a novice php learner, I was experimenting how to link different php files dynamically. While experimenting, I realize I can create variables in my php files and make my template files echoes out the html I need without editing my template files......
for example:
Within about-me.php page, I have included my header.php and footer.php using
<?php include ('includes/header.html'); ?>
<?php include ('includes/footer.html'); ?>
then I create a variable
$page_title = 'CompanyABC';
and echo out in the header.php
$page_title = 'South Asia Exact';
Now my question is can I do this to my inline css also?
for example, I have create a variable, that store all my inline css:
$page_inlinecss = "#SAEcontentR div#certification_certificate {
margin:0 auto 0 auto;
width:580px;
height:464px;
}\n";
then I echo out in my header.php like so:
<style type="text/css">
<?php echo $page_inlinecss; ?>
</style>
I have tried it and it works, but I want to know is it the right way to do it?
There isn't a right way to do inline CSS
Your code will work, it will produce a valid page, and it will look absolutely fine to the user. BUT you shouldn't do it that way.
So, why shouldn't you do it that way?
Maintainability is the main reason that you shouldn't handle CSS this way. It is far easier to manage a separate CSS file than to pick through PHP code looking for CSS rules to change.
It looks like the data you're storing is static, the point of a variable is to store data that can change. Things like the name of the website (Company ABC) are unlikely to change during the execution of the script, so you should include them in the static HTML template.
On top of this are issues like caching (most browsers cache .css files, saving you bandwidth) and accessibility (screen readers may not know how to deal with inline styles & js).
How should you handle dynamic styles?
One way to handle dynamic styles (that is -- styles based on information which will be different on different page loads) with a combination of PHP and CSS is to define class styles in your external document and then use PHP to apply them.
For example, put this in styles.css:
span.greentext { color: #0f0; }
And this in your PHP file:
<span class='<?php echo ($someCondition) ? "greentext" : null; ?>'>Some text</span>
Or, if you have more styles to handle:
Alternatively, you could load a specific stylesheet upon a condition:
<?php if($someCondition): ?>
<link rel="stylesheet" href="styles/conditional.css" type="text/css" media="screen">
<?php endif; ?>
Hope this helps, and please don't use inline CSS, or variables, unless necessary. You'll thank yourself for it when you have to change the site 5 months down the line.
Can you do this? Yes.
Should you do this? Ehh. (No. was a bit harsh...)
Better to store the CSS filename in a php variable, then in the header add:
<link rel="stylesheet" href="<?php echo $this_page_style_sheet; ?>" />
There is no right or wrong in this case.
You may store the CSS in a string and echo it as you see fit. Or you may even embed it in your includes/header.html file. It's up to you.
Personally, if it is a collection of CSS rules, I would keep it in its own CSS file, and just echo the filename when needed.
$css_filename = "/path/to/rules.css";
// ... etc etc
<link rel="stylesheet" href="<?php echo $css_filename; ?>">
This is a beauty and a pitfall of the way the system works. You can do that, it works and it doesn't seem to present any immediate and glaring security issues. I don't know if that was an intended use of PHP, but it works so if it fits your situation you can use it. The pitfall comes when enough of these little workarounds are used that eventually a security issue could arise somewhere, but I don't recall CSS ever being used as a vector for an attack.
You can do this to generate dynamic css
file css.php
<?php
header("Content-Type: text/css");
echo 'p {color:red}';
?>
html (not complete but it should work cross browser)
<link rel="stylesheet" href="css.php" type="text/css" />
<p>This should be red</p>
Some more strict/uptight folks might say that proper CSS doesn't need variables, yadda yadda.
Personally I think if this works, then it's a clever way to add some ease-of-use to CSS. I'm all for it.
This is more a question of what browsers will do, rather than the back-end architecture.
I am using codeigniter and have a controller setup to handle assets (CSS, JS, and images), and at the moment I am simply processing the PHP out of CSS files and presenting them as CSS files to the browser, so www.mysite.com/asset/home.css will call the asset class and generate the CSS file for home from a single file.
I would like to make the request for the CSS files more dynamic, so that the request will determine multiple files that should be combined, and then passed to less.php for parsing and minimization.
Taking into account issues of caching, what would be the best method of passing variables to the CSS class? Flat Link URI variables? Traditional GET URI? I could use a database to reference a given name for its components, but isn't that a lot of overhead?
Any thoughts or opinions are welcomed!
++ How would browsers handle something like standard.menu.comments.css?
+++ I ended up going with a URI string appended to the file. It's not as clean I would want, but it appears to be working. I will likely move to a flat slash separated URI parser soon to clean up the request lines. Thanks for your help!
You can create a file style.php with the following header:
<?php header("Content-type: text/css"); ?>
And link this style in your template:
<link rel="stylesheet" type="text/css" media="screen" href="style.php?color=red">
Then you can import some stylesheets in your style.php:
#import ("someStyle.css");
Or you can pass some $_GET variables and create conditional styles:
<?php
if ($_GET['color'] == 'red')
{
echo ".myBlock {background: #ff0000;}";
}
else
{
echo ".myBlock {background: #00ff00;}";
}
?>
If you just don't want your .css files to be cached, append random $_GET variable to your linked style:
<link rel="stylesheet" type="text/css" media="screen" href="style.css?<?php echo time(); ?>">
Does anyone know how to achieve something like TypeKit when combining multiple CSS request? Maybe I'am not aware of that but when you list some fonts the site would generate (maybe dynamic) CSS like 567,568,569.css lo load the font-file. I thought of it as dynamic as it would change if you use other combination (in this case font ID).
I use the technique described by Carpetsmoker, but I didn't like the fact that the PHP script is invoked every time. On Apache, you can set the following rewrite rule (in .htaccess):
RewriteCond %{REQUEST_URI} ^/css/cache
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^css/cache/(.*)$ /css/csscacher.php?files=$1 [L]
So say a request comes in for /css/cache/file1.css-file2.css, Apache will test for its existence. If it doesn't exist, the request will be forwarded to the csscacher.php script with the filename passed as the value of the "files" param. csscacher.php will load and combine the multiple files, send the result to the browser, but also write the result to /css/cache/file1.css-file2.css. All subsequent requests will be served as a static file.
To clear the cache, you'd just delete everything in the /css/cache folder. csscacher.php will recreate them from the source files as requests come in. More detail here.
You could also just use
#import url('reset.css');
at the top of your main css fiel to import other css files on the fly.
Have a look at the Google minify project. It offers a good solution to combine and also compress your JavaScript or CSS files. It is a PHP library that you can set up on your webserver with a script that takes a list of JS or CSS files and outputs a concatenated version. It also caches the result.
The implementation could be separated into three steps. Firstly, define a control wraps all the reference JS files.
Secondly, during the rendering of that control, using any kind of algorithm (e.g. encoding / encrypting) for all file paths to a string, and generate the script tag with a src which points to a certain handler with that generated as querystring.
e.g. Image we have two files: a.js and b.js, we have a control wraps them and generates the script tag like:
<script type='text/javascript' src='/js.php?include=encodeab'></script>
Thirdly, when client side displays the html page and sends request for that script tag, a certain server side handler (js.php in above case) will decode / decrypt that querystring to a list of included files, then read content of them, combile together and output to stream.
Hope this helps.
Be wary using dynamic js or css files as you may accidentally force the user to download them on each page (instead of using browser caching).
You can include multiple javascript/php files into one file, then give it a header of type javascript:
header("Content-type: text/javascript");
include('javascript1.php');
include('javascript2.js');
The same holds true for CSS.
Resources:
http://www.javascriptkit.com/javatutors/externalphp.shtml
http://www.webmasterworld.com/php/4239826.htm
You can use something along the lines of:
<?php
header('Content-Type: text/css');
if (isset($_GET['files']))
{
$files = explode(',', $_GET['files']);
foreach ($files as $file)
{
# BEWARE!
# What happens if the file is ../../../../../../../../etc/passwd?
$file = str_replace('..', '', ltrim($file, '/'));
include($file);
}
}
?>
test.html
<html>
<head>
<link rel="stylesheet" type="text/css" href="css.php?files=style1.css,style2.css" />
</head>
<body>
<h1>This should be red</h1>
<p>red border</p>
</body>
</html>
style1.css
p { border: 1px solid red; }
style2.css
h1 { color: red; }
This is a simple example, you can easily expand it to allow javascript files. Another good optimisation would be setting the Last modified headers based on the mtime of the .css files (use stat()) ... But the general idea should be clear.
BEWARE, to be honest, I'm not sure if the escaping/parsing of the $_GET['files'] is enough ... Please research this topic to be sure, this can a very dangerous security problem :-)
Hope this is enough to get you in the right direction.
You can do something close by calling a dynamic JS file:
start with a php file and then in it:
<?php
if(isset($_GET['jsOne'])){
include'example.com/js/one.js'; // points to some .js file
}
if(isset($_GET['jsTwo'])){
include'example.com/js/two.js'; // points to some other .js file
}
if(isset($_GET['jsThree'])){
include'example.com/js/three.js'; // points to yet a another .js file
}
?>
and in the header just have:
<script type="text/javascript" src="js/allScripts.php?jsOne=yes&jsThree=yes"> and so on
Hope this helps.
ih ave read about the technique to allow dynamic HTML stylesheets using PHP's preprocessor, however I was windering how safe this tecnique is, and if for any reason it is discouraged.
For example, instead of using typical:
<link rel="stylesheet" type="text/css" href="http:mysite.com/style.css/>
I could use:
<link rel="stylesheet" type="text/css" href="http:mysite.com/style.php/>
What do you think?
It's perfectly fine.
I'd suggest setting the following header in the PHP though:
Header("Content-Type: text/css");
If you can use .htaccess files you can set it up to parse *.css files as PHP using:
AddHandler application/x-httpd-php .css
Then you can use PHP directly within your *.css files.
Be sure to also set the header type to text/css as the others have mentioned as well:
header('Content-type: text/css');
It's only as safe as the code that you put into style.php.
Yes, you can use PHP to generate your stylesheet. Make sure to declare the output properly as CSS by sending an appropriate Content-Type value specifying both the media type and the character encoding.
But note that it costs additional time and resources to generate the stylesheet with every request. So you should add some kind of caching mechanism (static files and HTTP caching) to reduce server load and even unnecessary requests.
As others have mentioned, PHP can be used to output any kind of text. So it's not a problem to output dynamic CSS (or even dynamic JavaScript). Be aware though that you're increasing your server load by doing this. The server will have to fire up the PHP engine to serve what would otherwise be a simple static .css file.
You can render any kind of Text Output with PHP (and other stuff) including CSS, just make sure the right header is given header('Content-Type: text/css; charset=iso-8859-1'); (or any other charset).
But to be honest I can't think of an Situation were it would be necessary to use a dynamic stylesheet in that manner.
Does anybody know of an automated way of telling whether a PHP script is being called directly (as a HTML page), or as a JavaScript, or as a CSS Stylesheet?
Without GET variables, or setting a flag in the file ( that is what I am doing right now).
Just curious.
EDIT: Some background because it was asked for in answers: The reason why I want this is a framework that I use when serving HTML pages as well as when serving CSS files. This frameweork has a custom error handler. When I'm in JS "mode", I would like to throw errors as a JS alert(). When I'm in CSS mode, maybe a red body background or something. I would like to avoid working with flags (?mode=css) or constant definitions for the sake of code cleanness, but several answerers have confirmed that there is no "magic" way of finding out what a resource is being used for.
So you want to distinguish between:
<link type="text/css" rel="stylesheet"
href="http://example.com/path/to/php-file.php" />
<script type="text/javascript"
src="http://example.com/path/to/php-file.php"></script>
Or simply opening
http://example.com/path/to/php-file.php
in a browser.
There's no flag set in these cases to distinguish how the file was called. You can examine the $_SERVER array by doing <?php print_r($_SERVER); ?> and they should be identical in each case.
I take it you're adding ?mode=css or ?mode=js to the end of the url -- that seems like a logical way to switch what kind of output you want. Then in the code you can do:
$mode = (isset($_GET['mode']) ? $_GET['mode'] : '';
switch ($mode):
case 'css':
// css
break;
case 'js':
// js
break;
default:
// default
endswitch;
If I understand you correctly, you have a page which calls itself, (like this):
<?php // page.php
if (is_called_as_js()) {
header('Content-Type: text/javascript;charset=utf-8');
echo "alert('hello');";
exit;
} elseif (is_called_as_css()) {
header('Content-Type: text/css');
echo 'body { color: green }';
exit;
}
?>
<html>
(...)
<script src="page.php"></script>
<link rel="stylesheet" href="page.php" />
In that case, no, there's no way to tell - the browser sends a request saying GET /page.php. No intent is mentioned - just "give me the page and the browser will decide what to do with it". (yeah, yeah, there is Accept and whatnot, haven't seen a modern browser actually using this feature to say "give me this page as CSS", most just say Accept: */*)
If you insist that all your output, be it JS, CSS, or HTML, should be generated with one file, I suggest an URL rewriter (assuming Apache HTTP server, this would be mod_rewrite; most platforms offer this functionality in some way or another). Example using mod_rewrite:
# .htaccess
RewriteEngine On
RewriteRule ^css/(.*) /page.php?type=css&file=$1 [L]
RewriteRule ^js/(.*) /page.php?type=js&file=$1 [L]
This way, request to /css/style.css will look like page.php?type=css&file=style.css when your script is run, similarly for /js/foobar.js.
(Technically, you're still using GET variables to find out if the result is supposed to be HTML,JS,or CSS; but it's not visible to the users, plus you get around some older browsers' limitation "if query string, don't cache or cache brokenly")
No.
There isnt really any reason why you should need to do this though. Either you should have very differnt php files being called as css or js files or you should pass get parameters. They way you layout your code should make this unambiguous.
Although it's not entirely clear to me why you'd want to generate such different filetypes through a single script, you could use different wrappers:
<?php // js.php
define('TYPE','javascript');
require('page.php');
?>
<?php // css.php
define('TYPE','css');
require('page.php');
?>
<?php // page.php
if (!defined('TYPE')) {
?>
<script src="js.php"></script>
<link rel="stylesheet" href="css.php" />
<?php
} else if (TYPE == 'javascript') {
header('Content-Type: text/javascript;charset=utf-8');
?>
alert('hello');
<?php
} else if (TYPE == 'css') {
header('Content-Type: text/css');
?>
BODY { color: red }
<?php
}
?>
You're still getting to page.php in the end, but you now know with what intent.