Creating a PHP and CSS3 Powered About Page

Demo Download

In this tutorial, we will be creating a simple about page that is powered by PHP, HTML5 and CSS3. It will present your contact information to your visitors, with an option for downloading it as a vCard (useful for importing it in third party applications).

You can use today's example as a placeholder for your upcoming personal website, or as an actual about page.


As always, the first step is to write the HTML markup that will be powering our example. This is a simple page the main purpose of which is to present our contact details semantically. This will require adding appropriate meta tags and using the hCard microformat to embed data in the page.


<!DOCTYPE html>
        <meta charset="utf-8" />
        <meta name="description" content="Online info page of <?php echo $profile->fullName()?>. Learn more about me and download a vCard." />

        <title>Creating a PHP and CSS Powered About Page  | Tutorialzine Demo</title>

        <!-- Our CSS stylesheet file -->
        <link rel="stylesheet" href="assets/css/styles.css" />

        <!--[if lt IE 9]>
          <script src=""></script>


        <section id="infoPage">

            <img src="<?php echo $profile->photoURL()?>" alt="<?php echo $profile->fullName()?>" width="164" height="164" />

                <h1><?php echo $profile->fullName()?></h1>
                <h2><?php echo $profile->tags()?></h2>

            <p class="description"><?php echo nl2br($profile->description())?></p>

            <a href="<?php echo $profile->facebook()?>" class="grayButton facebook">Find me on Facebook</a>
            <a href="<?php echo $profile->twitter()?>" class="grayButton twitter">Follow me on Twitter</a>

            <ul class="vcard">
                <li class="fn"><?php echo $profile->fullName()?></li>
                <li class="org"><?php echo $profile->company()?></li>
                <li class="tel"><?php echo $profile->cellphone()?></li>
                <li><a class="url" href="<?php echo $profile->website()?>"><?php echo $profile->website()?></a></li>


        <section id="links">
            <a href="?vcard" class="vcard">Download as V-Card</a>
            <a href="?json" class="json">Get as a JSON feed</a>
            <p>In this tutorial: <a href="">Self Portrait</a> by <a href="">Levy Carneiro Jr</a></p>


The $profile variable you see above, holds an object of the AboutPage PHP class that we will be writing in a moment. It holds our contact details and provides a number of useful methods for generating JSON and vCard files.

As mentioned above, we are using the hCard microformat to embed contact details in the page. This is a simple standard with which we use the class names of regular HTML elements to specify data, easily recognizable by search engines. The hCard holds information about our full name, organization, phone and home page:

<ul class="vcard">
    <li class="fn"><?php echo $profile->fullName()?></li>
    <li class="org"><?php echo $profile->company()?></li>
    <li class="tel"><?php echo $profile->cellphone()?></li>
    <li><a class="url" href="<?php echo $profile->website()?>"><?php echo $profile->website()?></a></li>

You can also optionally specify a home / work address and other kinds of useful information.



One of the points of using a server side language is that we can leave some aspects of the page to be generated on the fly. This frees us from having to manually keep various parts of the page up to date.

In the case with our about page, we have a simple configuration file, which holds the data, used by the page. This same resource is used for the generation of the vCard file and the JSON feed.


$info = array(
    'firstName'     => 'John',
    'middleName'    => 'S.',
    'lastName'      => 'Smith',
    'photoURL'      => 'assets/img/photo.jpg',
    'birthDay'      => strtotime('22-03-1983'),
    'city'          => 'MyCity',
    'country'       => 'United States',
    'street'        => 'My Street 21',
    'zip'           => '12345',
    'company'       => 'Google Inc',
    'website'       => '',
    'email'         => '[email protected]',
    'cellphone'     => '12345678910',
    'description'   => "I am a webdeveloper living in ...",
    'tags'          => 'Developer, Designer, Photographer',
    'facebook'      => '',
    'twitter'       => ''

Not all of these properties are presented on the about page. Some of them (like the address fields, company, email and birthday) are only made available when the user downloads the profile as a vCard or as a JSON file. You can also add quite a few more properties to this array (a complete list is given as a comment in the config.php file).

So now that we have provided all the information we wanted, we need to build a class that will handle the task of presenting a complete about page.


class AboutPage{
    private $info = array();

    // The constructor:

    public function __construct(array $info){
        $this->info = $info;

    // A helper method that assembles the person's full name:

    public function fullName(){
        return $this->firstName().' '.$this->middleName().' '.$this->lastName();

    // Using PHP's Magick __call method to make the
    // properties of $this->info available as method calls:

    public function __call($method,$args = array()){

            throw new Exception('Such a method does not exist!');

            $this->info[$method] = $args[0];
            return $this->info[$method];

    // This method generates a vcard from the $info
    // array, using the third party vCard class:

    public function downloadVcard(){

        $vcard = new vCard;

        $methodCalls = array();

        // Translating the properties of $info to method calls
        // understandable by the third party vCard class:

        $propertyMap = array(
            'firstName'     => 'setFirstName',
            'middleName'    => 'setMiddleName',
            'lastName'      => 'setLastName',
            'birthDay'      => 'setBirthday',
            'city'          => 'setHomeCity',
            'zip'           => 'setHomeZIP',
            'country'       => 'setHomeCountry',
            'website'       => 'setURLWork',
            'email'         => 'setEMail',
            'description'   => 'setNote',
            'cellphone'     => 'setCellphone');

        // Looping though the properties in $info:

        foreach($this->info as $k=>$v){

            // Mapping a property of the array to a recognized method:

                $methodCalls[$propertyMap[$k]] = $v;
            else {

                // If it does not exist, transform it to setPropertyName,
                // which might be recognized by the vCard class:

                $methodCalls['set'.ucfirst($k)] = $v;

        // Attempt to call these methods:

        foreach($methodCalls as $k=>$v){
            else error_log('Invalid property in your $info array: '.$k);

        // Serving the vcard with a x-vcard Mime type:

        header('Content-Type: text/x-vcard; charset=utf-8');
        header('Content-Disposition: attachment; filename="'.$this->fullName().'.vcf"');
        echo $vcard->generateCardOutput();

    // This method generates and serves a JSON object from the data:

    public function generateJSON(){
        header('Content-Type: application/json');
        header('Content-Disposition: attachment; filename="'.$this->fullName().'.json"');

        // If you wish to allow cross-domain AJAX requests, uncomment the following line:
        // header('Access-Control-Allow-Origin: *');

        echo json_encode($this->info);

As you can see from the code below, we are using a third party open source class for the actual generation of the vCard file (vcf). As this class uses its own set of method calls, we will need to transform our configuration file to something that it will understand. We are doing this with the $propertyMap array which maps properties found in our $info array to the names of method calls that will need to be executed on the vCard object. After we configure the $vcard object, we set the content headers and call the object's generateCardOutput() method. This causes the browser to display a file download dialog.

We are doing basically the same thing in the generateJSON method, with the worthy exception that we are not using a third party PHP class, but the json_encode() built-in. We are serving the JSON file with an application/json content type. You can also uncomment the access control header if you wish to be able to access your data via AJAX from other domains.

Now lets see how we are using this class in index.php:


require 'includes/config.php';
require 'includes/aboutPage.class.php';
require 'includes/vcard.class.php';

$profile = new AboutPage($info);

else if(array_key_exists('vcard',$_GET)){

The fragment you see above is found at the top of index.php, before any of the HTML, as we have to be able to set headers. After including the appropriate PHP source files, we create a new AboutPage object with the configuration array as its parameter. After this we check whether the requested URL is ?json or ?vcard, and serve the appropriate data. Otherwise, the regular about page is displayed.


Most of the design of the about page is pretty straightforward. However, a fair share of CSS3 is used to keep the number of images to a minimum. The two buttons - Find me on facebook, and Follow me on twitter, that are positioned below the text, are ordinary hyperlinks with a .grayButton class name. You can see the definition of this class below:


    padding:6px 12px 6px 30px;

    background:-moz-linear-gradient(left top -90deg, #fff, #ccc);
    background:-webkit-linear-gradient(left top -90deg, #fff, #ccc);
    background:linear-gradient(left top -90deg, #fff, #ccc);

    -moz-box-shadow: 1px 1px 1px #333;
    -webkit-box-shadow: 1px 1px 1px #333;
    box-shadow: 1px 1px 1px #333;


    text-shadow:1px 1px 0 #fff;


    text-decoration:none !important;
    box-shadow:0 0 5px #2b99ff;

    background:url('../img/icons.png') no-repeat;
    height: 18px;
    left: 4px;
    position: absolute;
    top: 6px;
    width: 20px;
    content: '';

    background-position:0 -20px;

The code above applies a CSS3 linear gradient to the button, text shadows and rounded corners. It also defines a 0.25 sec transition, that animates the glow that is applied on hover. We are also using the :before pseudo element to create the icon that goes with the button. As we are using a sprite, the only thing that differs between the two buttons is the offset of the background image.

After this we have the "Download as vCard" and "Get as a JSON file" links:


    padding-top: 20px;
    border-top:1px solid #4a4a4a;
    text-shadow: 1px 1px 0 #333333;
    margin:0 auto;

#links a{
    color: #ccc;

#links > a{
    display: inline-block;
    font-size: 11px;
    margin: 0 10px;

#links > a:before{
    background: url("../img/icons.png") no-repeat -10px -60px;

#links > a.vcard:before{
    background-position: -10px -40px;
    top: 0;
    left: -8px;

#links p{
    color: #888888;
    font-size: 10px;
    font-style: normal;
    padding: 30px;

As the #links section element contains more than these links (it contains a paragraph with a link to a great portrait image by Levy Carneiro Jr.) , we have to limit the styling to the anchor elements that are direct children of the section.

With this our PHP & CSS3 powered about page is complete!

To Wrap it up

You can use this about page as a simple placeholder for your personal website. You can also use an existing users database and create beautiful profiles for your users. Combined with some of our previous tutorials, you can display your latest posts on facebook, flickr images or tweets as a personalized home page.

Bootstrap Studio

The revolutionary web design tool for creating responsive websites and apps.

Learn more

Related Articles

Abdullah Al Mamun

Great tut as usual :)


Interesting way for this especially including the vCard!

Beben Koben

we...e...e...used PHP, so cool \m/

Wow, it's gr8. Thanks..

This is a very awesome tut. I just tried to use it but unfortunately I had some problem. I was continually getting the HTTP Error 500. and now when I checked the error log it says "PHP Fatal error: Multiple access type modifiers are not allowed in /var/www/includes/vcard.class.php on line 65". I have no idea how to fix this. Can you help me please?
Thanks a lot

Martin Angelov

Sarmad, you can re-download the demo archive. This was an issue that is now fixed.

Multiple access type modifiers are not allowed in C:\xampp\htdocs\xar\includes\vcard.class.php on line 65


I think you mistakenly typed double 'public'

Martin Angelov

Thank you for catching that. I have no idea how it got in the download archive. Fixed.

please some help

i wanna change $info array, to get date from members table \

i was try this but it didn't work

$query = "SELECT * FROM profile WHERE u_id='$u_id'";
$info= mysql_fetch_row($res);


@Hi Ahmed, maybe I can help you, try this

$query = "SELECT * FROM profile WHERE u_id=’$u_id’";
$info= mysql_fetch_row($res);

$query = "SELECT * FROM profile WHERE u_id=’$u_id’";
$info= mysql_fetch_row($res);

Hope that help

i really like the vcard functionality, its really helpful.


Thank you very much for this tutorial.


with some responsible design it would be very cool