Skip to main content
Ben Nadel at the Angular NYC Meetup (Jan. 2019) with: Igor Minar
Ben Nadel at the Angular NYC Meetup (Jan. 2019) with: Igor Minar

Separating Layout HTML And CSS From Content HTML And CSS Is Good

By
Published in

I'm a slow learner. That's part of why I write so much - it takes ages for ideas to sink into my Neanderthal brain. Such is the case with something like the separation of concerns in HTML and CSS. 11-years ago, I looked at Nicole Sullivan's Object-Oriented CSS (OOCSS); then, 9-years ago, I looked at Jon Snook's Scalable and Module Architecture for CSS (SMACSS). Both of these engineers spoke highly of separating layout from content. And yet, a decade later, my brain is still trying to ingest these concepts. And so, this post is nothing more than a note to self that creating a separation of concerns between layout and content is always a good thing!

Run this demo in my JavaScript Demos project on GitHub.

View this code in my JavaScript Demos project on GitHub.

I think part of why it has taken so long for this concept to gel in my head is that, historically, when I think "layout", what my brain is actually thinking is "page layout". Headers, columns, asides, footers - things of that nature. It's taken me years to truly embrace the idea that layout isn't just about pages - everything has layout.

  • Nav bars have layout.
  • Button bars have layout.
  • Drop-down menus have layout.
  • Content grids have layout.
  • Forms have layout.

It's layouts all the way down!

Sometimes the distinction between the layout and the content is fuzzy; and, it's easy to combine the two responsibilities into a single concept - which is the trap that I often fall into. But, as I'm discovering over and over again, keeping the two concepts - and their responsibilities - separate, creates for more flexible and maintainable user interface (UI) code.

As a simple example, let's look at a horizontal list of Avatars. In the past, I might collapse this down into a "single thing" in which the Avatars are baked-into the list, so to speak. But, these days, more and more, I'm trying to see this as two separate constructs:

  • A horizontal layout for Avatars.
  • An Avatar component.

The former takes care of the orientation, spacing, and alignment; the latter takes care of the Avatar. To see this in action, I've put together a hard-coded HTML and CSS demo:

ASIDE: Part of this approach finally "clicked" for me when I was listening to a recent Full Stack Radio episode with Mark Dalgleish in which he stated that content should never have any margin associated with it - that margin should always be handled by a higher-level layout component.

<!doctype html>
<html lang="en">
<head>
	<meta charset="utf-8" />
	<meta name="viewport" content="width=device-width, initial-scale=1" />

	<title>
		Separating Layout HTML And CSS From Content HTML And CSS
	</title>
</head>
<body>

	<h1>
		Separating Layout HTML And CSS From Content HTML And CSS
	</h1>

	<!--
		In the following example, we have a "Layout" - THE AVATAR LIST - which contains
		the content - THE AVATAR. You could easily have combined these two concepts into
		a single "construct"; however, the more I deal with approaches like this, more it
		seems to pay-off in keeping the two concepts separate (the layout and the
		content).
	-->
	<style type="text/css">

		/* THE LAYOUT: Avatar List. */
		.avatar-list {
			display: flex ;
			list-style-type: none ;
			margin: 0px 0px 0px 0px ;
			padding: 0px 0px 0px 0px ;
		}

		.avatar-list__item {
			margin: 0px 7px 0px 0px ;
			padding: 0px 0px 0px 0px ;
		}

		.avatar-list__item:last-child {
			margin-right: 0px ;
		}


		/* THE CONTENT: Avatar. */
		.avatar {
			align-items: center ;
			background-color: #596376 ;
			border-radius: 45px ;
			color: #ffffff ;
			display: flex ;
			justify-content: center ;
			font-family: monospace, sans-serif ;
			font-size: 13px ;
			height: 45px ;
			letter-spacing: 2px ;
			line-height: 13px ;
			width: 45px ;
		}

	</style>

	<ul class="avatar-list">
		<li class="avatar-list__item">

			<div title="Karyn Dwyer" class="avatar">
				KD
			</div>

		</li>
		<li class="avatar-list__item">

			<div title="Christina Cox" class="avatar">
				CC
			</div>

		</li>
		<li class="avatar-list__item">

			<div title="Tony Nappo" class="avatar">
				TN
			</div>

		</li>
		<li class="avatar-list__item">

			<div title="Wendy Crewson" class="avatar">
				WC
			</div>

		</li>
		<li class="avatar-list__item">

			<div title="Peter Outerbridge" class="avatar">
				PO
			</div>

		</li>
	</ul>

</body>
</html>

As you can see, the ul and li elements work together to manage the layout of the avatars. And then, the div element manages the rendering of the avatar itself. Notice that the orientation and margins around the avatars are the responsibility of the layout. And, if we run this HTML and CSS demo, we get the following output:

The avatar list rendered in the browser.

This may make the HTML a bit more verbose; and, give each local DOM (Document Object Model) tree-branch one more node; but, it makes it easier to understand how to maintain the user interface over time. If you want to change something about the layout, you do it in the .avatar-list* CSS classes. And, if you want to change something about the avatar, you do it in the .avatar CSS class.

It's taken me a decade to get to this point. And, I'm hoping that by writing this down in a glorified note to self, it may actually stick this time. It's layouts all the way down - and separating the HTML and CSS of the various layouts from the HTML and CSS of the content is always a worthwhile approach, regardless of any additional verbosity or DOM depth.

The Mistake I Would Have Made in the Past

Before embracing the importance of this particular separation of concerns, I would have likely built this user interface by allowing each li element to implement both the layout and the avatar. I may have rationalized this approach by using two separate CSS classes on the li:

<li
	title="Christina Cox"
	class="avatar-list__item avatar">
	CC
</li>

... but, that only served to obfuscate the underlying mistake.

This Has Nothing To Do With Packaging And Consumption

Separating layout concerns from content concerns has nothing to do with how functionality is ultimately packaged and consumed within an application. For example, it's entirely possible that the concept of an "Avatar List" is encapsulated within a single, reusable Angular component; and, that no engineer will ever have to know that there is an "avatar list" and an "avatar". But, even if that were the case, separating the layout responsibilities from the content responsibilities within this single component would still have advantages.

And, should the desire ever arise to factor-out and re-use the "Avatar" in several places, having it separated-out within the original component immediately makes that a trivial task.

Want to use code from this post? Check out the license.

Reader Comments

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel