How to create Pinterest-like script – step 1

How to create Pinterest-like script – step 1

8 519
How to create Pinterest-like script - step 1

How to create Pinterest-like script – step 1

Do you like Pinterest? I am sure that yes, and, it is likely that you would like to create a similar photo website. I made up my mind to write a series of tutorials about development of similar script. For a start – let’s decide what features will be included into the script. I think, that besides of good design and friendly interface, we have to add next things: ajaxy popup to display full-size photos, possibility to write comments, like functionality, upload form, a way to sort photos (depends on its size) automatically and maybe something else. In our first lesson I prepared html markup with styles of our script. Also, in order to sort photos (align them) – I am going to use ‘masonry’ jQuery plugin.

Now you can check our demonstration and download the sources:

Live Demo

Step 1. HTML

As always, our first step is html markup. In the beginning – we have to include all the necessary styles and scripts in the head section:

<!DOCTYPE html>
<html lang="en" >
    <head>
        <meta charset="utf-8" />
        <meta name="author" content="Script Tutorials" />
        <title>How to create Pinterest-like script - step 1 | Script Tutorials</title>

        <!-- add styles -->
        <link href="css/main.css" rel="stylesheet" type="text/css" />

        <!-- add scripts -->
        <script src="js/jquery.min.js"></script>
        <script src="js/jquery.masonry.min.js"></script>
        <script src="js/script.js"></script>
    </head>

Now we can mark the main page structure. Schematically it looks like this:

<body>

    <!-- header panel -->
    <div class="header_panel">

        <!-- logo -->
        <a href="#" class="logo"></a>

        <!-- search form -->
        <form action="" method="get" class="search">
            .....
        </form>

        <!-- navigation menu -->
        <ul class="nav">
            .....
        </ul>

    </div>

    <!-- upload form -->
    <a href="#x" class="overlay" id="add_form"></a>
    <div class="popup">
        .....
    </div>

    <!-- main container with pin elements -->
    <div class="main_container">

        .....

    </div>
</body>

There are three main elements: header, upload form and main container (for pin elements). The header consists of a logo, search form and navigation menu. Look at its html markup:

    <!-- header panel -->
    <div class="header_panel">

        <!-- logo -->
        <a href="#" class="logo"></a>

        <!-- search form -->
        <form action="" method="get" class="search">
            <input autocomplete="off" name="q" size="27" placeholder="Search" type="text" />
            <input name="search" type="submit" />
        </form>

        <!-- navigation menu -->
        <ul class="nav">
            <li><a href="#add_form" id="login_pop">Add +</a></li>
            <li>
                <a href="#">About<span></span></a>
                <ul>
                    <li><a href="#">Help</a></li>
                    <li><a href="#">Pin It Button</a></li>
                    <li><a href="#" target="_blank">For Businesses</a></li>
                    <li class="div"><a href="#">Careers</a></li>
                    <li><a href="#">Team</a></li>
                    <li><a href="#">Blog</a></li>
                    <li class="div"><a href="#">Terms of Service</a></li>
                    <li><a href="#">Privacy Policy</a></li>
                    <li><a href="#">Copyright</a></li>
                    <li><a href="#">Trademark</a></li>
                </ul>
            </li>
            <li>
                <a href="#">Profile<span></span></a>
                <ul>
                    <li><a href="#">Invite Friends</a></li>
                    <li><a href="#">Find Friends</a></li>
                    <li class="div"><a href="#">Boards</a></li>
                    <li><a href="#">Pins</a></li>
                    <li><a href="#">Likes</a></li>
                    <li class="div"><a href="#">Settings</a></li>
                    <li><a href="#">Logout</a></li>
                </ul>
            </li>
            <li>
                <a href="http://www.script-tutorials.com/pinterest-like-script-step-1/">Back to tutorial<span></span></a>
            </li>
        </ul>

    </div>

As you see – everything is easy here. The second main element is upload form, I’m going to use the power of CSS3 to make CSS-based popup:

    <!-- upload form -->
    <a href="#x" class="overlay" id="add_form"></a>
    <div class="popup">
        <div class="header">
            <a class="close" href="#close">x</a>
            <h2>Upload a Pin</h2>
        </div>
        <form>
            <input type="file" name="image_file" id="image_file" onchange="" />
        </form>
    </div>

You can find related CSS styles in the second step of our tutorial. Finally, it is important to review html markup of our photo units (or – pins):

    <div class="pin">
        <div class="holder">
            <div class="actions" pin_id="1">
                <a href="#" class="button">Repin</a>
                <a href="#" class="button">Like</a>
                <a href="#" class="button disabled comment_tr">Comment</a>
            </div>
            <a class="image ajax" href="#" title="Photo number 1" pin_id="1">
                <img alt="Photo number 1" src="photos/pic1.jpg">
            </a>
        </div>
        <p class="desc">Photo number 1 description</p>
        <p class="info">
            <span>1 likes</span>
            <span>1 repins</span>
        </p>
        <form class="comment" method="post" action="">
            <input type="hidden" name="id" value="1" />
            <textarea placeholder="Add a comment..." maxlength="1000"></textarea>
            <button type="button" class="button">Comment</button>
        </form>
    </div>

Every pin consists of a holder element (action buttons and thumbnail image), description, info row, and comments box.

Step 2. CSS

Now, I would like to give you CSS styles to stylize today’s result. First section is base styles:

css/main.css

/* base styles */
* {
    margin: 0;
    padding: 0;
}
html {
    background-color: #F7F5F5;
    font-size: 10px;
    font-family: arial,sans-serif;
}
a {
    color: #221919;
    text-decoration: none;
}

Then, we can stylize our header area:

/* header elements */
.header_panel {
    background-color: #FAF7F7;
    box-shadow: 0 1px #FFFFFF inset, 0 1px 3px rgba(34, 25, 25, 0.4);
    height: 44px;
    left: 0;
    padding: 0 7px;
    position: relative;
    right: 0;
    top: 0;
    z-index: 1;
}
.logo {
    background: url("../images/logo.png") repeat scroll 0 0 transparent;
    display: block;
    height: 30px;
    left: 50%;
    margin-left: -50px;
    position: absolute;
    top: 10px;
    width: 100px;
}
.search {
    float: left;
    margin: 8px 0 0;
}
.search input[type=text] {
    background-color: #FAF7F7;
    border-color: #C2C0C0 #CCCACA #D1CFCF;
    border-image: none;
    border-style: solid;
    border-width: 1px;
    box-shadow: 0 1px #FFFFFF, 0 1px rgba(34, 25, 25, 0.05) inset;
    color: #8C7E7E;
    float: left;
    font-size: 13px;
    height: 16px;
    padding: 5px;
    width: 180px;

    -webkit-transition: all .5s;
    -moz-transition: all .5s;
    -ms-transition: all .5s;
    -o-transition: all .5s;
    transition: all .5s;
}
.search input[type=text]:focus {
    background-color: #FFFFFF;
    box-shadow: 0 1px #FFFFFF, 0 1px rgba(34, 25, 25, 0.1) inset;
    width: 250px;
}
.search input[type=submit] {
    background: url("../images/search.gif") no-repeat scroll center center transparent;
    border-color: #C2C0C0 #CCCACA #D1CFCF;
    border-style: solid;
    border-width: 1px;
    box-shadow: 0 1px rgba(255, 255, 255, 0.9), 0 0 2px rgba(255, 255, 255, 0.75) inset;
    color: transparent;
    content: "";
    cursor: pointer;
    float: left;
    height: 28px;
    margin-left: -1px;
    min-height: 17px;
    padding: 7px 7px 1px;
    width: 30px;
}

/* navigation styles */
.nav {
    float: right;
    position: relative;
}
.nav li {
    display: inline;
    font-size: 13px;
    position: relative;
}
.nav > li > a {
    color: #524D4D;
    cursor: pointer;
    display: inline-block;
    font-weight: bold;
    height: 29px;
    padding: 15px 27px 0 14px;
    position: relative;
    text-decoration: none;
    text-shadow: 0 1px #FFFFFF;
}
.nav > li > a span {
    background: url("../images/down.png") no-repeat scroll center top transparent;
    height: 6px;
    position: absolute;
    right: 14px;
    top: 20px;
    width: 7px;
}
.nav > li:hover > a {
    background-color: #E1DFDF;
    color: #221919;
    text-decoration: none;
    text-shadow: 0 1px rgba(255, 255, 255, 0.3);
}
.nav > li:active > a {
    background-color: #CB2027;
    color: #FFFFFF;
    text-shadow: 0 -1px rgba(34, 25, 25, 0.3);
}
.nav li ul {
    background-color: #FFFFFF;
    border-top: 1px solid #CCCACA;
    box-shadow: 0 2px 4px rgba(34, 25, 25, 0.5);
    display: none;
    left: 0;
    position: absolute;
    top: 28px;
    width: 140px;
    z-index: 1;
}
.nav li:hover ul {
    display: block;
}
.nav li ul a {
    color: #524D4D;
    display: block;
    font-weight: normal;
    padding: 7px 10px;
    text-align: left;
}
.nav li ul a:hover {
    background-color: #E1DFDF;
    color: #221919;
    text-decoration: none;
}
.nav li ul a:active {
    background-color: #CB2027;
    color: #FFFFFF;
}
.nav .div a {
    border-top: 1px solid #E1DFDF;
}
.nav > li:last-child ul {
    left: auto;
    right: 0;
}

As you see – this is usual UL-LI based dropdown menu here. Well, now, the most interesting styles for today (CSS3-based upload form):

/* popup upload form styles */
.overlay {
    background-color: #FFFFFF;
    bottom: 0;
    display: none;
    left: 0;
    opacity: 0.8;
    position: fixed;
    right: 0;
    top: 0;
    z-index: 9;
}
.overlay:target {
    display: block;
}
.popup {
    background: none repeat scroll 0 0 #FCF9F9;
    border: 1px solid #F7F5F5;
    box-shadow: 0 2px 5px rgba(34, 25, 25, 0.5);
    display: inline-block;
    left: 50%;
    padding: 30px 30px 20px;
    position: fixed;
    top: 40%;
    visibility: hidden;
    width: 550px;
    z-index: 10;

    -webkit-transform: translate(-50%, -50%);
    -moz-transform: translate(-50%, -50%);
    -ms-transform: translate(-50%, -50%);
    -o-transform: translate(-50%, -50%);
    transform: translate(-50%, -50%);

    -webkit-transition: all 0.3s ease-in-out 0s;
    -moz-transition: all 0.3s ease-in-out 0s;
    -ms-transition: all 0.3s ease-in-out 0s;
    -o-transition: all 0.3s ease-in-out 0s;
    transition: all 0.3s ease-in-out 0s;
}
.overlay:target+.popup {
    top: 50%;
    opacity: 1 ;
    visibility: visible;
}
.popup .header {
    background-color: #F2F0F0;
    border-bottom: 1px solid #CCCACA;
    margin: -30px -31px 20px;
    padding: 18px 31px 8px;
    position: relative;
}
.popup .header h2 {
    color: #8C7E7E;
    font-size: 21px;
    line-height: 1em;
    margin: 0 37px 0 0;
    text-shadow: 0 1px #FFFFFF;
}
.popup .close {
    background: -webkit-linear-gradient(#FFFCFC, #F0EDED) repeat scroll 0 0 transparent;
    background: -moz-linear-gradient(#FFFCFC, #F0EDED) repeat scroll 0 0 transparent;
    background: linear-gradient(#FFFCFC, #F0EDED) repeat scroll 0 0 transparent;
    border-left: 1px solid rgba(34, 25, 25, 0.15);
    bottom: 0;
    box-shadow: 0 1px 2px #FFFFFF inset;
    color: #BBBBBB;
    display: block;
    font-size: 50px;
    line-height: 42px;
    position: absolute;
    right: 0;
    text-align: center;
    text-decoration: none;
    top: 0;
    width: 57px;
    z-index: 1;
}
.popup form input[type="file"] {
    font-size: 18px;
}

This is a similar method as we used in our previous lesson (CSS3 Modal Popups). Well, now I have to give you final styles for the main container (for pin elements) and for single pin:

/* photo pins - general styles */
.main_container {
    margin: 0 auto;
    padding: 10px 10px 0;
    position: relative;
}
.button {
    background-color: #F0EDED;
    background-image: -webkit-linear-gradient(center top , #FDFAFB, #F9F7F7 50%, #F6F3F4 50%, #F0EDED);
    background-image: -moz-linear-gradient(center top , #FDFAFB, #F9F7F7 50%, #F6F3F4 50%, #F0EDED);
    background-image: linear-gradient(center top , #FDFAFB, #F9F7F7 50%, #F6F3F4 50%, #F0EDED);
    border: 1px solid #BBBBBB;
    border-radius: 6px 6px 6px 6px;
    color: #524D4D;
    cursor: pointer;
    display: inline-block;
    float: right;
    font-weight: bold;
    line-height: 1em;
    margin: 0;
    padding: 5px 9px;
    text-align: center;
    text-shadow: 0 1px rgba(255, 255, 255, 0.9);

    -webkit-transition: all 0.2s ease-in-out 0s;
    -moz-transition: all 0.2s ease-in-out 0s;
    -ms-transition: all 0.2s ease-in-out 0s;
    -o-transition: all 0.2s ease-in-out 0s;
    transition: all 0.2s ease-in-out 0s;
}
.button:hover {
    box-shadow: 0 1px rgba(255, 255, 255, 0.35) inset, 0 0 0 1px rgba(140, 126, 126, 0.5), 0 1px 2px rgba(35, 24, 24, 0.75);
}
.button.disabled, .button[disabled] {
    background: none repeat scroll 0 0 #F2F0F0;
    border-color: #D1CDCD;
    color: #D1CDCD;
    cursor: default;
    text-shadow: 0 -1px rgba(34, 25, 25, 0.01);
}

/* single pin styles */
.pin {
    background-color: #FFFFFF;
    box-shadow: 0 1px 3px rgba(34, 25, 25, 0.4);
    float: left;
    font-size: 11px;
    margin: 0 15px 15px 0;
    padding: 15px 15px 0;
    position: relative;
    width: 192px;
}
.pin .holder {
    position: relative;
}
.pin .actions {
    left: -8px;
    position: absolute;
    top: -8px;
    z-index: 3;
}
.pin .actions a {
    clear: none;
    display: none;
    float: left;
    margin: 0 5px 0 0;
}
.pin:hover .actions a {
    display: block;
}
.pin .image {
    background-color: #F2F0F0;
    cursor: -webkit-zoom-in;
    cursor: -moz-zoom-in;
    text-decoration: none;
}
.pin .image img {
    max-width: 192px;
    min-height: 75px;
    opacity: 1;
}
.pin .desc {
    margin: 10px 0 5px;
    overflow: hidden;
    word-wrap: break-word;
}
.pin .info {
    color: #8C7E7E;
    line-height: 1.35em;
    margin: 0 0 0.8em;
    overflow: hidden;
}
.pin .info span {
    float: left;
    margin-right: 10px;
}
.comment {
    background-color: #F2F0F0;
    border-top: 1px solid #D9D4D4;
    box-shadow: 0 1px #FCFAFA inset;
    margin: 0 -15px;
    overflow: hidden;
    padding: 10px 15px;
}
.comment textarea {
    background-color: #FCF9F9;
    border: 1px solid #CCCCCC;
    color: #8C7E7E;
    font-size: 11px;
    height: 21px;
    line-height: 1em;
    margin-bottom: 6px;
    padding: 4px 3px 3px;
    resize: none;
    width: 185px;
}
.comment textarea:focus {
    background-color: #FFFFFF;
    box-shadow: 0 1px 1px rgba(34, 29, 29, 0.1) inset;
}

Step 3. JS

We have just got over our big step with styles, and now I would like to give you a small piece of javascript:

js/script.js

$(document).ready(function(){

    // masonry initialization
    $('.main_container').masonry({
        // options
        itemSelector : '.pin',
        isAnimated: true,
        isFitWidth: true
    });

    // onclick event handler (for comments)
    $('.comment_tr').click(function () {
        $(this).toggleClass('disabled');
        $(this).parent().parent().parent().find('form').slideToggle(250, function () {
            $('.main_container').masonry();
        });
    }); 

});

As you see – it is very easy to use masonry jQuery plugin, in the same time it does a great job – it aligns elements (pins) over the page.


Live Demo

Conclusion

We have just finished our first lesson where we started making Pinterest-like script. I hope that you like it. It would be kind of you to share our materials with your friends. Good luck and welcome back!

SIMILAR ARTICLES

Sliding single-level menu

0 45

8 COMMENTS

  1. Great like always Andrew,

    Realy smart your strick to us “X” letter for the close pop up with a font size :D !
    Just long but very passionated tutorial.

    Thanks.

  2. The script isn’t working on Chrome when you load the page?
    Only if you click on an action, then script runs the right way!

    Is there a solution to fix this?

  3. Great Job..! and elegant…
    I’m trying to use it on a module of a DotNetNuke site, and what happens is that seems to fight with something:
    symptoms are no scrolling page, conflict with the footer.
    What should i have to do to make it work?
    I putted css and js in the head section of the module, the markup in the module…

    Thank you

    • Hi Pino,
      In order to understand what causes these problems, I recommend that you use firebug to inspect all possible JS (and other) errors.

Leave a Reply