Friday, 24 April 2015

Ten things that should be common sense to the developer-client relationship... but somehow aren't.

Working for a vendor as a developer has opened my eyes to a few things where the client-developer relationship is concerned. Some of these things are mostly common sense... or so I thought. Having been employed by three different vendors, I've seen developers (myself included) totally miss some of these. And the results are often not pretty.



Keep client data safe
from misuse - especially from
you!

1. Respect Client data

This one is a biggie. As a vendor, especially when you're hosting client data on your own servers, you may have access to client data such as the client's customer database. And it doesn't take a genius to figure out that if the confidentiality of this data was ever compromised, things could get sticky. Both professionally and legally.

I've seen developers use one client's data and export it to the staging database of another client, for testing purposes. Even assuming that the original client doesn't find out, what about the client who finds someone else's data on his staging server? Can someone say "crisis of confidence"? If you, as a developer, could handle someone else's data in such a cavalier fashion, why should you be any less careful with my data?

And yes, the last developer I know who did this, lost his job. Deservedly so.



What the client wants is not always
legal or good for him.

2. The Client is always sometimes right

Clients, as a rule, are not just paying you to do the grunt work of building their web portal. They're also paying for a certain amount of expertise, and this should come in the form of recommendations and critique, even if it contradicts what the client wants. Especially if what the client wants is legally questionable (complying would bring you in conflict with existing laws), technologically unsound (complying would crash your server or introduce unreasonably long lag times), or contravenes best practices (such as cross-browser compatibility, searchability or security). The client deserves to be advised of such, and it is your duty, indeed the bare minimum, to do so.

So don't use "customer is always right" as an excuse, and blindly follow what's written in the requirements.

That said...


Know when to shut
the hell up, honey.

3. The Client is usually right

Yes, the client is paying for your expertise. Yes, it's your duty to advise.

And yes, you should totally know when to shut the hell up and do the work.

Sometimes you may not agree with the client. Perhaps you don't think the sidebar text should be in the sidebar. Perhaps you think the font is all wrong. Perhaps you don't agree with certain color choices. Yes, you know more about websites than your client. But it's his money. Your ego needs to take a back seat there.

By all means, make your recommendations. But if the client has noted your objections and dismissed them, for goodness sake, let it stop there and get the job done. The client wants what he wants, and after you've advised him to the contrary, it's his responsibility from thereon. This is not about you.

I once had to work with just such a developer. Her client came with a request and as she was busy, the request was forwarded to me. I performed the necessary changes and because things got really busy after that point, forgot to respond (yes, contravening Point 6 below). The client called me back later to check, and I informed her that yes, the changes were done and apologized for not having informed her earlier. To my surprise, she expressed an amount of gratitude I considered disproportionate to the amount of work I had done (basically one page with two buttons and some text).

Apparently, when the client had asked the other developer to do this originally, the other developer had argued vehemently against the chosen color scheme and page, and this had gone on for over a workday. That I had carried out the request without fuss, in the space of half an hour, seemed like a godsend.

In a nutshell, all I really want to say is - that's company time you're using. Don't waste it on things that are out of your jurisdiction.



Customer checklist is your priority.

4. Client KPIs come first

Somewhat related to the previous point, value-add is a good thing. But it's even better to understand your priorities. There are some things the client doesn't ask for which may or may not be implied. Things such as cross-browser compatibility, W3C compliancy, and so on. And having those things is a good thing.

But the Client's explicitly-stated KPIs should come first.

The client doesn't care about things he never asked for. You could include fifty little freebies that make his system sing like a bird; but if there's even one item on his list that he wanted (and paid for), but isn't there, the project isn't done. Again, that's company time you're using. Make it count.



Email FTW!

5. Verbal doesn't count

Sometimes the Client thinks aloud during a conversation. Sometimes, during a meeting, some stuff gets thrown about. But all this means jacksquat if it's not documented. It's very easy, and dare I say, very convenient, to forget stuff if there's no proof it was ever said, other than a fuzzy metric such as human memory.

Draft an email after each communication, and send it to the person you communicated with, asking for clarification and confirmation on the points made. CC all relevant parties.

That way, if something goes south in the process of getting things done, at least it can be traced. The entire conversation wasn't just a figment of your imagination.

Which also brings us to...


Talk, dammit.

6. Communicate often

When a client sends you an email, the reasonable assumption is that he would like a response today. Sometimes you need time to properly formulate your response. That's perfectly acceptable, and one of the advantages of being able to communicate via written medium. A good limit to set would be to reply all his emails between two to four hours later, if not right away.

Better still, call, and then confirm your conversation via email. (see Point 5)

Some clients may jump to the wrong (or right?) conclusion that you don't care, if you don't respond within a certain time-frame. And unless you're some kind of masochist, you do not want to give that impression.

There was this vendor whom I joined years back. One of the developers, a Burmese, had passed me a client project that I could cut my teeth on. During the next couple weeks, we took turns attending to the client. Midway through the third week, the client emailed my boss to ask if I could be put solely in charge of the project from now on, as I seemed to understand their requirements better. And everybody knows that when the boss gets an email like that, it's pretty damning.

Bear in mind that this was only my third week on the job. Prior to that, I hadn't touched any C# or ASP.NET. Where this was concerned, my Burmese colleague was unquestionably the better programmer. What was the difference?

No prizes for guessing: communication.

To be fair, English wasn't the guy's first language. But he had a bad habit of not answering emails promptly enough, and not reading the emails carefully before working on the requirements, and not clarifying his doubts. I didn't have that problem. It wasn't that I was a particularly good communicator, it was more that my colleague was horrendous at it.



Remind you of anyone?

7. You're not paid to work...

...you're paid to get work done. Many developers can't tell the difference, and that's their undoing.

The client (and by extension, your boss) doesn't care that you spent all night slaving on his shopping cart, as long as it's delivered by 9am in the morning as stated in the project timeline. He doesn't care that you missed your mother's birthday because you had to fix the security bug in his inventory management system. He doesn't care, and he shouldn't care.

So don't imagine that if you're seen staying back late in the office or working on weekends, that it gives you a free pass. You're given eight to nine hours a day (officially at least) to get things done, and failing that, there's a total of twenty-four hours in a day. If you can't get your shit done by the deadline, don't expect any sympathy.

You're not judged by the amount of time you spend in the office, or even by the amount of time you spend actually working as opposed to recreational websurfing. You're judged by what you deliver, and when.



The almighty visual.

8. Clients tend to be visually-oriented

This goes especially true for those not technically trained. When they take a look at what you've done so far, the first thing they're going to see is the front-end and layout. And from there, they'll form a snap judgement of how much work there is left to be done.

Perhaps you've finished coding all the Stored Procedures and security measures. Perhaps your code is now water-tight. But if your front-end is still the same white screen and black text as when you first started, the client is going to feel (despite his better judgement) that not much has been done. Don't hold it against them. If they were capable of thinking like technically-trained professionals, they wouldn't need you.

I've been guilty of this. When I work, a minimal front-end goes up first, and from there on I do a lot of back-end heavy lifting. But sometimes, I have to be reminded to work against my instincts and tinker a little with the front-end every time I finish some of the back-end work, so that my not-so tech-savvy clients have a better gauge of how far along the system is coming.

It's a royal pain in the arse, but it's necessary.



Slow down, dude.

9. Don't deliver too fast

If the client agrees that the next project milestone is deliverable in six days, and you can finish in two, all well and good. But only show him on the fourth day, at the earliest!

This is called "expectation management", and gives you valuable breathing space. You avoid the inevitable pickle when your client gives you something similar to do, but this time, expects it in two days instead of six.

I've been guilty of this as well, especially in an in-house environment. When someone wanted something, I didn't follow procedure to the letter. If something required an hour, I delivered within 15 minutes and moved on. It seemed efficient and convenient, but it was ultimately unsustainable for anyone following up on my cases. Yes, I was something of a cowboy cop in those days. But this would not fly in a vendor environment, especially if your client's getting billed by the hour.



Money's nice. Earn it the right way.

10. Don't work for the client directly

This applies if you're working as a developer for a vendor, and not if you're freelancing. But in the case of the former, it's a huge mistake.

Some clients will find your company's charges exorbitant, and come to the conclusion that paying you directly to take care of their stuff for them outside office hours, would be cheaper. They're right on both counts - your company has to cater for overhead and your salary, and still remain profitable, so the company charges more. And since you don't have to deal with any of that stuff, you could charge less.

It's all very tempting. Side income, what's not to love? But don't do it.

Firstly, even if it's not stated explicitly in your contract that you can't do this, and thus you may not get into any legal trouble over this, it's still blatantly unethical. By siphoning away your company's clients, you are biting the hand that feeds you. Not cool. This isn't about loyalty. It's about professional integrity.

And really, would you trust a client who would resort to something like this? And would any client trust a developer who would agree to it?

And that's the list!

Been guilty of any of these lately? If common sense was as common as its name implied, this list would not exist. But sadly...

You know you're reading this because I'm always sometimes right!
T___T

Thursday, 16 April 2015

Spot The Bug: The Year and Month Combination

Hi and welcome to the very first edition of Spot The Bug!

Are ya ready?!
Somewhere last year, I wrote a piece of PHP code that seemed all right initially, but somehow failed to work early January. It was a simple listing of featured birds for various months, grouped by Year and Month, starting from current Month and Year, and working its way through all records in descending order (latest first, least recent last), for 12 months. Seemed straightforward enough.

The data in MySQL: (tb_featuredbirds)
record_title record_no record_month record_year
Cuckoo 1 4 2014
Pigeon 2 4 2014
Woodpecker 1 5 2014
Eagle 1 6 2014
Owl 1 7 2014
Nightingale 2 7 2014
Tit 3 7 2014
Thrush 1 8 2014
Pelican 1 9 2014
Stork 1 10 2014
Crane 1 11 2014
Raven 1 12 2014
Ostrich 2 12 2014
Dodo 3 12 2014
Mockingbird 1 1 2015
Hummingbird 2 1 2015


The code, in PHP using the mysqli extension:
<?php

$DBConn = new mysqli($DBServer, $DBUser, $DBPass, $DBName);

$year=intval(date("YYYY",strtotime("now")));
$month=intval(date("m",strtotime("now")));

$months=1;

$current_year=0;

while ($months<=12)
{
    if ($current_year!=$year)
    {
        echo "<b><u>";
        echo $year;
        echo "</u></b>";

        $current_year=$year;
    }

    echo "<b>";
    echo date("M",strtotime($year."-".$month."-01"));
    echo "</b>"; 

    $strsql = $DBConn->prepare("SELECT record_title FROM tb_featuredbirds WHERE record_year=? and record_month=? ORDER BY record_no");
    $strsql->bind_param("ii", $year,$month);
    $strsql->execute();

    $strsql->bind_result($bird);

    echo "<ul>";

    while ($strsql->fetch())
    {
        echo "<li>" . $bird . "</li>";
    }

    echo "</ul>";

    $strsql->close();

    $month=($month==1?12:$month-1);
    $year=($month==1?$year-1:$year);

    $months++;
}
?>


The result:
2015
Jan
  • Mockingbird
  • Hummingbird
Dec
    Nov
      Oct
        Sep
          Aug
            Jul
              Jun
                May
                  Apr
                    Mar
                      Feb

                        What went wrong

                        Anything from last year and before, just didn't show up! It was January then, and only stuff that was dated January of this year, was displayed. There were no system error messages.

                        Why it went wrong

                        The error was at these lines. See the logical disconnect there?
                            $month=($month==1?12:$month-1);
                            $year=($month==1?$year-1:$year);

                        Of course, if you progress backwards, once the $month variable reaches January, the next value must be December. By that logic, once the $month variable reaches January, the $year variable should be decremented, to reflect December of the preceding year. I've highlighted the transition below.

                        Step 1: $month=1, $year=2015
                        Step 2: $month=12, $year=2014
                        Step 3: $month=11, $year=2014
                        Step 4: $month=10, $year=2014
                        .
                        .
                        .

                        But if $month variable turns to 12, then the next line, which checks if the $month variable is 1 before decrementing the $year variable, would never fire off! Instead, the progression would be more like:

                        Step 1: $month=1, $year=2015
                        Step 2: $month=12, $year=2015
                        Step 3: $month=11, $year=2015
                        Step 4: $month=10, $year=2015
                        .
                        .
                        .

                        It was all right in the middle or near the end of the current year (because the code would never have come into effect anyway), but once 2015 arrived, the logic bug kicked in. Because there were no records for the year of 2015 other than January, no records would be returned.

                        How I fixed it

                        I basically switched the two lines around, and it worked like a charm.
                            $year=($month==1?$year-1:$year);
                            $month=($month==1?12:$month-1);

                        The new result:
                        2015
                        Jan
                        • Mockingbird
                        • Hummingbird
                        2014
                        Dec
                        • Raven
                        • Ostrich
                        • Dodo
                        Nov
                        • Crane
                        Oct
                        • Stork
                        Sep
                        • Pelican
                        Aug
                        • Thrush
                        Jul
                        • Owl
                        • Nightingale
                        • Tit
                        Jun
                        • Eagle
                        May
                        • Woodpecker
                        Apr
                        • Cuckoo
                        • Pigeon

                        Moral of the story

                        Sequence matters. It matters a lot! Boy, did I feel like a noob when I debugged.

                        Thanks for joining me for Spot The Bug. Join me again next time. It's a date!
                        T___T

                        Thursday, 9 April 2015

                        The Impending Demise of Internet Explorer

                        Internet Explorer is dead! Well, sort of.

                        Yep! Party time, baby.


                        The demise of what could arguably be the most despised browser on the Internet (after Netscape Navigator, that is) was reported last month.

                        Microsoft will be working on a new browser, currently known as "Project Spartan".

                        This is not going to be one of those constructive commentaries over the Internet detailing the pros and cons of Microsoft's new browser baby. Firstly because I don't have a Windows 10 Trial running, and secondly because I'm too... well, ecstatic.

                        I mean, this is Internet Explorer. How many ways do I not love thee? Let me count the ways...

                        Developing for it has been a royal pain in the ass. I recall the days and nights of feverishly adjusting HTML and CSS code to hammer it into presentable shape for, like, five different versions. And at that time, IE 10 hadn't even been released yet! We used to have to run software like IETester just to make sure our websites ran on that damn thing in all its myriad versions. Gettin' real tired of that shit, yo.

                        IE Tester


                        Not to mention that sometimes JavaScript didn't run as expected on IE. There's a long boring story revolving around JavaScript and Microsoft's proprietary JScript, but I'm not going to go into it. You can get a rough idea here. Then again, considering this is Microsoft we're talking about, our problems on that front may not be over.

                        Suffice to say, I was not at all a big fan of Internet Explorer. The fact that Microsoft is no longer going to make it the de facto browser is the best news I've heard all week. It will still be available for legacy purposes, but no further work will be done on it... I hope. It takes a while for any technology to truly die. I mean, how many years has it been since classic ASP was no longer actively supported? Ten, eleven? It's still hanging on to this day.

                        What next?

                        The new browser is slated to be more lightweight, more friendly, and more consistent with web standards.

                        I'm wondering how AJAX runs on that. Though, at least where Greek mythology is concerned, anything named "Project Spartan" being anathema to something called "AJAX" would be strangely incongruous. In that same vein, I'd have to wonder how Trojan Horses would react to it!


                        Enough horsing around!

                        OK, enough of the corny and nerdy Trojan War references. It's time to launch a thousand ships in celebration!

                        This can only be a good thing. I'm dead serious.
                        T___T

                        Thursday, 2 April 2015

                        Web Tutorial: The Faux 3D Easter Egg (Part 2/2)

                        Welcome back! This is where we apply some 3D effects to make it look, well, 3D.

                        Now, add another div inside the egg div.

                                <div class="egg">
                                    <div class="egg_reflection">

                                    </div>

                                    <div id="eggpattern" class="pattern_wrapper">


                        Then create the egg_reflection class as follows.

                                    .egg_reflection
                                    {
                                        opacity: 0.6;
                                        filter: alpha(opacity=60); /* For IE8 and earlier */
                                        -webkit-border-radius: 63px 63px 63px 63px / 108px 108px 72px 72px;
                                        border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
                                        width:200px;
                                        height:300px;
                                        position:absolute;
                                        z-index:100;

                                        background: -moz-radial-gradient(100px 100px, ellipse cover,  #FFFFFF 0%, #444444 58%); /* FF3.6+ */
                                        background: -webkit-gradient(radial, 100px 100px, 0px, center center, 100%, color-stop(0%,#FFFFFF), color-stop(58%,#444444)); /* Chrome,Safari4+ */
                                        background: -webkit-radial-gradient(100px 100px, ellipse cover,  #FFFFFF 0%,#444444 58%); /* Chrome10+,Safari5.1+ */
                                        background: -o-radial-gradient(100px 100px, ellipse cover,  #FFFFFF 0%,#444444 58%); /* Opera 12+ */
                                        background: -ms-radial-gradient(100px 100px, ellipse cover,  #FFFFFF 0%,#444444 58%); /* IE10+ */
                                        background: radial-gradient(ellipse at 100px 100px,  #FFFFFF 0%,#444444 58%); /* W3C */
                                        filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#FFFFFF', endColorstr='#444444',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */
                                    }


                        I don't really want to go into how a radial gradient CSS is created, so I got the CSS for the radial gradient here (http://www.colorzilla.com/gradient-editor/). It has to be a darker shade of gray (#444444) to white (#FFFFFF), and set to translucent (opacity 60%). position:absolute and z-index:100 overlays the translucent egg shape over the first egg outline. The rest of the specifications are the same for the class egg.

                        Does this look 3D yet?




                        Let's add a shadow under the spinning egg to enhance the illusion.
                                <div class="egg">
                                    <div class="egg_reflection">

                                    </div>
                                    <div id="eggpattern" class="pattern_wrapper">
                                        <div class="patterns">
                                            <div class="pattern_wrapper">
                                                <div class="pattern pattern1">
                                                   
                                                </div>
                                                <div class="pattern pattern2">
                                                   
                                                </div>
                                                <div class="pattern pattern3">
                                                   
                                                </div>
                                            </div>
                                            <div class="pattern_wrapper">
                                                <div class="pattern pattern1">
                                                   
                                                </div>
                                                <div class="pattern pattern2a">
                                                   
                                                </div>
                                                <div class="pattern pattern3a">
                                                   
                                                </div>
                                            </div>
                                            <div class="pattern_wrapper">
                                                <div class="pattern pattern1">
                                                   
                                                </div>
                                                <div class="pattern pattern2">
                                                   
                                                </div>
                                                <div class="pattern pattern3">
                                                   
                                                </div>
                                            </div>
                                            <div class="pattern_wrapper">
                                                <div class="pattern pattern1">
                                                   
                                                </div>
                                                <div class="pattern pattern2a">
                                                   
                                                </div>
                                                <div class="pattern pattern3a">
                                                   
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="egg_shadow">

                                </div>


                        And then create the egg_shadow class in your CSS.

                                    .egg_shadow
                                    {
                                        border-radius: 50%;
                                        width:150px;
                                        height:10px;
                                        box-shadow: 0px 20px 5px 5px #444444;
                                        background:none;
                                        margin:-20px auto 0 auto;
                                    }


                        This is what you should see.



                        The final result. Click! It works!



                        And you have what looks like a 3D floating, spinning egg. I bet you're feeling mighty pleased with yourself, aren't you?

                        Have a Happy Easter. Egg-citing times lie ahead!
                        T___T

                        Wednesday, 1 April 2015

                        Web Tutorial: The Faux 3D Easter Egg (Part 1/2)

                        Happy April Fool's Day! Easter approaches. The sweet smell of renewal fills the air. And with it, I bring you more CSS3 goodness. I present... the spinning Easter Egg.

                        What's so special about that?

                        The animations in play today aren't anything you haven't seen before. But everything will be in 3D.

                        Really?!

                        No, not really. You see, back in the day where graphic processors and browsers weren't so advanced, we had to do decent approximations of this kind of thing. That's right, we're going to fake it. It is, after all, April Fool's Day! This is something I used to do in Flash, and now it can be done on CSS3! I'll show you all the different components I put together to create this effect, and the logic behind it.

                        This is more about concept today, so we're not going to obsess over the correct usage of CSS.

                        First, set up the HTML. We're going to draw an egg.
                        <!DOCTYPE html>
                        <html>
                            <head>
                                <title>Easter</title>
                            </head>

                            <body>
                                <div class="egg">

                                </div>
                            </body>
                        </html>

                        Now, let's create the CSS class egg. For reference, check this link. (https://css-tricks.com/examples/ShapesOfCSS/). I'm just copying and pasting snippets of CSS code for the egg shape because I'm such a lazy bastard programming genius.
                        <!DOCTYPE html>
                        <html>
                            <head>
                                <title>Easter</title>

                                <style type="text/css">
                                    .egg
                                    {
                                        background-color:#dddddd;
                                        -webkit-border-radius: 63px 63px 63px 63px / 108px 108px 72px 72px;
                                        border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
                                        width:200px;
                                        height:300px;
                                        margin:0 auto 0 auto;
                                    }
                                </style>

                            </head>

                            <body>
                                <div class="egg">

                                </div>
                            </body>
                        </html>

                        The egg doesn't need a border. But we'll give it one anyway, just to have a visual point of reference. This egg has a grey background specified for your visual reference, and we'll remove it when the time is right.. margin:0 auto 0 auto sets the egg to appear dead center of the screen.

                        This is what it should look like so far.


                        Doesn't look like much!


                        Don't worry. It will, once we start animating! For that, we need a nice Easter Egg pattern. I'm going to just add a nested div inside the first div.
                                <div class="egg">
                                    <div id="eggpattern" class="pattern_wrapper">
                                        <div class="patterns">
                                            <div class="pattern_wrapper">
                                                <div class="pattern pattern1">
                                                   
                                                </div>
                                                <div class="pattern pattern2">
                                                   
                                                </div>
                                                <div class="pattern pattern3">
                                                   
                                                </div>
                                            </div>
                                        </div>
                                    </div>

                                </div>


                        The eggpattern div holds all the blings you're going to subject this poor innocent egg to. This will be important later on. For now, add the following styles to your CSS.
                                    .pattern_wrapper
                                    {
                                        width:800px;
                                        height:300px;
                                        border:1px solid #FF0000;
                                    }

                                    .patterns
                                    {
                                        width:200px;
                                        height:300px;
                                        overflow:hidden;
                                        position:relative;
                                        float:left;

                                        border:1px solid #000000;            
                                    }

                                    .pattern
                                    {
                                        position:absolute;
                                        width:200px;
                                        height:300px;
                                        margin-left:0px;
                                        margin-top:0px;
                                        overflow:hidden;
                                    }

                                    .pattern1
                                    {
                                        z-index:10;
                                        background-color:#FFFF00;
                                    }

                                    .pattern1:before
                                    {
                                        content:"";
                                        display:block;
                                        background-color:#FFAA99;
                                        width:200px;
                                        height:200px;
                                        margin-top:-100px;
                                    }

                                    .pattern2
                                    {
                                        z-index:20;
                                    }

                                    .pattern2:before
                                    {
                                        content:": :";
                                        font-size:120px;
                                        color:#FF5555;
                                        display:block;
                                        position:absolute;
                                        transform:rotate(45deg);
                                        margin-top:80px;
                                        margin-left:20px;
                                    }

                                    .pattern2:after
                                    {
                                        content:":";
                                        font-size:240px;
                                        color:#FF5555;
                                        display:block;
                                        position:absolute;
                                        transform:rotate(5deg);
                                        margin-top:-80px;
                                        margin-left:100px;
                                    }

                                    .pattern3
                                    {
                                        z-index:30;
                                    }

                                    .pattern3:before
                                    {
                                        content:"";
                                        display:block;
                                        width:80px;
                                        height:150px;
                                        -webkit-border-radius: 63px 63px 63px 63px / 108px 108px 72px 72px;
                                        border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
                                        box-shadow: -10px -15px 0 0px #FF8800;
                                        margin-left:20px;
                                        margin-top:20px;
                                        -ms-transform: rotate(-20deg); /* IE 9 */
                                        -webkit-transform: rotate(-20deg); /* Chrome, Safari, Opera */
                                    }

                                    .pattern3:after
                                    {
                                        content:"";
                                        display:block;
                                        width:80px;
                                        height:150px;
                                        -webkit-border-radius: 63px 63px 63px 63px / 108px 108px 72px 72px;
                                        border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
                                        box-shadow: 5px 10px 0 10px #FF8800;
                                        margin-left:50px;
                                        margin-top:-20px;
                                        -ms-transform: rotate(-20deg); /* IE 9 */
                                        -webkit-transform: rotate(-20deg); /* Chrome, Safari, Opera */
                                    }


                        The patterns (plural) class is for the div that holds the eggpattern div, like a sheath. And outlined in black for your visual reference.

                        The pattern_wrapper class is for the eggpattern div that holds all the different pattern blocks. It's also the div that will be animated later. Here I've given it a red border, again, for your visual reference.

                        The pattern (singular) class has its position property set to absolute because these are going to be overlaid on top of each other. The pattern1 class, with z-index set to 10, is behind pattern2 and pattern3.

                        If all this is gibberish to you, don't worry too much about it. It's tangential to what we're really doing here today. Let's see what we just did:


                        See that big block of garish color? That's all the patterns we fit into each pattern block. You'll notice that the eggpattern div is four times as long as the pattern block. That's no coincidence, because we're doing to fill this space up as well.

                        What we just did was the front of the egg. Now we do the back of the egg. Add these nested divs to your collection!
                                <div class="egg">
                                    <div id="eggpattern" class="pattern_wrapper">
                                        <div class="patterns">
                                            <div class="pattern_wrapper">
                                                <div class="pattern pattern1">
                                                   
                                                </div>
                                                <div class="pattern pattern2">
                                                   
                                                </div>
                                                <div class="pattern pattern3">
                                                   
                                                </div>
                                            </div>
                                            <div class="pattern_wrapper">
                                                <div class="pattern pattern1">
                                                   
                                                </div>
                                                <div class="pattern pattern2a">
                                                   
                                                </div>
                                                <div class="pattern pattern3a">
                                                   
                                                </div>
                                            </div>
                                            <div class="pattern_wrapper">
                                                <div class="pattern pattern1">
                                                   
                                                </div>
                                                <div class="pattern pattern2">
                                                   
                                                </div>
                                                <div class="pattern pattern3">
                                                   
                                                </div>
                                            </div>
                                            <div class="pattern_wrapper">
                                                <div class="pattern pattern1">
                                                   
                                                </div>
                                                <div class="pattern pattern2a">
                                                   
                                                </div>
                                                <div class="pattern pattern3a">
                                                   
                                                </div>
                                            </div>

                                        </div>
                                    </div>
                                </div>


                        Make these changes to the CSS
                                    .pattern2,.pattern2a
                                    {
                                        z-index:20;
                                    }

                                    .pattern3,.pattern3a
                                    {
                                        z-index:30;
                                    }


                                    .pattern2a:before
                                    {
                                        content:". .:";
                                        font-size:150px;
                                        color:#FF5555;
                                        display:block;
                                        position:absolute;
                                        transform:rotate(55deg);
                                        margin-top:50px;
                                        margin-left:20px;
                                    }

                                    .pattern2a:after
                                    {
                                        content:":";
                                        font-size:270px;
                                        color:#FF5555;
                                        display:block;
                                        position:absolute;
                                        transform:rotate(-45deg);
                                        margin-top:-80px;
                                        margin-left:50px;
                                    }

                                    .pattern3a:before
                                    {
                                        content:"";
                                        display:block;
                                        width:80px;
                                        height:100px;
                                        -webkit-border-radius: 63px 63px 63px 63px / 108px 108px 72px 72px;
                                        border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
                                        box-shadow: 10px -10px 0 0px #DD00FF;
                                        margin-left:60px;
                                        margin-top:20px;
                                        -ms-transform: rotate(120deg); /* IE 9 */
                                        -webkit-transform: rotate(120deg); /* Chrome, Safari, Opera */
                                    }

                                    .pattern3a:after
                                    {
                                        content:"";
                                        display:block;
                                        width:80px;
                                        height:180px;
                                       -webkit-border-radius: 63px 63px 63px 63px / 108px 108px 72px 72px;
                                        border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
                                        box-shadow: -10px 10px 0 10px #DD00FF;
                                        margin-left:50px;
                                        margin-top:-20px;
                                        -ms-transform: rotate(-80deg); /* IE 9 */
                                        -webkit-transform: rotate(-80deg); /* Chrome, Safari, Opera */
                                    }


                        Now look at the result. Back and front of the egg are lined up one after another. The pattern1 class makes it seamless. Feel free to go wild with the colors and stuff. The specifications I provided were just examples.

                        Now, set the border property of the pattern_wrapper and patterns classes class to 0px, like so.
                                    .pattern_wrapper
                                    {
                                        width:800px;
                                        height:300px;
                                        border:0px solid #FF0000;
                                    }

                                    .patterns
                                    {
                                        width:200px;
                                        height:300px;
                                        overflow:hidden;
                                        position:relative;
                                        float:left;
                                        border:0px solid #000000;           
                                    }


                        Looking better.



                        Now, we're going to specify the animations that make the egg spin left or right. Add these classes to your CSS.
                                    .spin_left
                                    {
                                        -webkit-animation: spinleft 2s linear infinite; /* Chrome, Safari, Opera */
                                        animation: spinleft 2s linear infinite;
                                    }

                                    /* Chrome, Safari, Opera */
                                    @-webkit-keyframes spinleft
                                    {
                                        from {margin-left: 0px;}
                                        to {margin-left: -400px;}
                                    }

                                    /* Standard syntax */
                                    @keyframes spinleft
                                    {
                                        from {margin-left: 0px;}
                                        to {margin-left: -400px;}
                                    }

                                    .spin_right
                                    {
                                        -webkit-animation: spinright 2s linear infinite; /* Chrome, Safari, Opera */
                                        animation: spinright 2s linear infinite;
                                    }

                                    /* Chrome, Safari, Opera */
                                    @-webkit-keyframes spinright
                                    {
                                        from {margin-left: -400px;}
                                        to {margin-left: 0px;}
                                    }

                                    /* Standard syntax */
                                    @keyframes spinright
                                    {
                                        from {margin-left: -400px;}
                                        to {margin-left: 0px;}
                                    }


                        For more on CSS animations, click here. (http://www.w3schools.com/css/css3_animations.asp)

                        What we did was to specify that when "spinning" left, we actually just change the margin-left property. And vice versa for spinning right. The animations are set to infinite, and will graduate over 2 seconds. Adjust this value if you want the egg to spin faster or slower.

                        Alter the class of the eggpattern div like so:
                        <div id="eggpattern" class="pattern_wrapper spin_left">


                        Refresh your browser. Now you'll see the patterns move left, and repeat indefinitely! But we're not done! Add one more line to the CSS class egg.
                                    .egg
                                    {
                                        background-color:#dddddd;
                                        -webkit-border-radius: 63px 63px 63px 63px / 108px 108px 72px 72px;
                                        border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
                                        width:200px;
                                        height:300px;
                                        margin:0 auto 0 auto;
                                        overflow:hidden;
                                    }


                        Presto! Because the part of the pattern that is outside of the egg is now set to hidden, it looks like the egg is spinning! Much better, eh? The Easter Bunny would be proud.


                        Since we already made an animation specification for "spinning" right, let's not waste it. Create two buttons in your HTML, just after the egg div, like so:

                                </div>
                                <input type="button" value="<" onclick="spin_left();">
                                <input type="button" value=">" onclick="spin_right();">

                        </html>


                        And add this JavaScript to your HTML head.
                                <script>
                                    function spin_left()
                                    {
                                        var egg=document.getElementById("eggpattern");
                                        egg.className="pattern_wrapper spin_left";
                                    }

                                    function spin_right()
                                    {
                                        var egg=document.getElementById("eggpattern");
                                        egg.className="pattern_wrapper spin_right";
                                    }
                                </script>


                        Now by default, the egg spins left. But you can change the direction anytime by clicking on the buttons. The JavaScript functions basically change the CSS class of the eggpattern div to animate in the direction specified by the CSS classes spin_right and spin_left.


                        So far so good! We have a nicely decorated (OK, that one's subjective, but whatevs, dude) Easter egg that spins left and right at the click of a button. But damn, it does look kind of flat, doesn't it? We're going to fix that, no worry.

                        Next

                        Applying more CSS tricks to bring the 3D effect to life! Stay tuned!