A Frontend Development Process

An excerpt from Learn JavaScript the Hard Way teaching a starter creative process for using HTML and CSS.

Reposted from Learn JS the Hard Way By Zed A. Shaw

A Frontend Development Process

This is an excerpt from Learn JS the Hard Way's CSS module. If you like what you read then register to get the entire module, plus modules on HTML, and JavaScript for beginners.

You know the basics of HTML, and you know a similar amount of CSS, but how do you turn that into a working web page? Simply knowing all the HTML tags and all the CSS attributes isn't enough. You need something called a "process" that will guide you in your first web pages. A process is something artists use to remove a lot of the cognitive overload involved in creating complex visual experiences. By following a process as a beginner you can focus on applying what you know without also trying to figure out what to do next.

I like to call these "personal processes" or "creative processes" so that they aren't confused with the team oriented processes you find in software. The team processes are things like Scrum, Agile Development, XP, and other techniques for managing a large group of people. A personal process is one you can follow on your own to get your idea out of your head, which is also why I could call them a "creative process." Let's just call these "Personal Creative Processes" or PCP for short.

Everyone Has a Process, Except for You

An established artist, writer, musician, or programmer will most likely have a process that works for them. This process is something they've built up--either intentionally or accidentally--over years of working. For some people the process is very important and they're also very conscious of it. Other people just simply "go for it" and think they don't have a process, but if you were to film them working for a few days you'd easily find they do have one.

You, however, probably don't have one because you're a beginner and not that experienced. Or, maybe you've been programming for a while, but you're not as experienced in frontend development. I'd say you're still a beginner, so you don't really know what your process is yet.

I've created a process that works well for beginners for that very reason. If you follow it you'll increase your probability that what you make mostly works. As you work this process and practice it you'll eventually develop your own way of working, or just be fine with this one, but eventually the process should disappear. The goal isn't to chain you to something like a set of rules, but to set you up with a guide that helps you internalize the steps needed to create something. Once those steps are internalized you'll be able to think about more important things rather than, "Should I put images on now or later?"

If you already have experience in creating websites then exercise 9 and 10 may only be mildly interesting to you. Try it out, but if it's killing your flow then don't worry about it. This is entirely for beginners who really don't know what to do next.

What Makes a Good Process?

One way to understand Personal Creative Processes (PCP) is to see how other creative people do their thing. I can't speak for other people, but I am a painter, writer, and programmer so I can talk about my own processes. Even though I'm describing my personal process, I've found that there's four general features to all creative processes people use:

  1. Rough, loose, general, and "chunky" starts. It's easier to change or restart when you keep things loose. Big general structure in the beginning is also easier to manipulate because it's simpler.
  2. Avoiding details for as long as possible. Details are important but also very difficult to change. They're also difficult to get right if the underlying structure isn't solid enough to hold the details. Details also distract from the more important elements like composition, structure, plot, or logic.
  3. Tolerant of mistakes by making them easy to identify and fix in each stage. Mistakes are inevitable, so a good process makes them easy to correct and detect as you work. No point in making mistakes easy to fix if you can't even find them.
  4. Everything "works" as you progress, even if everything is not "exact." A rough sketch can be close enough that people will recognize the subject, even if it's not totally accurate. This means it "works", even if it's not photo realistic.

If a process can give you these four things then it will help, but for a beginner there's a few more things to consider:

  1. It has to be simple enough that you can remember it and follow it.
  2. It has to use a structure that focuses on one or two concepts at each stage.
  3. It can't be so rigid it kills all risk and experimentation, but still needs to teach "trusting the process."
  4. It has to allow for frequent rapid repetition while also being methodical enough to allow for study and contemplation.

What would a good process look like then? "Good" is subjective, but since you're just starting out I propose this process:

  1. Big Block Layout Layout the big blocks for the page, usually 3-7 blocks, or a big "example" block for each element you'll need.
  2. Refine Fake Content Fill in the big blocks with fake text, placeholder images, and other "content" to work out more refined positioning and proportions.
  3. Replace and Refine More Replace the block structure with semantic HTML tags and use CSS to correct placement, improve visuals, and add more details.
  4. Turn the Lights On Finally, add in the color schemes, fonts, images, and real text and then use that to continually refine the details even more. Your goal here is to not only make each element nice, but to make sure it fits with the whole visual experience, aka the "gestalt."

You can usually do step 1 and 2 on each big element of a large UI. For example, a landing page is a long list of big user interfaces. Each section has its own layout and design, so it makes more sense to do steps 1 (big block layout) and 2 (fake content) for each big element, treating them like one "UI." However, if you're doing a single page UI then you would do these steps in order.

You'll see what I mean in the demos in Exercises 9 and 10 when I recreate a landing page using this process, and also in the livestreams I did while figuring the process out.

You might think it's difficult to avoid color until the end, but it turns out color, fonts, and other things really only confuse you when trying to work on visual things. If you wait until the end you'll see this magic thing where you "turn the lights on" and suddenly your boring monochrome page comes to life with just a few CSS variables. But, if it really bothers you to not know the colors then consider collecting them up and keeping them in a "mood board" file for reference as you work.

Getting Practical with blockstart.css

Great, I've talked on and on about high minded ideas like "fill out the big blocks first" and "refine with medium details" but what does that mean in practical CSS and HTML? To help understand this I created blockstart.css which is a very simple tiny CSS file that lets you do stage 1 and 2 of the process. You use blockstart.css like this:

  1. Use <block>, <grid>, and <content> tags to create containers for the "big blocks." Use classes and variables inside style="" to change the configuration of these tags. This means you don't have to work in 2 places at once. You just work this simple HTML.
  2. Fill in these <block> tags with fake text, formatting tags like <h1>, and use <shape> to create image placeholders. As you do this you can adjust the blocks to work with the content and get closer to your desired layout.
  3. Replace each <block> tag with a named tag. If you are working on the hero of a landing page, then you change <block> to <hero>. You then copy that block's settings up to your CSS and start working the CSS to recreate the block. Now you have an HTML and CSS structure you can refine, and you've removed the majority of the blockstart.css content.
  4. "Turn the lights on" by going back through each of these new tags and add in the color, fonts, real text, images, videos, and further refinement. It's at this stage that you could then keep working on this page forever (or until you give up and rewrite it).

Sometimes I'll combine stage 1 and stage 2 if I need things to space out or fill blocks before they work. Otherwise I'll follow this process fairly closely, creating the blocks and slowly building them up with details until they're what I want. The end result of this process isn't so much a "finished work in 4 easy steps" but more of a "get a first rendition you can develop after 4 easy steps."

Reviewing the blockstart.css

To use this process you'll need understand what's in the blockstart.css file, so let's go through the major rules in the blockstart.css file and explain what they're doing before you watch the video demonstrating how to use it.

At the top of the file we have variables that are used to set different values and simple display features. The --value[0-9] are nothing more than simple gray colors in an even distribution of light to dark. This helps you create the page without color.

:root {
  --color-border: hsl(0, 0%, 50%);
  --border-radius: 5px;
  --value0: hsl(0, 0%, 0%);
  --value1: hsl(0, 0%, 11%);
  --value2: hsl(0, 0%, 22%);
  --value3: hsl(0, 0%, 33%);
  --value4: hsl(0, 0%, 44%);
  --value5: hsl(0, 0%, 55%);
  --value6: hsl(0, 0%, 66%);
  --value7: hsl(0, 0%, 77%);
  --value8: hsl(0, 0%, 88%);
  --value9: hsl(0, 0%, 100%);
  --text: 0;
}

The body tag is then set to display flex, it's given a simple text value, and all the padding is removed. This gives a quick reset of the body and makes it easier to work with flex-box later.

body {
  color: hsl(0, 0%, calc(var(--text) * 11%));
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  padding: 0px;
  margin: 0px;
}

A content tag is a simple handy container for those situations where you need to wrap some content but don't want to use a more complex block. It's mostly only set to flex.

content {
  display: flex;
  flex-direction: column;
}

Next we fix links to have no color:

a {
  color: hsl(0, 0%, calc(var(--text) * 11%));
}

Now we are finally at the block tag, the meat of the whole blockstart.css file. This sets the color using a variable, displays flex style, and uses a variable --spacing so you can change the spacing in the block tag. If you want flex-end you just write style="--spacing: flex-end".

block {
  color: hsl(0, 0%, calc(var(--text) * 11%));
  display: flex;
  --spacing: space-evenly;
  justify-content: var(--spacing);
  flex-direction: column;
}

One thing we don't want is a ton of block tags everywhere or else they'll be a pain to replace. This rule says that all of the first children will be set to display flex, plus a few other settings that make them work better inside the block tag. They should stretch to fill the block, have a small margin, use the --text variable like block and body, and flex equally and automatically. This makes it easy to throw any tags inside a block, have them behave like a block, but not require anymore CSS.

block > * {
  color: hsl(0, 0%, calc(var(--text) * 11%));
  display: flex;
  flex: 1 1 auto;
  --spacing: flex-start;
  justify-content: var(--spacing);
  align-self: stretch;
  flex-direction: column;
  margin: 2px;
}

During this initial stage of development you usually want everything to behave like a block, but sometimes you have to switch the tag back to being normal. For example, if you want a button to not expand to fill the block. The no-flex class simply undoes most of the settings from the previous rule.

.no-flex {
  display: block;
  flex: unset;
  flex-direction: unset;
  align-self: unset;
}

Centering things is weirdly too hard in web development, but these three classes will help. You can tag most things with class="center" and it will center itself and its contents...mostly. You still need to add a center-text class if you also want the text centered. If you want a block to center itself, but not center its contents, then use center-self.

.center {
  justify-content: center;
  align-items: center;
  align-self: center;
}

.center-text > * {
  text-align: center;
}

.center-self {
  align-self: center;
}

The default orientation for display: flex is horizontal (row), which is stupid. Everything in the web normally goes vertically by default, and 90% of the contents you'll work with are vertical, so we default to vertical (column). If you want horizontal then use class="horizontal".

.vertical {
  flex-direction: column;
}

.horizontal {
  flex-direction: row;
}

The grid is so useful I may just keep it in my results. Grids don't show up in designs too often, and usually if you tried to remove this grid tag to be "semantic" you'd end up with some other word for a grid. That's why I'm finding just leaving the grid tags there works fine.

grid {
  --cols: 1fr 1fr;
  --rows: auto;
  --gap: 0.5rem;

  color: hsl(0, 0%, calc(var(--text) * 11%));
  display: grid;
  grid-gap: var(--gap);
  grid-template-columns: var(--cols);
  grid-template-rows: var(--rows);
}

There's rare occasions--especially in the final stage when you're introducing images--where you need to "stack" multiple elements. This CSS uses a feature of CSS grids to stack layers more easily than previous methods. If you need to overlay some text on an image than this is your best friend.

stack {
  color: hsl(0, 0%, calc(var(--text) * 11%));
  display: grid;
  grid-template-rows: 1fr;
  grid-template-columns: 1fr;
  grid-template-areas: "cover";
}

stack > * {
  color: hsl(0, 0%, calc(var(--text) * 11%));
  width: 100%;
  height: 100%;
  position: relative;
  grid-area: cover;
}

stack > .top {
  z-index: 1000;
}

Many times you quickly need a spacer to separate elements, so we just use an invisible hr to get it done.

hr {
  --height: 1rem;
  min-height: var(--height);
  visibility: hidden;
}

hr.huge {
  --height: 3rem;
}

Placeholder images are fine, but they take a long time to find, download, and link. This rule makes a simple shape tag that can take a h1 label (or anything) inside and a value. You can use the style="--w: WIDTH; --h: HEIGHT;" variables to set its size, and --value: VALUE; --text: VALUE;" to set its value for background and text. For example, if you want a 300px by 300px square that's black with white text you use style="--w: 300px; --h: 300px; --value: 0; --text: 9".

shape {
  --w: 100%;
  --h: 100%;
  --value: 4;

  color: hsl(0, 0%, calc(var(--text) * 11%));
  background-color: hsl(0, 0%, calc(var(--value) * 11%));
  display: flex;
  width: var(--w);
  min-width: var(--w);
  max-width: var(--w);
  height: var(--h);
  min-height: var(--h);
  max-height: var(--h);
  text-align: center;
  justify-content: center;
  align-items: center;
  align-self: center;
}

It's tough to figure out what is really happening to the blocks, so the debug class will add a red border around the outer block, and then blue borders on the first child blocks. It's very handy.

.debug {
  border: 1px solid red;
}

.debug > * {
  border: 1px solid blue;
}

You always need some quick padding and to set specific sizes of things, so the pad and sized classes do that.

.pad {
  --pad: 1rem;
  padding: var(--pad);
}

.sized {
  --w: 100%;
  --h: 100%;
  width: var(--w);
  min-width: var(--w);
  max-width: var(--w);
  height: var(--h);
  min-height: var(--h);
  max-height: var(--h);
}

Finally, you can set a border with the border class and set a block to be "solid" with the solid class. The solid class uses the typical --value variable to set it's background. If you wanted a black background you'd write class="solid" style="--value: 0".

.border {
  border: 1px solid var(--color-border);
  border-radius: var(--border-radius);
}

.solid {
  --value: 8;
  background-color: hsl(0, 0%, calc(var(--value) * 11%));
}

The Challenge

You have short descriptions of these rules, you know HTML, and you know CSS. Your challenge for this exercise is two tasks:

  1. Study this CSS and make sure you know what everything does. Do you know what's going on in hsl(0, 0%, calc(var(--value) * 11%))? Why am I putting variables inside CSS rules instead of in the :root? If there's something I'm doing that you don't know then study it.
  2. Create your own .html file that demonstrates each of the rules in your own words. You can refer to the blockstart.css docs if you get stuck.
  3. Using the blockstart.css file, take one of the blockstart.css demos and replicate it. You should only do stages 1 and 2.
  4. Take what you've learned and find a different landing page in the real world to replicate. Remember to only do stages 1 and 2.

The Video

The video for this exercise shows me doing the challenge, so only watch it if you are stuck. You should also watch it if you're unclear about the process, then simply pick a different demo to do than the one I do in the video.


More from Learn Code the Hard Way

Exploring the Replacement for C as an Educational Language

My thoughts so far on finding a replacement for C in teaching compiled languages and memory safety.

ResearchPublished Apr 20, 2024

How to Read Programmer Documentation

An excerpt from Learn Python the Hard Way, 5th Edition that explains how I analyze learn from projects with poor or no documentation (which is most of them).

PythonPublished July 29, 2023

The 5 Simple Rules to the Game of Code

An experimental idea to teach the basics of a Turing machine before teaching loops and branching. Feedback welcome.

PythonPublished July 29, 2023

Announcing _Learn Python the Hard Way_'s Next Edition

Announcing the new version of _Learn Python the Hard Way_ which will be entirely focused on Pre-Beginner Data Science and not web development.

AnnouncementPublished May 11, 2023