HTML and CSS Basics, part 18: Build your own micro CSS framework

Building a custom CSS micro-framewrok

By: Ajdin Imsirovic 24 September 2019

This is the 18th post in this series of articles.

In this article, we’ll build our own micro CSS framework.

Initially, I thought about adding a complete set of instructions on both how to build each part of our micro framework in SCSS, including steps onhow to compile it, but I realized that it might be too difficult for a beginner-level tutorial.

So instead I decided to keep the tutorial more beginner-friendly.

Before we begin building our CSS micro-framework, we need to think about the structure of what we’d like to build.

The structure of our CSS micro-framework

Here are the different sections that our CSS micro-framework needs to have:

  1. A CSS reset
  2. Simple layout classes to use
  3. Widths, heights, margins, and paddings
  4. Typography
  5. Effects (such as colors, shadows, or opacity)
  6. Column-grid

Why separate this CSS structure like above?

There’s no empirical, scientific proof that the above code structure is the best there is for a CSS micro-framework.

But from experience, I find it a nice way to organize my code and think about it.

1. A CSS reset

Let’s now think about each of these sections a bit more in depth. We’ll skip the CSS reset section, because we’ve already covered it in part 14 of this article series.

2. Layout classes

In this part of our micro-framework, we need to group CSS properties that deal with:

  1. Display (block, inline, inline-block, flex, grid)
  2. Floats and clears (a subject which we already covered here)
  3. Position (static, relative, absolute, fixed - which we talked about in part 7 and part 8 of this article series)
  4. Top, right, bottom, left properties, which are closely related to positioning
  5. Z-index (CSS stacking order)
  6. Flexbox properties:
    • Flex parent properties (flex-direction, flex-wrap, justify-content, align-items, align-content)
    • Flex children properties (order, flex-grow, flex-basis, align-self)
  7. overflow properties

As we can see, there is a lot of CSS related to layouts!

Of course, adding all of this functionality, as listed above, would make our framework a lot larger than what we’re aiming for: a helpful CSS micro-framework.

Thus, this leaves us with 3 options:

  1. We completely remove certain parts of the layout-related CSS properties from our micro-framework
  2. We cover each of these cases, but we severely limit them in scope
  3. A combination of the above 2 approaches

Ultimately, it boils down to this: what are the most-often used CSS properties, out of all those we listed above?

This is the code that I came up with as the answer:

/* 1. Display */
.display-block { display: block }
.display-inline { display: inline }
.display-inline-block { display: inline-block }
.display-flex { display: flex}
.flex-direction-column {
    /* browser defaults to flex-direction: row */
    flex-direction: column
}
/* 2. Floats and clears */
.float-left { float: left }
.float-right { float: right }
.clear-both { clear: both }

/* 3. Position */
.position-static { position: static }
.position-relative { position: relative }
.position-absolute { position: absolute }
.position-fixed { position: fixed }

/* 4. **Top, right, bottom, left** */
.top0 { top: 0 }
.top1 { top: 10px }
.bottom0 { bottom: 0 }
.bottom2 { bottom: 20px }
/*
Extend this as needed...
.leftX, .rightX, etc...
*/

/* We're skipping the rest */
/* 5.  **Z-index** */
/* 6. */
/* 7. */

3. Widths, heights, margins, and paddings

To keep widths, heights, margins, and paddings simple, we can add only the bare useful minimum:

/* widths */
.w25p { width: 25% }
.w33p { width: 33.33% }
.w50p { width: 50% }
.w75p { width: 75% }
.w100p { width: 100% }

/* heights */
.h25vh { height: 25vh }
.h33vh { height: 33.33vh }
.h50vh { height: 50vh }
.h75vh { height: 75vh }
.h100vh { height: 100vh }

.m10 { margin: 10px }
.m20 { margin: 20px }
.pt10 { padding-top: 10px }
.pr10 { padding-right: 10px }
.pb10 { padding-bottom: 10px }
.pl10 { padding-left: 10px }

.p0 { padding: 0}
.m0 { margin: 0}

Why did we choose this minimum number of CSS code above, and not something else?

Here is the reasoning behind the above code:

  1. Percentage-based widths will allow us to quickly set a width on a child element, based on the width of the parent element; for example, if a parent is 100 pixels wide, and we use the w50p class on the child, the child element will be 50 pixels wide.
  2. There are many situations where you’d want an element to extend the complete height of the viewport, i.e be 100vh tall. The vh unit of measure is short for “viewport height”.
  3. If your website design involves lots of elements with similar margins and padding, using a class like m10 or p0 might make sense. Here we can also see a variation on the m10 idea with pt10, pr10, pb10, and pl10 classes.

This is a good time to discuss naming conventions too.

If a class doesn’t have a *unit of measure after it, it means it’s a pixel value. If a p letter follows it, it’s a percentage value (contrast, for example, w25p and m10).

4. Typography

Typography can be made quite complex. Here are the very basics:

/* quick font-family */
.arial { font-family: Arial, sans-serif }
.georgia { font-family: Georgia, sans-serif }

/* font sizes */
.fs20 { font-size: 20px }
.fs30 { font-size: 30px }

/* font weights and decorations */
.font-weight-bold { font-weight: bold }

/* line height presets */
.line-height1 { line-height: 1 }
.line-height2 { line-height: 2 }

5. Effects (such as colors, shadows, or opacity)

For effects, we’ll just add the very basics. Feel free to extend them later.

.bg-tomato { background: tomato }
.bg-olive { background: olive }
.bg-plum { background: plum }
.bg-wheat { background: wheat }

.color-tomato { color: tomato }
.color-olive { color: olive }
.color-plum { color: plum }
.color-wheat { color: wheat }

.shadow0 { box-shadow: none }
.shadow1 { box-shadow: 5px 5px 0 0px rgba(0, 0, 0, 0.4) }
.shadow2 { box-shadow: 5px 5px 5px 0px rgba(0, 0, 0, 0.4) }

.opacity0 { opacity: 0 }
.opacity1 { opacity: 1 }
.opacity05 { opacity: 0.5 }

6. Column-grid

As far as the column grid goes, we’ll use the float-based on we built earlier on, in part 15 of this series.

The only difference is, we’re removing the coloring from the original column grid we built in part 15. To make it easier to compare, we’ve just commented out the coloring code.

.container {
    max-width: 1200px;
    width: 100%;
    margin: 0 auto;
}
.wrapper {
    /* background: silver;*/
    width: calc(100% - 20px);
    margin: 10px;
    min-height: 50px;
    overflow: auto;
    clear: both;
}
/* 1/12 = 0.0833 */
@media (max-width: 799px) {
    .smcol1 { width: calc(8.33% - 2%) }
    .smcol2 { width: calc(16.66% - 2%) }
    .smcol3 { width: calc(24.99% - 2%) }
    .smcol4 { width: calc(33.32% - 2%) }
    .smcol5 { width: calc(41.65% - 2%) }
    .smcol6 { width: calc(49.98% - 2%) }
    .smcol7 { width: calc(58.31% - 2%) }
    .smcol8 { width: calc(66.64% - 2%) }
    .smcol9 { width: calc(74.97% - 2%) }
    .smcol10 { width: calc(83.33% - 2%) }
    .smcol11 { width: calc(91.63% - 2%) }
    .smcol12 { width: calc(100% - 2%) }

    .smcol1,
    .smcol2,
    .smcol3,
    .smcol4,
    .smcol5,
    .smcol6,
    .smcol7,
    .smcol8,
    .smcol9,
    .smcol10,
    .smcol11,
    .smcol12 {
        /*background: yellowgreen;*/
        min-height: 50px;
        display: block;
        margin: 10px 1%;
        /*outline: 1px solid black;*/
        float: left;
    }
}

@media (min-width: 800px) {
    .lgcol1 { width: calc(8.33% - 2%) }
    .lgcol2 { width: calc(16.66% - 2%) }
    .lgcol3 { width: calc(24.99% - 2%) }
    .lgcol4 { width: calc(33.32% - 2%) }
    .lgcol5 { width: calc(41.65% - 2%) }
    .lgcol6 { width: calc(49.98% - 2%) }
    .lgcol7 { width: calc(58.31% - 2%) }
    .lgcol8 { width: calc(66.64% - 2%) }
    .lgcol9 { width: calc(74.97% - 2%) }
    .lgcol10 { width: calc(83.33% - 2%) }
    .lgcol11 { width: calc(91.63% - 2%) }
    .lgcol12 { width: calc(100% - 2%) }

    .lgcol1,
    .lgcol2,
    .lgcol3,
    .lgcol4,
    .lgcol5,
    .lgcol6,
    .lgcol7,
    .lgcol8,
    .lgcol9,
    .lgcol10,
    .lgcol11,
    .lgcol12 {
        /*background: lightsalmon;*/
        min-height: 50px;
        display: block;
        margin: 10px 1%;
        /*outline: 1px solid black;*/
        float: left;
    }
}

That’s it, we’ve got our custom, complete CSS micro-framework!

To wrap up this article, let’s have a look at this codelab, showcasing a few divs styled using it.

Feel free to open up your browser’s developer tools and add and remove classes so that you can see how they affect the codelab layout above.

Use the below links to navigate through other tutorials in this guide.

< Back to part 17: Introduction to SCSS

You are here: Part 18, Build your own micro CSS framework

Continue to part 19: Building a layout with our micro CSS framework >

Feel free to check out my work here: