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