New Website

I've made a new website, as lynx.io is dead. You can find it here: http://macr.ae/—it's similar in format to lynx.io, but has better articles, and they're all written by me.

JavaScript disabled

While it will still mostly work, a lot of this site's functionality relies on JavaScript - please enable it for the best experience.

Dynamic styles using PHP and Cookies

Ever wondered how you can let your visitors customize your sites design in various ways? It can very easily be done with PHP and cookies. Having dynamic styles could add functionality like adjusting text size, color or background color etc.

In this example I am gonna show you how to make a form which will show some default style settings and let your visitors change them and have them saved as a cookie so the visitor will keep the style. You should read up about the ternary operator if you haven't already.

First, on the page we display the form on, we want to set some default values for the form if a cookie isn't already set, otherwise we will set the old value.

<?php
    // Check if the cookie is already set, otherwise set some default styling options
    // Also, we need to unserialize the value of the cookie as we are working with arrays
    $style = !empty($_COOKIE['style']) ? unserialize($_COOKIE['style']) : null;

    // First check if the keys in the arrays are empty, then check if it starts with #
    $body_background_color = !empty($style['body_background_color']) ? (strpos($style['body_background_color'],"#") !== 0 ? "#". $style['body_background_color'] : $style['body_background_color']) : "#fff";
    $body_text_color = !empty($style['body_text_color']) ? (strpos($style['body_text_color'],"#") !== 0 ? "#". $style['body_text_color'] : $style['body_text_color']) : "#000";
    $body_text_size = !empty($style['body_text_size']) ? $style['body_text_size'] : 12;

    $example_background_color = !empty($style['example_background_color']) ? (strpos($style['example_background_color'],"#") !== 0 ? "#". $style['example_background_color'] : $style['example_background_color']) : "#fff";
    $example_text_color = !empty($style['example_text_color']) ? (strpos($style['example_text_color'],"#") !== 0 ? "#". $style['example_text_color'] : $style['example_text_color']) : "#000";
    $example_text_size = !empty($style['example_text_size']) ? $style['example_text_size'] : 10;

As you can see here, we first have to check if the cookie is set by checking if it is empty. If it isn't, we unserialize the array data stored in the cookie. Then if the indexes in the array is empty or the array is null, they are set to a default value.

Next we want to show the form:

        // If the form hasn't been submitted we should show the form to the user
        if($_SERVER['REQUEST_METHOD'] !== 'POST') {
    ?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<link href="style.php" rel="stylesheet" type="text/css" />
<title>Modify stlye</title>
</head>
<body>
    <form action="<?php echo $_SERVER['PHP_SELF'] ?>"  method="post" name="submit">
        <fieldset>
            <label for="background">Backgorund color</label><br />
            <input type="text" id="background" name="body_background_color" value="<?php echo $body_background_color ?>" /><br />
            <label for="textcolor">Text color</label><br />
            <input type="text" id="textcolor" name="body_text_color" value="<?php echo $body_text_color ?>"/><br />
            <label for="textsize">Text size</label><br />
            <input type="text" id="textsize" name="body_text_size" value="<?php echo $body_text_size ?>"/><br /><br />
            <label for="examplebackground">#example background color</label><br />
            <input type="text" id="examplebackground" name="example_background_color" value="<?php echo $example_background_color ?>"/><br />
            <label for="exampletextcolor">#example text color</label><br />
            <input type="text" id="exampletextcolor" name="example_text_color" value="<?php echo $example_text_color ?>"/><br />
            <label for="exampletextsize">#example text size</label><br />
            <input type="text" id="exampletextsize" name="example_text_size" value="<?php echo $example_text_size ?>"/><br /><br />
            <input name="submit" type="submit" value="submit" />
        </fieldset>
    </form>
    <br />
    <div id="example">
        #example Lorem Ipsum herp derp
    </div>
</body>
</html>

This is a rather basic form and a div with the id #example containing a bit of text.

Next, if the form has been submitted, we want to update the settings and redirect the user back to this page.

<?php
        } else {
            // We set the cookie expiration time to 1 month on from the _update_ of values
            $month = 2592000 + time();

            // We need to serialize the $style array as we cannot store the array directly in the cookie
            $style = serialize($_POST);

            // We set the cookie name to "style" and put in our serialized array $style and expiration date $month
            setcookie("style", $style, $month);

            // Reload the page to make sure changes take effect
            header("Location: index.php");

        }
    ?>

This here serializes (stores an array as a text representation) the form data and sets it to a cookie called "style", which can later be accessed by using $_COOKIE['style'].

Next for the CSS file (which is actually a .php file):

<?php
    header("Content-type: text/css");

    // Check if the cookie is already set, otherwise set some default styling options
    // Also, we need to unserialize the value of the cookie as we are working with arrays
    $style = !empty($_COOKIE['style']) ? unserialize($_COOKIE['style']) : null;

    // First check if the keys in the arrays are empty, then check if it starts with #
    $body_background_color = !empty($style['body_background_color']) ? (strpos($style['body_background_color'],"#") !== 0 ? "#". $style['body_background_color'] : $style['body_background_color']) : "#fff";
    $body_text_color = !empty($style['body_text_color']) ? (strpos($style['body_text_color'],"#") !== 0 ? "#". $style['body_text_color'] : $style['body_text_color']) : "#000";
    $body_text_size = !empty($style['body_text_size']) ? $style['body_text_size'] : 12;

    $example_background_color = !empty($style['example_background_color']) ? (strpos($style['example_background_color'],"#") !== 0 ? "#". $style['example_background_color'] : $style['example_background_color']) : "#fff";
    $example_text_color = !empty($style['example_text_color']) ? (strpos($style['example_text_color'],"#") !== 0 ? "#". $style['example_text_color'] : $style['example_text_color']) : "#000";
    $example_text_size = !empty($style['example_text_size']) ? $style['example_text_size'] : 10;
?>

body {
    background-color: <?php echo $body_background_color ?>;
    color: <?php echo $body_text_color ?>;
    font-size: <?php echo $body_text_size ?>px;
}

#example {
    background-color: <?php echo $example_background_color ?>;
    color: <?php echo $example_text_color ?>;
    font-size: <?php echo $example_text_size ?>px;
}

The code in the header is the same code we had in the previous file with the addition of header("Content-type: text/css"); which tells the browser that this really is a css file. Then we have the layout where we echo the values.

mySQL implementation

To take it further, if you have registered users and want them to be able to have their own style, computer-wide, you could store the serialized array in the user table. Do not forget to validate and escape the form input before sending it to mySQL though. Later, you could just fetch the row from the database instead of fetching the cookie.

About Victor Nagy:

Webdeveloper from Lerum, Sweden, currently living in Skövde and attending HIS, University of Skövde

You can view more articles by this author here.

Tags: php css dynamic style

Comments

Callum Macrae says:

Nice article, shame about the nested ternary :-D

Nate says:

When testing this code I receive the following errors:

Warning: Cannot modify header information – headers already sent by (output started at /index.php:29) in /index.php on line 64

Warning: Cannot modify header information – headers already sent by (output started at /index.php:29) in /index.php on line 67

I have two files. The style.php file and the index.php file contains the code in the first three code blocks as shown in the article.

Any help would be appreciated.

Callum Macrae says:

I didn’t notice that, thanks for pointing it out. I’ve just poked galaxyAbstractor, he’ll fix it soon :-D

The problem is that the headers are sent on line 15 of the first snippet, but then in the third snippet, lines 10 and 13 both try to edit the headers which isn’t possible. Moving all the HTML to below the PHP will solve this problem.

Nate says:

I did some research to attempted to resolve the issue with the obstart(); and obend_clean(); functions which are supposed to allow you to place headers after output by storing the output in an internal buffer. I was unsuccessful in my attempt but I'm new to php and may have not used the functions properly to return successful results.

Callum Macrae says:

I’ve fixed it

Emanuel says:

Was thinking about this a few days ago and I think that it isn’t a good idea if you have too many users. Don’t know if the browser would cache your css file and if it doesn’t it would mean that you would have to parse cookies every time you display a page. I was thinking about saving the data from cookies into a css file for every user and only allow them to customize the site if they have an account, of course you can’t apply this to WordPress, not without some more tweaking and you would have to use more disk space, but wouldn’t affect your speed.

Callum Macrae says:

Yeah, the browser would cache it unless the cache-control header was used in the htaccess or at runtime. This would obviously drive up the amount of requests to the server.

Parsing the cookies isn’t a problem, as the cookies are sent in the header of every request. What WOULD have an affect is parsing the PHP in the CSS file; sending a static file will always use less resources than a dynamic file.

What would be best is to store the style information using JavaScript (+cookies), and then apply it using JS, too. This would take all the strain off the server and would be slightly faster for the user, too :-)

Also, I just noticed an XSS vulnerability: index.php/” onMouseOver=”document.location=evil

says:

Add comment

 

You can use markdown in comments (press "m" for a cheatsheet).

Enable JavaScript to post a comment

Markdown Cheat Sheet

# This is an <h1> tag
## This an <h2> tag
###### This is an <h6> tag

Inline markup: _this text is italic_, **this is bold**, and `code()`.

[Link text](link URL "Optional title")
[Google](http://google.com/ "Google!")

![Alt text](image URL)

![This is a fish](images/fish.jpg)

1. Ordered list item 1
2. Ordered list item 2

* Unordered list item 1
* Unordered list item 2
* Item 2a
* Item 2b

And some code:

// Code is indented by one tab
echo 'Hello world!';

Horizontal rules are done using four or more hyphens:

----

> This is a blockquote

This is an <h1> tag

This an <h2> tag

This is an <h6> tag

Inline markup: this text is italic, this is bold, and code().

Link text Google

This is a fish

  1. Ordered list item 1
  2. Ordered list item 2
  • Unordered list item 1
  • Unordered list item 2
    • Item 2a
    • Item 2b

And some code:

// Code is indented by one tab
echo 'Hello world!';

Horizontal rules are done using four or more hyphens:


This is a blockquote

Toggle MarkDown / HTML (t), full reference or close this