Basic Fluid Grid and Responsive Design


To give my brain a bit of a rest from the Zend learning and in preparation for some future projects, I decided it was time for me to look at responsive design techniques and using CSS grids for doing site design.  Lordy was that stuff confusing!  Took me an hour or two of reading a lot of articles, and trying to separate stuff that's 5 years old from more current practices, to finally get the idea.  The way I figured out to explain it was this:

  • a "grid" is essentially a "row" or horizontal zone of the page
  • each grid can be contain 1 or more columns, or vertical zones, and columns can be just content or contain more grids
  • a grid is a container of multiple "boxes" that flow beside one another
  • CSS is used to determine the width of the columns in a grid while grid heights are generally determined by the tallest content within the column
  • Grid column widths are generally based on fractional/percentile measures, i.e. 3rds, 5ths, etc.
  • Grid layouts will require having divs, potentially a lot of divs, in the HTML code

In all my reading, there was a lot of back and forth on whether it's better to use a CSS framework or module (or whatever other name they call themselves) or build your own grid.  For learning, I decided I'd rather just use a premade one to get an understanding of the whole concept.  Since we've already started using Pure CSS (which just released v0.50 BTW), and they have a grid system built in, I went with that.  Pure's CSS grids offer a grid system based on 5ths and on 24ths.

When I was explaining this to my partner and later to my sweetie, they both questioned the jump from 5ths to 24ths.  It was only as I was talking about it with my sweetie though that the light bulb finally came on and I could articulate why it was good.  5ths is a useful grid measurement, particular for main layout, but going from 1/5 – 2/5 is a pretty big jump in widths.  24ths allow for more finite control of the widths and a greater range of widths, while also still allowing for big basic widths like 3rds and 4ths.

So with that understanding, I began the slightly painful process of redesigning one of our existing sites to using the fluid grid design.  For this purpose, we'll redo the movie shelves design. As a reminder, here is what it looks like now:

Which is using DIVs for the layout and an attempt at making them nice and flexible.

<!DOCTYPE html>
<html lang="en">
<head>
	<title>An Eclectic World: Movie Shelves</title>
	<meta charset="UTF-8">
	<meta name="description" content="An online browsable directory of all of the movies in my collection">
	<meta name="author" content="Summer S. Wilson">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta http-equiv="content-language" content="en-US">
	<link href="css/movieshelves.css" media="screen" rel="stylesheet" type="text/css">
	<link href="//ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/themes/flick/jquery-ui.css" media="screen" rel="stylesheet" type="text/css">
	<link href="http://yui.yahooapis.com/pure/0.4.2/pure-nr-min.css" media="screen" rel="stylesheet" type="text/css">
	<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
	<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js"></script>
	<script type="text/javascript" src="/js/core.js"></script>
</head>
<body>
<div id="page" class="clearfix">
	<div id="siteHeader">
		<div id="siteNameBox"> <a href="/" title=""><img src="/img/header_movieshelves.gif" width="461" height="100" alt="Take me to the Movie Shelves front page" /></a> </div>
		<div id="siteMenu">
			<div id="loginLink"> <a href="/authentication">Log In</a> </div>
			<div id="topMenu">Can I get a menu?</div>
		</div>
	</div>
	<div id="middleSection" class="clearfix">
		<div id="leftSideBar">
			<ul class="navigation">
				<li class="active"> <a href="/">Home</a> </li>
				<li> <a href="#">Browse</a>
					<ul>
						<li> <a href="/publicSeries">By Series</a> </li>
						<li> <a href="/publicGenres">By Genre</a> </li>
						<li> <a href="/publicStudios">By Studio</a> </li>
						<li> <a href="/movies/">By Year</a> </li>
						<li> <a href="/publicFormats">By Format</a> </li>
						<li> <a href="/movies/">View All</a> </li>
					</ul>
				</li>
				<li> <a href="/movies/">Search</a> </li>
			</ul>
		</div>
		<div id="pageContent">
			<h1 class="pageTitle"></h1>
			<p> I do love me watching anime, movies, and the like whenever I want, so I have quite a few DVDs.  I specially love snagging them on sale.  This online database helps me remember what I have (especially when out shopping) and acts as an inventory for insurance purposes. Of course, it also lets me share my collection with others, like you!</p>
			<h3>Newest Acquisitions</h3>
			<h3>Random Highlights</h3>
		</div>
	</div>
</div>
</body>
</html>

And the basic bits of the CSS that lay all that out:

/* 
	Default in all browsers is 16px font size; so font is set to be 100% of 16px in the body, then all ems are based on this line.  To do a new em, take pixels desired and divide by 16.
	So for a 10px width 10/16 = 0.625 em.
*/

/* Tag restyling */
body {
	font: 100%/1.125em Arial, Helvetica, sans-serif;
	background: #300;
	-moz-background-size: cover;
	background-size: cover;
	margin: 0em;
	padding: 0em;
}
h1, h2, h3, h4 {
	font-weight: bold;
	text-align: center;
}
h1 {
	margin-top: 0.3125em;
	margin-bottom: 0.3125em;
	color: #330066;
	font-size: 2.5em /* 2.500em/16px */;
}
h2 {
	margin-top: 0.3125em;
	margin-bottom: 0.3125em;
	color: #333366;
	font-size: 2.19em /* 35px/16px */;
}
h3 {
	margin-top: 0.3125em;
	margin-bottom: 0.3125em;
	color: #336699;
	font-size: 1.875em /* 30px/16px */;
}
h4 {
	margin-top: 0.3125em;
	margin-bottom: 0.3125em;
	color: #6666CC;
	font-size: 1.625em /* 25px/16px */;
}
img { border: 0; }
a { color: #00F; }
a:hover { color: #127290; }
p, table, ul, dl, ol { font-size: 0.9375em; /* 14px/16px */ }
p {
	padding: 0 1.25em;
	margin-bottom: 0.9375em;
	margin-top: 0em;
}
table {
	padding: 0.125em;
	padding: 0em;
	border-spacing: 0em;
	margin: 0.3125em auto 0.625em;
}
th, tr, td {
	vertical-align: top;
	padding: 0.125em;
}
th {
	white-space: nowrap;
}

/* Core stuff */
#page {
	width: 98%;
	min-width: 81.25em; /* 1300px */
	margin: 0.625em auto;
	clear: both;
	padding: 0em;
}

/* Header Stuff */
#siteHeader {
	height: 6.25em;
	border: 0.0625em solid #900;
	width: 100%;
	min-width: 81.25em; /* 1300px */
	clear: both;
	margin: 0em;
	padding: 0em;
	background: #000 url(/img/header_movieshelves_background.jpg);
}
#siteNameBox {
	float: left;
	width: 31.25em;
	height: 6.25em;
	margin: 0em;
	padding: 0em;
}
#loginLink {
	float: right;
	text-align: center;
	margin-top: .5em;
	margin-right: .5em;
	padding: .25em;
	
}
#loginLink a {
	color: #FFF;
	font-weight: bold;
}

/* Content/center Section */
#middleSection {
	border: 0.0625em solid #900;
	width: 100%;
	min-width: 81.25em; /* 1300px */
	clear: both;
	margin: 0em;
	padding: 0em;
	background: #FFF;
	min-height: 37.5em;
	border: 0.0625em solid #900;
}
#pageContent {
	float: right;
	min-width: 39.0625em;
	width: 84%;
	margin: 0em 0em 0.625em;
	background: #FFF;
	min-height: 37.5em;
	padding: 0em;
}
#leftSideBar {
	float: left;
	min-width: 12.5em;
	width: 15%;
	color: #330000;
	clear: left;
	min-height: 37.5em;
	background: #FFC;
	border-right: 0.0625em solid #900;
	margin: 0em;
	padding: 0em;
}

Since this particular design was already using divs, for me, most of the change was in cleaning up the div structure a little and then completely redoing the CSS.  Of course, the head links also changed a bit.  So here is the new HTML code:

<!DOCTYPE html>
<html lang="en">
<head>
	<title>An Eclectic World: Movie Shelves</title>
	<meta charset="UTF-8">
	<meta name="description" content="An online browsable directory of all of the movies in my collection">
	<meta name="author" content="Summer S. Wilson">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta http-equiv="content-language" content="en-US">
	<link href="css/movieshelves.css" media="screen" rel="stylesheet" type="text/css">
	<link href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/themes/flick/jquery-ui.css" media="screen" rel="stylesheet" type="text/css">
	<link href="http://yui.yahooapis.com/pure/0.5.0/pure-min.css" media="screen" rel="stylesheet" type="text/css"><!--update to the 5.0 -->
	
	<!--[if lte IE 8]>
		<link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.5.0/grids-responsive-old-ie-min.css">
	<![endif]-->
	<!--[if gt IE 8]><!-->
		<link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.5.0/grids-responsive-min.css">
	<!--<![endif]-->
	
	<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
	<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js"></script>
	<script type="text/javascript" src="/js/core.js"></script>
</head>
<body>
	<div id="layout">
		<div id="pageHeader" class="pure-g">
			<div class="pure-u-2-5"><a href="/" title=""><img src="/img/header_movieshelves.gif" width="461" height="100" alt="Take me to the Movie Shelves front page" /></a></div>
			<div class="pure-u-3-5">
				<div id="loginLink"> <a href="/authentication">Log In</a> </div>
				<div id="topMenu">Can I get a menu?</div>
			</div>
		</div>

		<div id="pageBody" class="pure-g">
			<div id="sideMenu" class="pure-u-1-8">
				<ul class="navigation">
					<li class="active"> <a href="/">Home</a> </li>
					<li> <a href="#">Browse</a>
						<ul>
							<li> <a href="/publicSeries">By Series</a> </li>
							<li> <a href="/publicGenres">By Genre</a> </li>
							<li> <a href="/publicStudios">By Studio</a> </li>
							<li> <a href="/movies/">By Year</a> </li>
							<li> <a href="/publicFormats">By Format</a> </li>
							<li> <a href="/movies/">View All</a> </li>
						</ul>
					</li>
					<li> <a href="/movies/">Search</a> </li>
				</ul>
			</div>
			<div id="pageContent" class="pure-u-7-8">
				<h1 class="pageTitle"></h1>
				<p> I do love me watching anime, movies, and the like whenever I want, so I have quite a few DVDs.  I specially love snagging them on sale.  This online database helps me remember what I have (especially when out shopping) and acts as an inventory for insurance purposes. Of course, it also lets me share my collection with others, like you!</p>
				<h3>Newest Acquisitions</h3>
				<h3>Random Highlights</h3>
			</div>
		</div>
	</div>
</body>
</html>

And the new CSS:

/* 
	Default in all browsers is 16px font size; so font is set to be 100% of 16px in the body, then all ems are based on this line.  To do a new em, take pixels desired and divide by 16.
	So for a 10px width 10/16 = 0.625 em.
*/

/* Tag restyling */
body {
	font: 16px/1.125em Arial, Helvetica, sans-serif;
	background: #300;
	margin: 0;
	padding: 0;
}
html, button, input, select, textarea, .pure-g [class *= "pure-u"] {
    font-family: Arial, Helvetica, sans-serif;
    font-size: 0.975em;
}

h1, h2, h3, h4 {
	font-weight: bold;
	text-align: center;
}
h1 {
	margin-top: 0.3125em;
	margin-bottom: 0.3125em;
	color: #330066;
	font-size: 2.5em /* 2.500em/16px */;
}
h2 {
	margin-top: 0.3125em;
	margin-bottom: 0.3125em;
	color: #333366;
	font-size: 2.19em /* 35px/16px */;
}
h3 {
	margin-top: 0.3125em;
	margin-bottom: 0.3125em;
	color: #336699;
	font-size: 1.875em /* 30px/16px */;
}
h4 {
	margin-top: 0.3125em;
	margin-bottom: 0.3125em;
	color: #6666CC;
	font-size: 1.625em /* 25px/16px */;
}
img { border: 0; }
a { color: #00F; }
a:hover { color: #127290; }
html, p, table, ul, dl, ol { font-size: 0.95em; /* 14px/16px */ }
p {
	padding: 0 1.25em;
	margin-bottom: 0.9375em;
	margin-top: 0em;
}
table {
	padding: 0.125em;
	padding: 0em;
	border-spacing: 0em;
	margin: 0.3125em auto 0.625em;
}
th, tr, td {
	vertical-align: top;
	padding: 0.125em;
}
th {
	white-space: nowrap;
}

/* Layout Divs */
#layout {
	clear: both;
	background: #FFF;
	padding: 0.000em !important;
	width: 95%;
	margin: 0.625em auto;
}
#pageHeader {
	height: 6.25em;
	padding: 0.125em 0.625em 0.125em 1.250em;
	border: 0.0625em solid #900;
	background: #000 url(/img/header_movieshelves_background.jpg);
}
#pageHeader #loginLink {
	float: right;
	text-align: center;
	margin-top: .5em;
	margin-right: .5em;
	padding: .25em;
	
}
#pageHeader #loginLink a {
	color: #FFF;
	font-weight: bold;
}
#pageBody {
	border: 0.0625em solid #900;
	background: #FFF;
}
#sideMenu {
	font-size: .8em;
	background: #FFC;
	color: #330000;
	border-right: 0.0625em solid #900;
	box-sizing: border-box;
	-moz-box-sizing: border-box; /* Older Firefoxs */
}
#sideMenu a:link, #sideMenu a:visited {
	font-weight: bold;
	width: 100%;
}
#sideMenu li {
	margin-bottom: 0.625em;
}
#sideMenu ul ul {
	margin-top: 0.625em;
	padding-left: 1.5em;
}
#pageContent {
	padding: 0em 1.25em 1.25em;
	margin: 0em;
	box-sizing: border-box;
	-moz-box-sizing: border-box; /* Older Firefoxs */
}

Final result?

Pretty much looks the same, except it isn't maxing the height out (which is fine as it doesn't have all the content yet) and it fixed the weird issue I was having with a floating white line under the main content area. It also flexs now, so when you reduce the browser window size, it continues to maintain the general look and feel, while my old one stopped reducing after you hit a certain minimum width and then you had to scroll. The CSS is quite a bit smaller, of course, as all the column widths and positioning stuff is now handled by Pure.

Now the title of this post also mentions responsive design.  This is basically redoing the design bits, as needed, for various screen sizes, hence it being "responsive". Since I am using pure, adding the basic responsive stuff is pretty easy.  For example, if I reduce my browser to say, 800×600, then my menu gets pretty messed up.

By adding a second class to the sideMenu and pageContent divs, I was able to implement a new grid declaration if the screen was below 768 pixels in width.

...
<div id="sideMenu" class="pure-u-1-8 pure-u-md-5-24">
	<ul class="navigation">
		<li class="active"> <a href="/">Home</a> </li>
		<li> <a href="#">Browse</a>
			<ul>
				<li> <a href="/publicSeries">By Series</a> </li>
				<li> <a href="/publicGenres">By Genre</a> </li>
				<li> <a href="/publicStudios">By Studio</a> </li>
				<li> <a href="/movies/">By Year</a> </li>
				<li> <a href="/publicFormats">By Format</a> </li>
				<li> <a href="/movies/">View All</a> </li>
			</ul>
		</li>
		<li> <a href="/movies/">Search</a> </li>
	</ul>
</div>
<div id="pageContent" class="pure-u-7-8 pure-u-md-19-24">
	<h1 class="pageTitle"></h1>
	<p> I do love me watching anime, movies, and the like whenever I want, so I have quite a few DVDs.  I specially love snagging them on sale.  This online database helps me remember what I have (especially when out shopping) and acts as an inventory for insurance purposes. Of course, it also lets me share my collection with others, like you!</p>
	<h3>Newest Acquisitions</h3>
	<h3>Random Highlights</h3>
</div>
...

So now the menu is still usable.

Much better!  But…one thing I know I'm bad about thinking about is what does it look like on a bigger screen?  So what happens if we simulate displaying this site on the TV screens we use in our conference rooms and make our browser crazy wide (in this case 1920×1080).

Now the menu is just too big!  So we add another set of classes to change the size for large displays, i.e. those wider than 1280px. In this case I added pure-u-xl-1-12 to the menu and pure-u-xl-11-12 to our content.

Again, much better.  Of course, this just touches the surface of responsive design.  For example, in a proper responsive design, my logo would also resize based on those changes in browser window, and maybe move around the content some.  For example, on a phone or small tablet in portrait mode, the menu still ends up getting squished, but since this was mostly me dipping my toes in, I'm satisfied with the initial results and having at least some knowledge now of the whole thing. 🙂

Update: Today I realized that my understanding of grids was slightly off, so I've updated this post accordingly and fixed the error in my new code sample (basically remove the pure-g class from the layout div)