Table of Contents
First and foremost, I want to say thanks to all of you who send their feedback and questions related to my product development workflow. I did not expect such a reaction at all. Since many of you wanted to know about the structure of HTML, CSS, Sass and JavaScript I use, I decided to write this article as a second part. Here, you will dive deeper into what code structure I use in my workflow along with examples. I hope this part will help you put together your own bulletproof workflow not just for product development, but any project you will work on.
You can read the beginning in part 1.
Missing CSS in my workflow
When it comes to CSS, I don’t have much to say. The reason is that two years ago I learned Sass preprocessor and have been using it since then. So, it has been a long time since I coded some project in regular bare CSS. The last moment I can recall was when I was working on a website refactoring and optimization project for client. The website I was cleaning up was in horrible state. It a catastrophe–HTML files were stuffed with div tags from floor to to ceiling and no, it was not the fifth version of HTML, barely the 4.1.
Let’s get back to CSS, which was not in better condition either. During the work on this project I realized how much I missed Sass and all its abilities. However, some of you were asking me about CSS and preprocessor couple of times and I want to make few things clear. First, learning Sass, at least its basics, is not hard at all. You can learn the fundamentals in less than twenty minutes. When you understand the basic, immerse yourself in deliberate practice and gradually improve your skills by implementing advanced features of Sass.
Second, even though I love Sass and use it every on a daily basis, I don’t want to give you advice on what preprocessor should you use. Currently, there are four biggest preprocessors you can enhance your workflow with. These are Sass, LESS, Stylus and the newest PostCSS. If you want, you can compare the first three. So … You know what? Screw it. Pick Sass.
Answer on the third question is NO. You should not use any preprocessor in your workflow just because someone told you it is cool or trendy. Also, don’t use preprocessors if you have only basic CSS skills. Meaning, if you are a beginner or someone not willing to learn and improve in coding CSS, you have to fully understand it first. Master the fundamental principles of CSS, learn about specificity and modular CSS. Then, if you will be able to write clean CSS, only then you can try to implement some preprocessor into your workflow. Not sooner.
Preprocessors are powerful tools that can either help you or hurt you. Imagine someone would ask you to borrow your car. Does he have a driving license? No, but he knows how to ride a bike without falling. I bet you would think he is crazy. The same thing applies to CSS. If your CSS is a mess and people need you or hours of intense study to understand it, preprocessor will make this mess only bigger. So beginners, hands off preprocessors!
HTML
After a “brief” stop at CSS, let’s switch to HTML and basic structure I use in my workflow for every project. The structure begins with a doctype for HTML5 following html tag with lang attribute and value of “en” (most of my projects are in English) and class “no-js”. I use this class to test if JavaScript is available or not. This test is simple. Just one line of JavaScript–to find this class and remove it from html tag–written in the bottom of the page before the body closing tag.
Head section (element) contains a bit more stuff. As said in the previous article, I always include link and meta tags for favicon, its variations and related files. As a result, the head contains additional eighteen links. Honestly, I never though about counting them, but the number is a bit high. Anyway, as in the body every part in the head is marked with comment to make it easier for client to understand it. Tags coming before favicons are meta for charset, http-equiv, viewport, handheldFriendly, description, author and one empty just for the case.
I almost forgot to mention the title tag. Next on the list are meta tags for Facebook OpenGraph followed by meta tags for Twitter cards. In case of Facebook OpenGraph, there are tags for title, type, description, image, url, locale and site_name. Twitter card part is shorter. It contains tags for card, creator, title and description. See? Full service ensured, including optimization for social media.
Next is part for fonts. Here I put all the stylesheets for external fonts. Because I like to use fonts with open source license, they are in majority of cases loaded from Google Fonts CDN. The last part of head section is dedicated to main stylesheet.
From time to time, there might be one exception when I will add one more part. This is when I want to use Modernizr–library to detect what features are supported in the browser–in some of my projects. This is also the only case I will put any scripts into head section of the page. Well, sometimes I will add analytics too.
Moving to body element … I am used to wrap up the whole page into a div tag with class “wrapper”, so this is a direct child body. Every piece of code and content of the website then goes into this div element. Just before closing tag of this div, sometimes body, I will put tags for scripts. In every project, when I use jQuery library, there is a tag with link to CDN to load the latest version and also short script to check whether jQuery object is available. If not (CDN is not available, or I am offline), jQuery is loaded from local folder.
Right after jQuery, if it is used, is my little JavaScript checker and a tag for file with external “custom” scripts written by me. The last script is for Google Analytics so client can track every metrics he needs right after uploading the website on the hosting. This is all when it comes to my workflow and HTML.
The bare HTML code I start every page with looks something like this:
<!DOCTYPE html>
<html lang="en" class="no-js">
<head>
<meta charset="UTF-8">
<title></title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="handheldFriendly" content="true">
<meta name="" content="">
<meta name="description" content="">
<meta name="Author" content="Alex Devero">
<!-- Favicons -->
<link rel="apple-touch-icon" sizes="57x57" href="apple-touch-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="apple-touch-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="apple-touch-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="apple-touch-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="apple-touch-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="apple-touch-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="apple-touch-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="apple-touch-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon-180x180.png">
<link rel="icon" type="image/png" href="favicon-32x32.png" sizes="32x32">
<link rel="icon" type="image/png" href="favicon-194x194.png" sizes="194x194">
<link rel="icon" type="image/png" href="favicon-96x96.png" sizes="96x96">
<link rel="icon" type="image/png" href="android-chrome-192x192.png" sizes="192x192">
<link rel="icon" type="image/png" href="favicon-16x16.png" sizes="16x16">
<link rel="manifest" href="manifest.json">
<meta name="msapplication-TileColor" content="#fffff">
<meta name="msapplication-TileImage" content="mstile-144x144.png">
<meta name="theme-color" content="#ffffff">
<!-- Facebook OpenGraph tags -->
<meta property="og:title" content="">
<!-- Title of the website -->
<meta property="og:type" content="website">
<!-- Type of the Facebook OpenGraph tag -->
<meta property="og:description" content="">
<!-- Description of the website -->
<meta property="og:image" content="">
<!-- Your photo -->
<meta property="og:url" content="">
<!-- URL of website -->
<meta property="og:locale" content="en_US">
<!-- Default language -->
<meta property="og:site_name" content="">
<!-- Name of the website -->
<!-- Twitter cards tags -->
<meta name="twitter:card" content="summary">
<!-- Type of Twitter card -->
<meta name="twitter:creator" content="">
<!-- Your Twitter handler -->
<meta name="twitter:title" content="">
<!-- Title of the website -->
<meta name="twitter:description" content="">
<!-- Description of the website -->
<!-- Stylesheets -->
<link rel="stylesheet" href="styles/styles.css">
<!-- Master stylesheet -->
</head>
<body>
<div class="wrapper">
<!-- Scripts -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
window.jQuery ||
document.write('<script src="js/vendor/jquery-1.11.3.min.js"></script>');
</script>
<script>
(function() {
///
// JavaScript checker
///
document.getElementsByClassName("no-js")[0].classList.remove("no-js");
})();
</script>
<!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
<script>
(function(b, o, i, l, e, r) {
b.GoogleAnalyticsObject = l;
b[l] ||
(b[l] = function() {
(b[l].q = b[l].q || []).push(arguments);
});
b[l].l = +new Date();
e = o.createElement(i);
r = o.getElementsByTagName(i)[0];
e.src = "https://www.google-analytics.com/analytics.js";
r.parentNode.insertBefore(e, r);
})(window, document, "script", "ga");
ga("create", "UA-XXXXX-X", "auto");
ga("send", "pageview");
</script>
</div>
</body>
</html>
Sass
My Sass workflow is a little bit more complicated. In all projects, I will always use several sass files–mostly twelve–that will be, in the end, imported into the main file. This main file is then processed to CSS either via command line or build system I wrote for Sublime Text 3 (beta) editor I use at work. Every Sass file, except the main, is dedicated to specific layer of the project. Meaning, the CSS for the project is divided into layers according to specific conditions.
The main layers are base, layout, modules, settings and tools. Base layer contains the basic settings–all styles applied to element selectors. There are no classes. Actually, this layer is in three versions–base, base.reset and base.fonts. Base, without suffix, will contain typography settings for heading, paragraphs and other styling. Remember, base files have lowest specificity, so no are classes allowed here.
Example of base file:
html,
body {
width: 100%;
height: 100%;
}
html {
font-size: 1rem;
-ms-touch-action: manipulation;
touch-action: manipulation;
}
body {
font-family: $font--merriweather;
font-weight: 400;
line-height: 1.45;
color: $color--black-default;
background-color: #fff;
}
a {
text-decoration: none;
@include transition(color);
}
h1,
h2,
h3 {
font-weight: inherit;
line-height: 1.2;
}
h1 {
font-size: 1.823rem;
}
h2 {
font-size: 1.15rem;
}
h3 {
font-size: 0.875rem;
}
Base.reset is for what the name suggests–customized reset stylesheet created by Eric Meyer. For those of you who don’t know what reset stylesheet does … It resets the styling of HTML elements to reduce browser inconsistencies. These styles include line heights, margins, padding and font sizes. In other words, it makes specific elements look the same across the different browser agents. With this, your wokflow is faster because you don’t have to care about these details like you would otherwise.
Example of customized base.reset file:
html,
body,
div,
span,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
em,
img,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
menu,
nav,
output,
section,
summary,
time,
audio,
video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section {
display: block;
}
body {
line-height: 1;
}
ol,
ul {
list-style: none;
}
blockquote,
q {
quotes: none;
}
blockquote:before,
blockquote:after,
q:before,
q:after {
content: "";
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
The last base file, base.fonts, is kind of a backup plan. It contains @font-face rules to import fonts from local folder in case I don’t have access to CDN. This file is normally commented out to prevent compiler from importing it into main stylesheet.
Next are files for layout layer–layout.global, layout.grid and layout.print. Layout layer is one level higher in specificity and so it contains styling applied via class selectors. layout.global is for case I will need to customize style of some element without creating new module for it. Layout.grid is dedicated to grid system used in layout. Right now, I’m using customized Skeleton CSS Boilerplate. The last file, layout.print, is basically a print stylesheet.
Some people following SMACSS architecture and similar approaches are using layout layer for modules. In my workflow, I like to use separate file called modules to handle all things related to modules. Following the modular CSS approach, the majority of work takes place in modules file.
The last two remaining Sass files are tools–tools.functions (Sass functions and directives), tools.mixins and tools.placeholders (placeholder selectors)–and settings–settings.colors for color variables and setting.global the rest of variables like timing for animations and transitions, margins, font sizes and so on. These files are strictly for Sass. If you are using plain CSS, all you need to know are the base, layout and modules files.
On top of this architecture is the main Sass file where I import all the files mentioned above in specific order to prevent breaking the CSS because some variable is not found. The order is following … First are settings followed by tools, base, layout and finally modules. With this, Sass workflow is complete.
Example of main Sass file:
@import '_settings.global';
@import '_settings.colors';
@import '_tools.mixins';
@import '_tools.placeholders';
@import '_tools.functions';
@import '_base.reset';
@import '_base';
//@import '_base.fonts';
@import '_layout.grid';
@import '_layout.print';
@import '_layout.global';
@import '_modules';
JavaScript
This part about JavaScript workflow is gonna be very short because as a default my file for external scripts is empty. I don’t use any scripts on a daily basis or in every project. My philosophy is that, every line of JavaScript must convey some specific function. You can use your decorative skills elsewhere without wasting bandwidth and resources.
Closing thoughts on product development and my workflow
That’s it. Now you know all the secrets of my product or project development workflow. I have to admit that some steps in my workflow are a bit more complex or complicated (Sass) than others. One advice I want you to leave you with today is to take the information in this article and use them as you want. Don’t take it as whole. Use what do you like, implement it into your workflow and remove the rest. Customize as you want to suit it your needs, style and work.
If you liked this article, please subscribe so you don't miss any future post.
If you'd like to support me and this blog, you can become a patron, or you can buy me a coffee 🙂