How To

How to turn a Photoshop PSD design into a Bootstrap web page

8 Sep , 2017  

PSD to Bootstrap How-To(Pssst! I made this article into a video course over at Skillshare. Click here to check it out and get a month free at Skillshare!)

Hello and welcome to today’s article, where we’ll learn how to turn a PSD design of a website into a web page with Bootstrap 3.

(New to HTML and CSS? This article assumes you’re a little familiar with them. You can get a quick start with HTML here, and with CSS here!)

Bootstrap is of course one of the most popular user interface libraries in use today.

Say what you will about its size and pervasive “look”, it is hands down the most commonly-used technology for building web pages right now. The ‘BuiltWith’ site currently puts Bootstrap usage at between 10 and 20 percent of the million top sites on the Internet.

Famously ‘mobile-first‘, Bootstrap has always been the easy path to implementing a web page that looks good and behaves well across nearly all web browsers.

Now version 4 of Bootstrap is about to be released and it shows no sign of slowing down.

Today, I’ll go over how we can use Bootstrap to turn the following design into a working web page:

Bootstrap mockup admin screen

(This is a cut-down and heavily modified version of a design for an admin screen for managing website popups. Of course in a real design, our branding would be filled in, and the buttons and links would actually do something!)

Since version 4 of Bootstrap is still in beta, I’ll stick with version 3 as we build out the web page.

If you’re not coding along with the article, you can always download the source files used in this article here:

But first, we should talk about what Bootstrap actually is.

Introduction to Bootstrap

At it’s core, boot strap is a collection of CSS and JavaScript (and HTML if you want to use one of the provided templates) that was originally released by Twitter (so Bootstrap is often referred to a ‘Twitter Bootstrap’).

The main job of Bootstrap’s CSS is to implement a grid system that displays well across displays of all sizes. This is one of Bootstrap’s biggest features: we can use it to display columns in a website – and not have to worry too much about it working in other browsers or devices.

So Bootstrap just saved us a bunch of time right there. Catering to the display whims of every single browser in every size is a huge job, and Bootstap takes care of that for us.

Bootstrap Concepts

These are the basic Bootstrap concepts we’ll deal with today. I’ll talk about each one more as we put it to use:

  • Navigation
  • Containers
  • Rows
  • Columns

Bootstrap provides predefined ‘components’ to implement each of these (note, these aren’t components in the sense that React, Angular or Vue would define them).

The components are collections of styling rules and JavaScript that implement user interface elements like buttons, menus and so on in a reliable and predictable way.

The only thing to remember is that the Bootstrap components assume they’re being used together – rows, for instance, won’t work well outside of containers. You’ll see what I mean as we get into it.

How to Customize Bootstrap

Another implication here is that it can be tough to modify Bootstrap’s styles by hand. For example, if we modify the background of a menu, will sub-menus have the same color? How about highlight colors when we hover over a menu option?

Luckily, Bootstrap has provided us with a way of handling this. If you head on over to the Bootstrap customization page you’ll see that everything – and I mean every tiny little thing – can be modified.

We can use the navigation menu on the right hand side to find the things we want to change. I’m only interested in changing the navigation bar colors, so I clicked Navbar in the righthand menu:

Bootstrap Navbar Customization Options

Then I changed the following:

  • navbar-border-radius – I set it to 0 (zero) to avoid rounded corners
  • navbar-default-color – white (#fff)
  • navbar-default-bg – I took this value from the mockup (#00b8b0)
  • navbar-default-link-color – white again (#fff)
  • navbar-default-link-hover-color – the mockup doesn’t show this, but I chose a darker version of our blue-green navbar color, #044.

Once we’re done with the customization, we can click ‘Compile and Download’ at the very bottom of the customization page. That’ll download a version of your modified Bootstrap as .zip file. Double-click to extract it and then you’ll be able to use it in your projects like any other CSS and JavaScript. You’ll see how I use it in the next section.

Let’s get started on our Bootstrap web page.

Implementing Navigation with Bootstrap

So let’s take a look at our design’s navigation:

Admin-Screen-Navigation

And when we click the user menu:

Admin-Screen-Navigation-Dropdown

Let’s see how we do this in Bootstrap.

First, here’s our skeleton HTML file, with required CSS and JavaScript included:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Admin</title>
    
    <!-- Font for our icons -->
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">

    <!-- Custom Bootstrap CSS -->
    <link rel="stylesheet" href="css/bootstrap.min.css">

    <!-- Our CSS -->
    <link rel="stylesheet" href="mockup.css">

    <!-- jQuery, required by Bootstrap -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

    <!-- Bootstrap JavaScript, required for menu interactions -->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
  </head>
  <body>
  </body>
</html>

So here’s our first go at a navigation bar (generally, that’s the area across the top of a web page that has links to other parts of the site).

This code goes between the body tags of our skeleton file.

    <!-- Navigation -->
    <nav class="navbar navbar-default poptext">
      <div class="container-fluid">

        <!-- The actual navigation menu -->
        <div>
          <!-- Navigation options on the left (site related) -->
          <div class="col-md-offset-4">
            <ul class="nav navbar-nav">
              <li><a href="#Pricing">Pricing</a></li>
              <li><a href="#About">About</a></li>
              <li><a href="#FAQ">FAQ</a></li>
              <li><a href="#Blog">Blog</a></li>
              <li><a href="#Contact">Contact</a></li>
            </ul> 
          </div>

          <!-- Navigation options on the right (user related) -->
          <ul class="nav navbar-nav navbar-right">
            <li><a href="#Upgrade">Upgrade</a></li>
            <li><a href="#Alerts"><i class="material-icons">notifications</i></a></li>
            <li><a href="#Help"><i class="material-icons">help</i></a></li>
            <li><a href="#UserMenu"><i class="material-icons user-icon">person</i></a></li>
          </ul> <!-- navbar-right -->

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

Which displays like this:

Admin screen with Bootstrap

So how does this work?

We start off with the HTML5 nav tag, which you can think of as a div with a special name for improved accessibility (i.e. help screen-reading software interpret a page).

We give it classes ‘navbar navbar-default’, which are Bootstrap styles for creating a navigation bar.

Then we have a div with class container-fluid.

Bootstrap Containers

Bootstrap has two kinds of container styles, container, which is 970 pixels wide, and container-fluid which has a width equal to 100% of your browser window. This is more useful for supporting both desktop and mobile devices.

Bootstrap’s column styles won’t work properly outside of either a container or container-fluid element. I’ll talk more about columns in a later section, but notice that the very next div has class col-md-offset-4. This looks weird, but it means move this element across 4 columns. Like I said, I’ll talk more about columns in a later section.

Finally, we get to an actual menu. Bootstrap implements menus with ul and li elements, ie unordered lists.

Menus with <ul> and <li>

We indicate that our ul is used as navigation by giving it classes nav and navbar-nav. After we’ve done that, whatever we put in li tags inside the ul will appear as navigation menu items. I’m using anchor tags with # href values that don’t go anywhere, since we’re only implementing one page of a mockup.

Because the mockup calls for two menus, one for the site links, and one for links orientated around user actions, there’s a second ul tag implementing the second menu. The only difference here is that the second ul tag has the navbar-right tag, meaning that it should be positioned to the right of the page (the default is the left). This creates some separation between our menus.

That’s great, but we have one problem. If the page is very narrow the navigation looks like this:

Stacked admin screen navigation

It’s hardly the worst thing that could happen, but if someone looks at our page on their phone, the menu’s going to take up a lot of room.

Creating a collapsible Bootstrap menu

So we’ll use Bootstrap’s styles and JavaScript to make a little collapsible menu for us. Now the navigation section looks like this:

    <!-- Navigation -->
    <nav class="navbar navbar-default poptext">
      <div class="container-fluid">

        <!-- Header and button for mobile view -->
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#mainNav">
            <!-- Make a hamburger: -->
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
        </div>

        <!-- The actual navigation menu -->
        <div class="collapse navbar-collapse" id="mainNav">
          <!-- Navigation options on the left (site related) -->
          <div class="col-md-offset-4">
            <ul class="nav navbar-nav">
              <li><a href="#Pricing">Pricing</a></li>
              <li><a href="#About">About</a></li>
              <li><a href="#FAQ">FAQ</a></li>
              <li><a href="#Blog">Blog</a></li>
              <li><a href="#Contact">Contact</a></li>
            </ul> 
          </div>

          <!-- Navigation options on the right (user related) -->
          <ul class="nav navbar-nav navbar-right">
            <li><a href="#Upgrade">Upgrade</a></li>
            <li><a href="#Alerts"><i class="material-icons">notifications</i></a></li>
            <li><a href="#Help"><i class="material-icons">help</i></a></li>
            <li><a href="#UserMenu"><i class="material-icons user-icon">person</i></a></li>
          </ul> <!-- navbar-right -->

        </div> <!-- #mainNav -->
      </div>
    </nav>

And now on small screens our menu looks like this:

Bootstrap navigation hamburger

Until it’s expanded, when it looks like this:

Bootstrap navigation hamburger expanded

There were two major changes to add this to our navigation. The first was adding this section to the top of the navigation section (just inside the top container-fluid div tag):

<!-- Header and button for mobile view -->
<div class="navbar-header">
  <button 
    type="button" 
    class="navbar-toggle collapsed" 
    data-toggle="collapse" 
    data-target="#mainNav"
   >
    <!-- Make a hamburger: -->
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
  </button>
</div>

(I’ve changed the formatting a little for clarity).

This is code to create a button with three horizontal lines (those three spans), that when clicked, expands our hidden menu. The one part of this you’ll need to modify for your own code is data-target=”#mainNav”

#mainNav is the id of of the div containing your main navigation. Wrapping our previous navigation code in a div with id set to #mainNav  and class=”collapse navbar-collapse” is the second change:

<!-- The actual navigation menu -->
<div class="collapse navbar-collapse" id="mainNav">
  <!-- Navigation options on the left (site related) -->

  <!-- [same navigation ul and li tags as before] -->

</div> <!-- #mainNav -->

Now, there’s one more change we need to make for our navigation:

When our user icon is clicked, we need a drop-down menu to display a series of action the user can take that are related to their account. Here it is again:

Admin-Screen-Navigation-Dropdown

To do that, we’ll give our User menu a new class, dropdown, and then put a submenu inside it. The code for our second menu now looks like this:

<ul class="nav navbar-nav navbar-right">
  <li><a href="#Upgrade">Upgrade</a></li>
  <li><a href="#Alerts"><i class="material-icons">notifications</i></a></li>
  <li><a href="#Help"><i class="material-icons">help</i></a></li>

  <li class="dropdown">
    <a
      href="#UserMenu"
      class="dropdown-toggle"
      data-toggle="dropdown"
      role="button"
      aria-haspopup="true"
      aria-expanded="false"
    >
      <i class="material-icons user-icon">person</i>
    </a>
    <ul class="dropdown-menu">
      <li><a href="#UserName"><strong>User Name</strong></a></li>
      <li><a href="#PlanName"><em>Plan Name</em></a></li>
      <li role="separator" class="divider"></li>
      <li><a href="#UpdateProfile">Update Profile</a></li>
      <li><a href="#Preferences">Preferences</a></li>
      <li><a href="#Billing">Billing</a></li>
      <li role="separator" class="divider"></li>
      <li><a href="#Logout">Logout</a></li>
    </ul>
  </li> <!-- dropdown -->

</ul> <!-- navbar-right -->

Our anchor tag also has the class dropdown-toggle and an attribute called data-toggle set to dropdown. The other attributes are there to improve accessibility.

Now, our menu looks like this on desktop:

Admin nav dropdown Bootstrap

And on a small screen:

Admin nav mobile dropdown

That’s it for our navigation menu. Now let’s take a look at the rest of the page.

Implementing the ‘brand’

Bootstrap has a standard position for the brand section of the website, which is in the far left of the navigation bar at the top.

The design we’re using doesn’t use that – it has the brand occupying the entire left-third of the page with some cheesy copy to enjoy while they scratch their heads over conversion rates.

This is the code to implement it:

<!-- Main content -->
<div class="container-fluid">
  <!-- Site identity --> 
  <section class="col-md-4">
    <div class="row">
      <img class="center-block id-img" src="img/identity.png">
    </div>
    <div class="row row-spacer">
      <div class="col-md-11 col-sm-11">
        <h3>This Is Important</h3>
        <p>This is our copy to make sure you feel good about paying for our service.</p>
        <p>We're here to make sure you succeed.</p>
        <p>Any questions? Just Ask.</p>
      </div>
    </div>
  </section>
</div>

And this is what it looks like now in the browser:

Admin with navigation and brand

I know the text is looking very squashy, but we’ll fix that in a moment.

First we need to talk about rows and columns in Bootstrap.

Bootstrap Rows and Columns

So Bootstrap has a bunch of styles that implement rows and columns in a web page.

This is a great way to create pages with event alignment and good horizontal and vertical rhythm.

Here’s how it works:

First, we need a container. Like I mentioned earlier in the article, Bootstrap gives us two container options, the 970-pixel wide container, and the full-width container-fluid.

We need a container, because columns are defined as a percentage of whatever’s containing them. The Bootstrap grid has 12 columns:

Bootstrap column sizes

So if we ask for column of width 1, we know it’s width will be 8.33% of whatever’s containing it. A column of width 9 would occupy 75% of its container.

You can see how if we have a container, several rows, and columns of the same size in each row, our content will line up nicely.

But there’s more to it than that.

Bootstrap columns for different screen sizes

Bootstrap’s column names follow a convention:

col-<screen size>-<column-size>

column-size refers to the width of the column, as described above.

screen-size is one of the following:

  • xs – extra small screens, like phones
  • sm – small screens, like large phones and small tablets
  • md – medium screens: large tablets and small laptops
  • lg – big laptops, desktops and everything bigger

So we could define a column like this: col-md-4, or col-xs-12.

What’s the point of the different screen sizes?

Bootstrap provides those because an 8-column table might look great on a large screen, but pretty horrible on a small phone.

So we should interpret those screen sizes ‘be a column on screens this size and larger, but be a full-width div otherwise.’

So a div with class col-md-3 will be a div with 25% width on medium and large screens, but a 100%-width div otherwise.

xs columns, since they’re the smallest, will be a column on all screens.

Make sense? No?

Don’t worry if it doesn’t – nothing explains like a demonstration, so let’s move on to implementing the rest of the web page.

Inputs, buttons and columns with Bootstrap

Now it’s time to work on the business part of our page. In reality, this could be any type of data – products, orders, invoices – anything. These are records we create, update, delete, read/report on (otherwise known as CRUD).

Here’s our little table of data from the mockup:

Admin screen Bootstrap data table

Let’s start with the top row:

<!-- Data and data actions --> 
<section class="col-md-8 ">
  <!-- Header and actions -->
  <div class="row">
    <div class="col-md-4">
      <h1>Forms</h1>
    </div>
    <div role="search" class="col-md-3 col-sm-3">
      <input type="text" class="form-control" id="txtSearch"/>
      <i class="material-icons form-control-feedback tool-hint">search</i>
    </div>
    <div class="col-md-3 col-sm-3">
      <button id="add-new-btn" class="btn-flat poptext" type="button">Add New Form</button>
    </div>
  </div>
</section>

(This code comes immediately after the <section> implementing the site’s brand)

So here we have a section with class set to col-md-8. The previous section was assigned col-md-4, so between them they occupy Bootstrap’s 12 columns.

After that we have a div with class=”row”, since we’ll have several rows inside our col-md-8.

Inside that row we have three columns:

  • The title, Forms, which has col-md-4
  • Then a search box, with col-md-3 and col-sm-3 (because we want it to maintain column layout until it reaches extra-small screen size)
  • And an ‘Add New Form’ button, which is also col-md-3 and col-sm-3.

Remember: the col* classes provide 12 columns inside their container. Because these elements appear inside a col-md-8 element, we have 12 tiny columns to play with.

And here we can see our column styles in action. At full width, we have our three columns:

admin-screen-data-header-full

And once we squash it up a bit, the Form <h1> element gets stacked as a full-length div, while the search input and the Add New Form button remain as columns:

admin-screen-data-header-small

Finally, once we make it really tiny, all three become full-width columns (note: we should add a style to put some distance between the search box and the button!)

admin-screen-data-extra-small

So that the first row taken care of.

Now we need to add the headers for our data table.

We can do this in pretty much the same way as the form header, with a series of columns defining the data table headings:

<!-- Data headings -->
<div class="row row-spacer">
  <div class="col-md-4 col-xs-2">Name</div>
  <div class="col-xs-2 text-right">Impressions</div>
  <div class="col-xs-2 text-right">Responses</div>
  <div class="col-xs-2 text-right">Conversion</div>
</div>
<div class="row">
  <div class="col-md-11 col-sm-11 lo-border"></div>
</div>

This time the columns will always be maintained, no matter what size device we use since the columns are all xs columns.

Note that the row-spacer and lo-border styles aren’t part of Bootstrap. I’ve added them to provide some padding to the top of a row, and a border on the bottom of a column, respectively.

Finally, it’s time to get some data into the table. This isn’t something we’d add by hand usually – it’d be sent from the server. Nonetheless we’ve got some here to complete our example:

<!-- Tediosly hand-written data -->
<div>
  <div class="row row-spacer data-row">
    <div class="col-md-4 col-xs-2">LP Form 1</div>
    <div class="col-xs-2 text-right">2452</div>
    <div class="col-xs-2 text-right">899</div>
    <div class="col-xs-2 text-right">36.7%</div>
    <div class="col-xs-2 tool-grp">
      <a href="#report"><i class="material-icons admin-tool">trending_up</i></a>
      <a href="#report"><i class="material-icons admin-tool">edit</i></a>
      <a href="#report"><i class="material-icons admin-tool">delete</i></a>
      <a href="#report"><i class="material-icons tool-hint">more_horiz</i></a>
    </div>
  </div>
  <div class="row row-spacer data-row">
    <div class="col-md-4 col-xs-2">FAQ Feedback</div>
    <div class="col-xs-2 text-right">1023</div>
    <div class="col-xs-2 text-right">112</div>
    <div class="col-xs-2 text-right">10.9%</div>
    <div class="col-xs-2 tool-grp">
      <a href="#report"><i class="material-icons admin-tool">trending_up</i></a>
      <a href="#report"><i class="material-icons admin-tool">edit</i></a>
      <a href="#report"><i class="material-icons admin-tool">delete</i></a>
      <a href="#report"><i class="material-icons tool-hint">more_horiz</i></a>
    </div>
  </div>
  <div class="row row-spacer data-row">
    <div class="col-md-4 col-xs-2">Satisfied YN</div>
    <div class="col-xs-2 text-right">20</div>
    <div class="col-xs-2 text-right">1</div>
    <div class="col-xs-2 text-right">5.0%</div>
    <div class="col-xs-2 tool-grp">
      <a href="#report"><i class="material-icons admin-tool">trending_up</i></a>
      <a href="#report"><i class="material-icons admin-tool">edit</i></a>
      <a href="#report"><i class="material-icons admin-tool">delete</i></a>
      <a href="#report"><i class="material-icons tool-hint">more_horiz</i></a>
    </div>
  </div>
</div>

Notice that the data columns have the same column values as their corresponding headers, to make sure they line up.

The one exception is the last column, with an extra class of tool-grp and a bunch of Google material-icons inside it. This for displaying the tools that provide reporting, editing and delete options for each row. They’re not related to Bootstrap, but they are implemented with CSS. Once again, download the examples to see how it works.

Here’s what our completed data table looks like:

Bootstrap admin-screen-data-complete

The last thing we have to add is the footer.

Implementing a Footer with Bootstrap

The footer is pretty straight forward, but it does have a couple small quirks. To get started, here’s our footer code:

<!-- Footer -->
<footer>
  <div class="container-fluid">
    <div class="row flexer row-spacer">
      <div class="center-block">
        <a href="#Pricing">Pricing</a>
        <a href="#About">About</a>
        <a href="#FAQ">FAQ</a>
        <a href="#Blog">Blog</a>
        <a href="#Contact">Contact</a>
      </div>
    </div>
    <div class="row flexer">
      <div class="center-block">
        <span class="copyright"></span>
        <span class="brand-text">The Brand </span>&nbsp;2017
      </div>
    </div>
  </div>
</footer>

The quirks I mentioned are that I’ve added a class flexer, which isn’t a Bootstrap class, but is there to help center the footer content.

What you also can’t see, is that I’ve added dispay:flex to the document body, and styled the body so that it’ll occupy 100% of the screen’s height.

I’ve done this to make sure the footer is always at the bottom of the screen, but isn’t one of those annoying sticky menus that follows you around on the page.

Once again, check the downloadable examples to see how this works.

Here’s how our final page looks:

Bootstrap admin page example

But that’s not all

Even thought I’ve skipped over a lot of detail in this post, I’ve covered everything you need to know to build a non-trivial Bootstrap page.

Of course, there’s plenty more to learn about Bootstrap, not to mention the imminent arrival of Bootstrap 4.

At any rate, I hope you’re convinced to learn more about Bootstrap and to consider using it to build your next project – it’s what will get you the biggest results with the least amount of work.

Don’t forget to download the completed code and examples used in this article, and I look forward to hearing about how you plan to use Bootstrap in the future.

By


4 Responses

  1. Ash says:

    Hi Luke,

    Thanks so much for a great article on breaking down Bootstrap elements.

    I have a question that seems to be a recurring problem with BS where I,d like to change the breakpoint when a site shows the burger menu responsively. I know I can customise it before downloading BS but I have attempted it through CSS that works sometimes and not so great other times.

    I have seen many articles online regarding this issue and the fixes I have found are a mix of good, bad and complicated 😊

    I wanted to ask, have you found a reliable way to change the breakpoints through CSS rather than downloading a customised BS again.

    Many thanks for your help.
    Ash

    • Luke says:

      Hey Ash,

      Thanks so much for your comment, but the short answer to your question is “no” 🙂 Sorry.

      For me, the cost of everything that Bootstrap gives us is just doing things the ‘Bootstrap way’ sometimes. It can be more work forcing Bootstrap to do what you want than just writing your own from scratch, especially in pure CSS.

      And sadly, Bootstrap 4 has taken away the online customisation interface, so to customise it we need to download the SCSS and rebuild Bootstrap. Which *isn’t that bad*, but a lot less convenient.

      Any particular reason you can’t work with a customised Bootstrap?

  2. Fen says:

    I have question, does the website need CSS? Because I use Angular, and just html doesn’t work out this way.

    • Luke says:

      Hi Fen, thanks so much for stopping by!

      When we use Bootstrap, we’re normally including the Bootstrap CSS file in the page. That’s where all the predefined styles for columns etc come from.

      If you need your own CSS on top of that (which is normal), that would need to be included in your page separately.

      Does that answer your question? Let me know!

      Luke

Leave a Reply

Your email address will not be published. Required fields are marked *