Notes from a Newbie Experiment 03: Layout

Notes from a Newbie document the creation and deployment of yardbirdfanclub.org with Perl Catalyst on shared hosting. They are intended for a Perl Catalyst Newbie who would like to study the creation and deployment of a Perl Catalyst application.

In these notes I continue to explore what it might take to create a blog application, focusing on how to use CSS to layout a page.

Create and Use CSS Styles

I wondered if I could get blog output to look anything like blogs.perl.org, and the answer is yes.

You will need to create:

  • root/static/css/main.css
  • root/header.tt
  • root/footer.tt

Use them in:

  • root/index.tt
  • root/blog.tt

main.css

I think there is nothing really fancy here, it is basic CSS as far as I know - but I don't know much.

I created this stylesheet a step at a time, slowly and painstakingly creating and applying styles to get the output I was looking for.

root/static/css/main.css:

#wrapper {
  width: 960px;
  margin-top: 0px;
  margin-right: auto;
  margin-left: auto;
}

#header {
  height: 100px;
  margin-left: 20px;
  background: #004060;
  background-image: url(../images/bird/bird.gif);
  background-position: left bottom;
  background-repeat: no-repeat; 
}

#header_title {
  margin-left: 70px;
  padding-top: 22px;
  color: #87ceeb;
  font-size: 2.2em;
  font-weight: bold;
}

#header_subtitle {
  margin-left: 70px;
  margin-top: 2px;
  color: #87ceeb;
  font-size: 0.9em;
}

#footer {
  padding-top: 0.4em;
  padding-bottom: 1.5em;
  background: #004060;
  color: #FFFFFF;
  font-size: 0.9em;
}

body {
  font-family: arial;
  margin-top: 0px;
  background: #004060;
}

#main_menu {
  border-left: 1px solid #FFFFFF;
  border-right: 1px solid #FFFFFF;
  border-bottom: 1px solid #FFFFFF;
  border-bottom-left-radius: 0.3em; 
  border-bottom-right-radius: 0.3em; 
  background: #003050;
  font-size: 0.9em;

  color: #FFFFFF;
}

#main_menu ul {
  padding-top: 0.275em;
  padding-bottom: 0.18em;
  margin: auto; /* center horizontally */
  list-style: none; 

  /* Menu background/border has no vertical height without
  this, I don't know why it works. */
  overflow: hidden;
}

#main_menu a {
  color: #87ceeb;
  text-decoration: none; 
}

#main_menu a:hover {
  color: #FFFFFF;
  text-decoration: underline; 
}

#main_menu_left li {
  padding-right: 5em;
  margin-left: -1.5em;
  float: left;
}

#main_menu_right li {
  margin-right: 1em;
  float: right;
}

#content_wrapper {
  border: 1px solid #000000;
  border-radius: 0.3em; 
  background: #FFFFFF;

  /* Expand content area when sidebar is vertically longer than content. */
  overflow: auto; 
}

#content_with_sidebar {
  margin-right: 225px;
  margin-left: 10px;
  margin-top: 0px;
  margin-bottom: 20px;
}

#content_without_sidebar {
  margin-right: 10px;
  margin-left: 10px;
  margin-top: 0px;
  margin-bottom: 20px;
}

#sidebar_wrapper {
  float: right;
}

.sidebar_item {
  width: 200px;
  margin-right: 10px;
  margin-top: 13px;
  margin-bottom: 10px;
  border: 1px solid #000000;
  border-radius: 0.3em; 
}

.sidebar_item_content {
  padding-left: 12px;
  padding-right: 12px;
}

header.tt

My conception of yardbirdfanclub.org is to have the same menu at the top of each page, and to similarly have a simple footer at the bottom of each page.

root/header.tt:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>[% title %]</title>
  <link rel="stylesheet" type="text/css" media="screen" href="[% c.uri_for('/static/css/main.css') %]" />
</head>
<body>
  <div id="wrapper">
    <div id="main_menu">
      <ul>
        <div id="main_menu_left">
          <li><a href="[% c.uri_for_action('/index') %]">Home</a></li>
          <li>Blog</li>
          <li>Events</li>
          <li>Links</li>
          <li>News</li>
          <li>Photos</li>
          <li>Video</li>
          <li>Members</li>
        </div>
        <div id="main_menu_right">
          <li>Login | Not a member?</li> 
        </div>
      </ul>
    </div> <!-- main_menu -->

footer.tt

root/footer.tt:

    <div id="footer">
      <p>Feedback Welcome | Webmaster<span style="float:right">The YARDBIRD Fan Club</span></p>
    </div>
  </div> <!-- wrapper -->
</body>
</html>

index.tt

This is the template we are using with our index action:

root/index.tt:

<h3>Take A Ride...</h3>
[% FOREACH blog_entry IN blog_entries %]
  <p><a href="[% c.uri_for_action('/blog', blog_entry.id) %]">[% blog_entry.title %]</a></p>
  <p>[% blog_entry.content %]</p>
[% END %]

Edit it to use our styles:

root/index.tt:

[% INCLUDE header.tt title = 'The YARDBIRD Fan Club'; %]
<div id="header">
  <div id="header_title">The YARDBIRD Fan Club</div>
  <div id="header_subtitle">Celebrating the NFL Rookie Sensation!</div>
</div>

<div id="content_wrapper">
  <div id="content_without_sidebar">
    <h3>Take A Ride...</h3>
    [% FOREACH blog_entry IN blog_entries %]
      <p><a href="[% c.uri_for_action('/blog', blog_entry.id) %]">[% blog_entry.title %]</a></p>
      <p>[% blog_entry.content %]</p>
    [% END %]
  </div>
</div>

[% INCLUDE footer.tt %]

blog.tt

This is the template we are using with our blog action:

root/blog.tt:

<h3>On The Wild Side.</h3>
<p>blog_entry.id: [% blog_entry.id %]</p>
<p>blog_entry.title: [% blog_entry.title %]</p>
<p>blog_entry.content: [% blog_entry.content %]</p>
<p>blog_entry.userid.name: [% blog_entry.userid.name %]</p>
<p>--------------------------------------</p>
[% FOREACH user_entry IN all_user_entries %]
  <p>[% user_entry.title %]</p>
  <p>[% user_entry.content %]</p>
[% END %]

Edit it to use our styles:

root/blog.tt:

[% INCLUDE header.tt title = 'The YARDBIRD Fan Club'; %]
<div id="header">
  <div id="header_title">The YARDBIRD Fan Club</div>
  <div id="header_subtitle">Celebrating the NFL Rookie Sensation!</div>
</div>

<div id="content_wrapper">
  <div id="sidebar_wrapper">

    <div class="sidebar_item">
      <div class="sidebar_item_content">
        [% FOREACH user_entry IN all_user_entries %]
          <p>[% user_entry.title %]</p>
          <p>[% user_entry.content %]</p>
        [% END %]
      </div> <!-- sidebar_item_content -->
    </div> <!-- sidebar_item -->
  </div> <!-- sidebar_wrapper -->

  <div id="content_with_sidebar">
    <h3>On The Wild Side.</h3>
    <p>blog_entry.id: [% blog_entry.id %]</p>
    <p>blog_entry.title: [% blog_entry.title %]</p>
    <p>blog_entry.content: [% blog_entry.content %]</p>
    <p>blog_entry.userid.name: [% blog_entry.userid.name %]</p>
  </div> <!-- content_with_sidebar -->
</div> <!-- content_wrapper -->

[% INCLUDE footer.tt %]

Review

Taking what I learned in Catalyst and DBIx::Class docs, I explored how I might create a blog. Being a rather dim-witted Newbie, I wanted to experiment without concern for broader issues one would otherwise take into consideration, such as configuration, controller name/path, file locations, ...

These experiments led to the discovery of details I need to implement a simple blog:

  • Database
  • Foreign Keys
    • Access other table data
    • Cascade edit/delete
  • Result Class
    • Row method creation and object use
  • ResultSet Class
    • ResultSet method creation and object use
  • CSS Layout

What Next?

Now that we have done the most difficult things, we'll start over and create the Yardbird application from scratch, starting first with authentication/authorization.

It will get much easier now.

Leave a comment

About j0e

user-pic I have experience and am skilled at maintaining old school Perl 5 and am seeking opportunities to use modern Perl.